-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Truncate synthetic column names during join pushdown if needed
In some operations (`applyAggregation` and `applyJoin`) synthetic columns are generated which get pushed down as projections into the remote database. It's possible for the generated column names to exceed the valid identifier length supported by the remote database leading to query failures or silent truncation of column name leading to unpredictable behaviour. For example on Oracle such a failure manifests as: ORA-00972: identifier is too long This change truncates the synthetic column names to always be smaller than the limit for Oracle. Also note that this change just fixes the `applyJoin` path since that's the one where the issue was observed. In future the limit will be allowed to vary according to database being used instead of hardcoded to the value for Oracle.
- Loading branch information
1 parent
3ec5767
commit 5e520fc
Showing
12 changed files
with
202 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/SyntheticColumnHandleBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.trino.plugin.jdbc; | ||
|
||
import static com.google.common.base.Splitter.fixedLength; | ||
import static com.google.common.base.Verify.verify; | ||
|
||
public class SyntheticColumnHandleBuilder | ||
{ | ||
public static final int DEFAULT_COLUMN_ALIAS_LENGTH = 30; | ||
|
||
public JdbcColumnHandle get(JdbcColumnHandle column, int nextSyntheticColumnId) | ||
{ | ||
verify(nextSyntheticColumnId >= 0, "nextSyntheticColumnId rolled over and is not monotonically increasing any more"); | ||
|
||
int sequentialNumberLength = String.valueOf(nextSyntheticColumnId).length(); | ||
int originalColumnNameLength = DEFAULT_COLUMN_ALIAS_LENGTH - sequentialNumberLength - "_".length(); | ||
|
||
String columnNameTruncated = fixedLength(originalColumnNameLength) | ||
.split(column.getColumnName()) | ||
.iterator() | ||
.next(); | ||
String columnName = columnNameTruncated + "_" + nextSyntheticColumnId; | ||
return JdbcColumnHandle.builderFrom(column) | ||
.setColumnName(columnName) | ||
.build(); | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
...rino-base-jdbc/src/main/java/io/trino/plugin/jdbc/SyntheticColumnHandleBuilderModule.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.trino.plugin.jdbc; | ||
|
||
import com.google.inject.AbstractModule; | ||
import com.google.inject.Singleton; | ||
|
||
public class SyntheticColumnHandleBuilderModule | ||
extends AbstractModule | ||
{ | ||
@Override | ||
public void configure() | ||
{ | ||
bind(SyntheticColumnHandleBuilder.class).in(Singleton.class); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
.../trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestSyntheticColumnHandleBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.trino.plugin.jdbc; | ||
|
||
import com.google.common.base.VerifyException; | ||
import org.testng.annotations.DataProvider; | ||
import org.testng.annotations.Test; | ||
|
||
import static io.trino.plugin.jdbc.TestingJdbcTypeHandle.JDBC_VARCHAR; | ||
import static io.trino.spi.type.VarcharType.VARCHAR; | ||
import static java.lang.Integer.MAX_VALUE; | ||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||
|
||
public class TestSyntheticColumnHandleBuilder | ||
{ | ||
private final SyntheticColumnHandleBuilder syntheticColumnHandleBuilder = new SyntheticColumnHandleBuilder(); | ||
|
||
@DataProvider(name = "columns") | ||
public static Object[][] testData() | ||
{ | ||
return new Object[][] { | ||
{"column_0", 999, "column_0_999"}, | ||
{"column_with_over_twenty_characters", 100, "column_with_over_twenty_ch_100"}, | ||
{"column_with_over_twenty_characters", MAX_VALUE, "column_with_over_tw_2147483647"} | ||
}; | ||
} | ||
|
||
@Test(dataProvider = "columns") | ||
public void testColumnAliasTruncation(String columnName, int nextSynthenticId, String expectedSyntheticColumnName) | ||
{ | ||
JdbcColumnHandle column = getDefaultColumnHandleBuilder() | ||
.setColumnName(columnName) | ||
.build(); | ||
|
||
JdbcColumnHandle result = syntheticColumnHandleBuilder.get(column, nextSynthenticId); | ||
|
||
assertThat(result.getColumnName()).isEqualTo(expectedSyntheticColumnName); | ||
} | ||
|
||
@Test | ||
public void testNegativeSyntheticId() | ||
{ | ||
JdbcColumnHandle column = getDefaultColumnHandleBuilder() | ||
.setColumnName("column_0") | ||
.build(); | ||
|
||
assertThatThrownBy(() -> syntheticColumnHandleBuilder.get(column, -2147483648)).isInstanceOf(VerifyException.class); | ||
} | ||
|
||
private static JdbcColumnHandle.Builder getDefaultColumnHandleBuilder() | ||
{ | ||
return JdbcColumnHandle.builder() | ||
.setJdbcTypeHandle(JDBC_VARCHAR) | ||
.setColumnType(VARCHAR); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters