diff --git a/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/BaseJdbcClient.java b/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/BaseJdbcClient.java index a53f6651b8a3..a8150d624563 100644 --- a/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/BaseJdbcClient.java +++ b/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/BaseJdbcClient.java @@ -114,6 +114,7 @@ public abstract class BaseJdbcClient private final IdentifierMapping identifierMapping; private final boolean supportsRetries; private final JdbcRemoteIdentifiersFactory jdbcRemoteIdentifiersFactory = new JdbcRemoteIdentifiersFactory(this); + private Integer maxColumnNameLength; public BaseJdbcClient( String identifierQuote, @@ -1435,6 +1436,26 @@ public OptionalInt getMaxWriteParallelism(ConnectorSession session) return OptionalInt.of(getWriteParallelism(session)); } + protected OptionalInt getMaxColumnNameLengthFromDatabaseMetaData(ConnectorSession session) + { + if (maxColumnNameLength != null) { + // According to JavaDoc of DatabaseMetaData#getMaxColumnNameLength a value of 0 signifies that the limit is unknown + if (maxColumnNameLength == 0) { + return OptionalInt.empty(); + } + + return OptionalInt.of(maxColumnNameLength); + } + + try (Connection connection = connectionFactory.openConnection(session)) { + maxColumnNameLength = connection.getMetaData().getMaxColumnNameLength(); + return OptionalInt.of(maxColumnNameLength); + } + catch (SQLException e) { + throw new TrinoException(JDBC_ERROR, e); + } + } + protected void verifySchemaName(DatabaseMetaData databaseMetadata, String schemaName) throws SQLException { diff --git a/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/CachingJdbcClient.java b/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/CachingJdbcClient.java index 1a2ed089609f..032d9895ca1b 100644 --- a/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/CachingJdbcClient.java +++ b/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/CachingJdbcClient.java @@ -560,6 +560,12 @@ public OptionalInt getMaxWriteParallelism(ConnectorSession session) return delegate.getMaxWriteParallelism(session); } + @Override + public OptionalInt getMaxColumnNameLength(ConnectorSession session) + { + return delegate.getMaxColumnNameLength(session); + } + public void onDataChanged(SchemaTableName table) { invalidateAllIf(statisticsCache, key -> key.mayReference(table)); diff --git a/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/DefaultJdbcMetadata.java b/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/DefaultJdbcMetadata.java index 13c2e7f75fd8..cee54f86096c 100644 --- a/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/DefaultJdbcMetadata.java +++ b/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/DefaultJdbcMetadata.java @@ -107,8 +107,6 @@ public class DefaultJdbcMetadata implements JdbcMetadata { - public static final int DEFAULT_COLUMN_ALIAS_LENGTH = 30; - private static final String SYNTHETIC_COLUMN_NAME_PREFIX = "_pfgnrtd_"; private static final String DELETE_ROW_ID = "_trino_artificial_column_handle_for_delete_row_id_"; private static final String MERGE_ROW_ID = "$merge_row_id"; @@ -391,19 +389,13 @@ public Optional> applyAggrega return Optional.empty(); } - String columnName = SYNTHETIC_COLUMN_NAME_PREFIX + nextSyntheticColumnId; + JdbcColumnHandle newColumn = createSyntheticAggregationColumn(aggregate, expression.get().getJdbcTypeHandle(), nextSyntheticColumnId); nextSyntheticColumnId++; - JdbcColumnHandle newColumn = JdbcColumnHandle.builder() - .setColumnName(columnName) - .setJdbcTypeHandle(expression.get().getJdbcTypeHandle()) - .setColumnType(aggregate.getOutputType()) - .setComment(Optional.of("synthetic")) - .build(); newColumns.add(newColumn); projections.add(new Variable(newColumn.getColumnName(), aggregate.getOutputType())); resultAssignments.add(new Assignment(newColumn.getColumnName(), newColumn, aggregate.getOutputType())); - expressions.put(columnName, new ParameterizedExpression(expression.get().getExpression(), expression.get().getParameters())); + expressions.put(newColumn.getColumnName(), new ParameterizedExpression(expression.get().getExpression(), expression.get().getParameters())); } List newColumnsList = newColumns.build(); @@ -431,6 +423,19 @@ public Optional> applyAggrega return Optional.of(new AggregationApplicationResult<>(handle, projections.build(), resultAssignments.build(), ImmutableMap.of(), precalculateStatisticsForPushdown)); } + @VisibleForTesting + static JdbcColumnHandle createSyntheticAggregationColumn(AggregateFunction aggregate, JdbcTypeHandle typeHandle, int nextSyntheticColumnId) + { + // the new column can be max len(SYNTHETIC_COLUMN_NAME_PREFIX) + len(Integer.MAX_VALUE) = 9 + 10 = 19 characters which is small enough to be supported by all databases + String columnName = SYNTHETIC_COLUMN_NAME_PREFIX + nextSyntheticColumnId; + return JdbcColumnHandle.builder() + .setColumnName(columnName) + .setJdbcTypeHandle(typeHandle) + .setColumnType(aggregate.getOutputType()) + .setComment(Optional.of("synthetic")) + .build(); + } + @Override public Optional> applyJoin( ConnectorSession session, @@ -459,15 +464,16 @@ public Optional> applyJoin( int nextSyntheticColumnId = max(leftHandle.getNextSyntheticColumnId(), rightHandle.getNextSyntheticColumnId()); ImmutableMap.Builder newLeftColumnsBuilder = ImmutableMap.builder(); + OptionalInt maxColumnNameLength = jdbcClient.getMaxColumnNameLength(session); for (JdbcColumnHandle column : jdbcClient.getColumns(session, leftHandle)) { - newLeftColumnsBuilder.put(column, createSyntheticColumn(column, nextSyntheticColumnId)); + newLeftColumnsBuilder.put(column, createSyntheticJoinProjectionColumn(column, nextSyntheticColumnId, maxColumnNameLength)); nextSyntheticColumnId++; } Map newLeftColumns = newLeftColumnsBuilder.buildOrThrow(); ImmutableMap.Builder newRightColumnsBuilder = ImmutableMap.builder(); for (JdbcColumnHandle column : jdbcClient.getColumns(session, rightHandle)) { - newRightColumnsBuilder.put(column, createSyntheticColumn(column, nextSyntheticColumnId)); + newRightColumnsBuilder.put(column, createSyntheticJoinProjectionColumn(column, nextSyntheticColumnId, maxColumnNameLength)); nextSyntheticColumnId++; } Map newRightColumns = newRightColumnsBuilder.buildOrThrow(); @@ -525,20 +531,40 @@ public Optional> applyJoin( } @VisibleForTesting - static JdbcColumnHandle createSyntheticColumn(JdbcColumnHandle column, int nextSyntheticColumnId) + static JdbcColumnHandle createSyntheticJoinProjectionColumn(JdbcColumnHandle column, int nextSyntheticColumnId, OptionalInt optionalMaxColumnNameLength) { 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(); + final String separator = "_"; + if (optionalMaxColumnNameLength.isEmpty()) { + return JdbcColumnHandle.builderFrom(column) + .setColumnName(column.getColumnName() + separator + nextSyntheticColumnId) + .build(); + } + + int maxColumnNameLength = optionalMaxColumnNameLength.getAsInt(); + int nextSyntheticColumnIdLength = String.valueOf(nextSyntheticColumnId).length(); + verify(maxColumnNameLength >= nextSyntheticColumnIdLength, "Maximum allowed column name length is %s but next synthetic id has length %s", maxColumnNameLength, nextSyntheticColumnIdLength); + + if (nextSyntheticColumnIdLength == maxColumnNameLength) { + return JdbcColumnHandle.builderFrom(column) + .setColumnName(String.valueOf(nextSyntheticColumnId)) + .build(); + } - String columnNameTruncated = fixedLength(originalColumnNameLength) + if (nextSyntheticColumnIdLength + separator.length() == maxColumnNameLength) { + return JdbcColumnHandle.builderFrom(column) + .setColumnName(separator + nextSyntheticColumnId) + .build(); + } + + // fixedLength only accepts values > 0, so the cases where the value would be <= 0 are handled above explicitly + String truncatedColumnName = fixedLength(maxColumnNameLength - separator.length() - nextSyntheticColumnIdLength) .split(column.getColumnName()) .iterator() .next(); - String columnName = columnNameTruncated + "_" + nextSyntheticColumnId; return JdbcColumnHandle.builderFrom(column) - .setColumnName(columnName) + .setColumnName(truncatedColumnName + separator + nextSyntheticColumnId) .build(); } diff --git a/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/ForwardingJdbcClient.java b/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/ForwardingJdbcClient.java index 0e70ec7beb94..2f784634a44b 100644 --- a/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/ForwardingJdbcClient.java +++ b/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/ForwardingJdbcClient.java @@ -450,4 +450,10 @@ public OptionalInt getMaxWriteParallelism(ConnectorSession session) { return delegate().getMaxWriteParallelism(session); } + + @Override + public OptionalInt getMaxColumnNameLength(ConnectorSession session) + { + return delegate().getMaxColumnNameLength(session); + } } diff --git a/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/JdbcClient.java b/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/JdbcClient.java index 9cb1e5ed7b43..38e6f7e80114 100644 --- a/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/JdbcClient.java +++ b/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/JdbcClient.java @@ -239,4 +239,9 @@ default Optional getTableScanRedirection(Con OptionalLong update(ConnectorSession session, JdbcTableHandle handle); OptionalInt getMaxWriteParallelism(ConnectorSession session); + + default OptionalInt getMaxColumnNameLength(ConnectorSession session) + { + return OptionalInt.empty(); + } } diff --git a/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/jmx/StatisticsAwareJdbcClient.java b/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/jmx/StatisticsAwareJdbcClient.java index ae1e01d029e9..d07bcfa5178c 100644 --- a/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/jmx/StatisticsAwareJdbcClient.java +++ b/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/jmx/StatisticsAwareJdbcClient.java @@ -470,4 +470,10 @@ public OptionalInt getMaxWriteParallelism(ConnectorSession session) { return delegate().getMaxWriteParallelism(session); } + + @Override + public OptionalInt getMaxColumnNameLength(ConnectorSession session) + { + return delegate().getMaxColumnNameLength(session); + } } diff --git a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/BaseJdbcConnectorTest.java b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/BaseJdbcConnectorTest.java index 4c1f14eacdb0..e2ea22c7d46a 100644 --- a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/BaseJdbcConnectorTest.java +++ b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/BaseJdbcConnectorTest.java @@ -2041,6 +2041,26 @@ protected TestTable simpleTable() return new TestTable(onRemoteDatabase(), format("%s.simple_table", getSession().getSchema().orElseThrow()), "(col BIGINT)", ImmutableList.of("1", "2")); } + @Test + public void testJoinPushdownWithLongIdentifiers() + { + skipTestUnless(hasBehavior(SUPPORTS_CREATE_TABLE) && hasBehavior(SUPPORTS_JOIN_PUSHDOWN)); + + String baseColumnName = "col"; + int maxLength = maxColumnNameLength() + // Assume 2^16 is enough for most use cases. Add a bit more to ensure 2^16 isn't actual limit. + .orElse(65536 + 5); + + String validColumnName = baseColumnName + "z".repeat(maxLength - baseColumnName.length()); + try (TestTable left = new TestTable(getQueryRunner()::execute, "test_long_id_l", format("(%s BIGINT)", validColumnName)); + TestTable right = new TestTable(getQueryRunner()::execute, "test_long_id_r", format("(%s BIGINT)", validColumnName))) { + assertThat(query(joinPushdownEnabled(getSession()), """ + SELECT l.%1$s, r.%1$s + FROM %2$s l JOIN %3$s r ON l.%1$s = r.%1$s""".formatted(validColumnName, left.getName(), right.getName()))) + .isFullyPushedDown(); + } + } + @Test public void testDynamicFiltering() { diff --git a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestDefaultJdbcMetadata.java b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestDefaultJdbcMetadata.java index 81b09fba8f79..971049d827dc 100644 --- a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestDefaultJdbcMetadata.java +++ b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestDefaultJdbcMetadata.java @@ -41,10 +41,12 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.OptionalInt; import java.util.function.Function; import static io.airlift.slice.Slices.utf8Slice; -import static io.trino.plugin.jdbc.DefaultJdbcMetadata.createSyntheticColumn; +import static io.trino.plugin.jdbc.DefaultJdbcMetadata.createSyntheticAggregationColumn; +import static io.trino.plugin.jdbc.DefaultJdbcMetadata.createSyntheticJoinProjectionColumn; import static io.trino.plugin.jdbc.TestingJdbcTypeHandle.JDBC_BIGINT; import static io.trino.plugin.jdbc.TestingJdbcTypeHandle.JDBC_VARCHAR; import static io.trino.spi.StandardErrorCode.NOT_FOUND; @@ -402,20 +404,47 @@ public void testMultiGroupKeyPredicatePushdown() @Test public void testColumnAliasTruncation() { - assertThat(createSyntheticColumn(column("column_0"), 999).getColumnName()) - .isEqualTo("column_0_999"); - assertThat(createSyntheticColumn(column("column_with_over_twenty_characters"), 100).getColumnName()) - .isEqualTo("column_with_over_twenty_ch_100"); - assertThat(createSyntheticColumn(column("column_with_over_twenty_characters"), Integer.MAX_VALUE).getColumnName()) - .isEqualTo("column_with_over_tw_2147483647"); + OptionalInt maxLength = OptionalInt.of(30); + assertThat(createSyntheticJoinProjectionColumn(column("no_truncation"), 123, maxLength).getColumnName()) + .isEqualTo("no_truncation_123"); + assertThat(createSyntheticJoinProjectionColumn(column("long_column_name_gets_truncated"), 123, maxLength).getColumnName()) + .isEqualTo("long_column_name_gets_trun_123"); + assertThat(createSyntheticJoinProjectionColumn(column("long_id_causes_truncation"), Integer.MAX_VALUE, maxLength).getColumnName()) + .isEqualTo("long_id_causes_trun_2147483647"); + + assertThat(createSyntheticJoinProjectionColumn(column("id_equals_max_length"), 1234, OptionalInt.of(4)).getColumnName()) + .isEqualTo("1234"); + assertThat(createSyntheticJoinProjectionColumn(column("id_and_separator_equals_max_length"), 1234, OptionalInt.of(5)).getColumnName()) + .isEqualTo("_1234"); + } + + @Test + public void testSyntheticIdExceedsLength() + { + assertThatThrownBy(() -> createSyntheticJoinProjectionColumn(column("id_exceeds_max_length"), 1234, OptionalInt.of(3))) + .isInstanceOf(VerifyException.class) + .hasMessage("Maximum allowed column name length is 3 but next synthetic id has length 4"); } @Test public void testNegativeSyntheticId() { - JdbcColumnHandle column = column("column_0"); + //noinspection NumericOverflow + assertThatThrownBy(() -> createSyntheticJoinProjectionColumn(column("negative_id"), Integer.MAX_VALUE + 1, OptionalInt.of(30))) + .isInstanceOf(VerifyException.class) + .hasMessage("nextSyntheticColumnId rolled over and is not monotonically increasing any more"); + } - assertThatThrownBy(() -> createSyntheticColumn(column, -2147483648)).isInstanceOf(VerifyException.class); + @Test + public void testAggregationColumnAliasMaxLength() + { + // this test is to ensure that the generated names for aggregation pushdown are short enough to be supported by all databases. + // Oracle has the smallest limit at 30 so any value smaller than that is acceptable. + assertThat(createSyntheticAggregationColumn( + new AggregateFunction("count", BIGINT, List.of(), List.of(), false, Optional.empty()), + JDBC_BIGINT, + Integer.MAX_VALUE).getColumnName().length()) + .isEqualTo(19); } private static JdbcColumnHandle column(String columnName) diff --git a/plugin/trino-oracle/src/main/java/io/trino/plugin/oracle/OracleClient.java b/plugin/trino-oracle/src/main/java/io/trino/plugin/oracle/OracleClient.java index eeeaccb62ac9..47837cff4e3e 100644 --- a/plugin/trino-oracle/src/main/java/io/trino/plugin/oracle/OracleClient.java +++ b/plugin/trino-oracle/src/main/java/io/trino/plugin/oracle/OracleClient.java @@ -89,6 +89,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.OptionalInt; import java.util.Set; import java.util.function.BiFunction; @@ -348,6 +349,12 @@ public void renameSchema(ConnectorSession session, String schemaName, String new throw new TrinoException(NOT_SUPPORTED, "This connector does not support renaming schemas"); } + @Override + public OptionalInt getMaxColumnNameLength(ConnectorSession session) + { + return getMaxColumnNameLengthFromDatabaseMetaData(session); + } + @Override public Optional getTableComment(ResultSet resultSet) throws SQLException diff --git a/plugin/trino-oracle/src/test/java/io/trino/plugin/oracle/TestOracleConnectorTest.java b/plugin/trino-oracle/src/test/java/io/trino/plugin/oracle/TestOracleConnectorTest.java index a372c5171e48..440fdfcd25e7 100644 --- a/plugin/trino-oracle/src/test/java/io/trino/plugin/oracle/TestOracleConnectorTest.java +++ b/plugin/trino-oracle/src/test/java/io/trino/plugin/oracle/TestOracleConnectorTest.java @@ -17,27 +17,22 @@ import io.airlift.testing.Closeables; import io.trino.testing.QueryRunner; import io.trino.testing.sql.SqlExecutor; -import io.trino.testing.sql.TestTable; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; -import static io.trino.plugin.jdbc.DefaultJdbcMetadata.DEFAULT_COLUMN_ALIAS_LENGTH; import static io.trino.plugin.oracle.TestingOracleServer.TEST_PASS; import static io.trino.plugin.oracle.TestingOracleServer.TEST_SCHEMA; import static io.trino.plugin.oracle.TestingOracleServer.TEST_USER; import static java.lang.String.format; import static java.util.stream.Collectors.joining; import static java.util.stream.IntStream.range; -import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; @TestInstance(PER_CLASS) public class TestOracleConnectorTest extends BaseOracleConnectorTest { - private static final String MAXIMUM_LENGTH_COLUMN_IDENTIFIER = "z".repeat(DEFAULT_COLUMN_ALIAS_LENGTH); - private TestingOracleServer oracleServer; @Override @@ -103,16 +98,4 @@ public void execute(String sql) } }; } - - @Test - public void testPushdownJoinWithLongNameSucceeds() - { - try (TestTable table = new TestTable(getQueryRunner()::execute, "long_identifier", "(%s bigint)".formatted(MAXIMUM_LENGTH_COLUMN_IDENTIFIER))) { - assertThat(query(joinPushdownEnabled(getSession()), """ - SELECT r.name, t.%s, n.name - FROM %s t JOIN region r ON r.regionkey = t.%s - JOIN nation n ON r.regionkey = n.regionkey""".formatted(MAXIMUM_LENGTH_COLUMN_IDENTIFIER, table.getName(), MAXIMUM_LENGTH_COLUMN_IDENTIFIER))) - .isFullyPushedDown(); - } - } } diff --git a/plugin/trino-postgresql/src/main/java/io/trino/plugin/postgresql/PostgreSqlClient.java b/plugin/trino-postgresql/src/main/java/io/trino/plugin/postgresql/PostgreSqlClient.java index d062c849ad17..affd261a925b 100644 --- a/plugin/trino-postgresql/src/main/java/io/trino/plugin/postgresql/PostgreSqlClient.java +++ b/plugin/trino-postgresql/src/main/java/io/trino/plugin/postgresql/PostgreSqlClient.java @@ -131,6 +131,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.OptionalInt; import java.util.OptionalLong; import java.util.UUID; import java.util.function.BiFunction; @@ -918,6 +919,12 @@ public OptionalLong update(ConnectorSession session, JdbcTableHandle handle) } } + @Override + public OptionalInt getMaxColumnNameLength(ConnectorSession session) + { + return getMaxColumnNameLengthFromDatabaseMetaData(session); + } + @Override public TableStatistics getTableStatistics(ConnectorSession session, JdbcTableHandle handle) { diff --git a/plugin/trino-redshift/src/main/java/io/trino/plugin/redshift/RedshiftClient.java b/plugin/trino-redshift/src/main/java/io/trino/plugin/redshift/RedshiftClient.java index 67184ff6604c..ba04e2693f02 100644 --- a/plugin/trino-redshift/src/main/java/io/trino/plugin/redshift/RedshiftClient.java +++ b/plugin/trino-redshift/src/main/java/io/trino/plugin/redshift/RedshiftClient.java @@ -102,6 +102,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.OptionalInt; import java.util.OptionalLong; import java.util.function.BiFunction; @@ -507,6 +508,12 @@ public OptionalLong update(ConnectorSession session, JdbcTableHandle handle) } } + @Override + public OptionalInt getMaxColumnNameLength(ConnectorSession session) + { + return getMaxColumnNameLengthFromDatabaseMetaData(session); + } + @Override protected void addColumn(ConnectorSession session, Connection connection, RemoteTableName table, ColumnMetadata column) throws SQLException diff --git a/plugin/trino-sqlserver/src/main/java/io/trino/plugin/sqlserver/SqlServerClient.java b/plugin/trino-sqlserver/src/main/java/io/trino/plugin/sqlserver/SqlServerClient.java index 29d9f937511f..f182a7f4e278 100644 --- a/plugin/trino-sqlserver/src/main/java/io/trino/plugin/sqlserver/SqlServerClient.java +++ b/plugin/trino-sqlserver/src/main/java/io/trino/plugin/sqlserver/SqlServerClient.java @@ -114,6 +114,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.OptionalInt; import java.util.function.BiFunction; import java.util.stream.Stream; @@ -1098,6 +1099,12 @@ public Map getTableProperties(ConnectorSession session, JdbcTabl } } + @Override + public OptionalInt getMaxColumnNameLength(ConnectorSession session) + { + return getMaxColumnNameLengthFromDatabaseMetaData(session); + } + @Override public void abortReadConnection(Connection connection, ResultSet resultSet) throws SQLException