diff --git a/presto-accumulo/src/main/java/com/facebook/presto/accumulo/AccumuloMetadata.java b/presto-accumulo/src/main/java/com/facebook/presto/accumulo/AccumuloMetadata.java index 1d968bae6c1b5..1829981653204 100644 --- a/presto-accumulo/src/main/java/com/facebook/presto/accumulo/AccumuloMetadata.java +++ b/presto-accumulo/src/main/java/com/facebook/presto/accumulo/AccumuloMetadata.java @@ -57,6 +57,7 @@ import static com.facebook.presto.spi.StandardErrorCode.NOT_SUPPORTED; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; +import static com.google.common.collect.ImmutableList.toImmutableList; import static java.lang.String.format; import static java.util.Objects.requireNonNull; @@ -282,7 +283,7 @@ public ConnectorTableMetadata getTableMetadata(ConnectorSession session, Connect AccumuloTableHandle handle = (AccumuloTableHandle) table; checkArgument(handle.getConnectorId().equals(connectorId), "table is not for this connector"); SchemaTableName tableName = new SchemaTableName(handle.getSchema(), handle.getTable()); - ConnectorTableMetadata metadata = getTableMetadata(tableName); + ConnectorTableMetadata metadata = getTableMetadata(session, tableName); if (metadata == null) { throw new TableNotFoundException(tableName); } @@ -353,7 +354,7 @@ public Map> listTableColumns(ConnectorSess requireNonNull(prefix, "prefix is null"); ImmutableMap.Builder> columns = ImmutableMap.builder(); for (SchemaTableName tableName : listTables(session, prefix)) { - ConnectorTableMetadata tableMetadata = getTableMetadata(tableName); + ConnectorTableMetadata tableMetadata = getTableMetadata(session, tableName); // table can disappear during listing operation if (tableMetadata != null) { columns.put(tableName, tableMetadata.getColumns()); @@ -385,7 +386,7 @@ public void rollback() } } - private ConnectorTableMetadata getTableMetadata(SchemaTableName tableName) + private ConnectorTableMetadata getTableMetadata(ConnectorSession session, SchemaTableName tableName) { if (!client.getSchemaNames().contains(tableName.getSchemaName())) { return null; @@ -398,7 +399,13 @@ private ConnectorTableMetadata getTableMetadata(SchemaTableName tableName) return null; } - return new ConnectorTableMetadata(tableName, table.getColumnsMetadata()); + List columns = table.getColumnsMetadata().stream() + .map(column -> column.toBuilder() + .setName(normalizeIdentifier(session, column.getName())) + .build()) + .collect(toImmutableList()); + + return new ConnectorTableMetadata(tableName, columns); } return null; diff --git a/presto-atop/src/main/java/com/facebook/presto/atop/AtopMetadata.java b/presto-atop/src/main/java/com/facebook/presto/atop/AtopMetadata.java index 34bd2171e22fa..3c8084a7d1d7b 100644 --- a/presto-atop/src/main/java/com/facebook/presto/atop/AtopMetadata.java +++ b/presto-atop/src/main/java/com/facebook/presto/atop/AtopMetadata.java @@ -121,7 +121,7 @@ public ConnectorTableMetadata getTableMetadata(ConnectorSession session, Connect ImmutableList.Builder columns = ImmutableList.builder(); for (AtopColumn column : atopTableHandle.getTable().getColumns()) { columns.add(ColumnMetadata.builder() - .setName(column.getName()) + .setName(normalizeIdentifier(session, column.getName())) .setType(typeManager.getType(column.getType())) .build()); } diff --git a/presto-base-arrow-flight/src/main/java/com/facebook/plugin/arrow/ArrowMetadata.java b/presto-base-arrow-flight/src/main/java/com/facebook/plugin/arrow/ArrowMetadata.java index fd530b21a718d..93fff6b62374d 100644 --- a/presto-base-arrow-flight/src/main/java/com/facebook/plugin/arrow/ArrowMetadata.java +++ b/presto-base-arrow-flight/src/main/java/com/facebook/plugin/arrow/ArrowMetadata.java @@ -148,7 +148,7 @@ public ConnectorTableMetadata getTableMetadata(ConnectorSession session, Connect for (Field field : columnList) { String columnName = field.getName(); Type fieldType = getPrestoTypeFromArrowField(field); - meta.add(ColumnMetadata.builder().setName(columnName).setType(fieldType).build()); + meta.add(ColumnMetadata.builder().setName(normalizeIdentifier(session, columnName)).setType(fieldType).build()); } return new ConnectorTableMetadata(new SchemaTableName(((ArrowTableHandle) table).getSchema(), ((ArrowTableHandle) table).getTable()), meta); } diff --git a/presto-base-arrow-flight/src/test/java/com/facebook/plugin/arrow/TestArrowColumnHandle.java b/presto-base-arrow-flight/src/test/java/com/facebook/plugin/arrow/TestArrowColumnHandle.java index 1d9c490180abc..27ded280221c5 100644 --- a/presto-base-arrow-flight/src/test/java/com/facebook/plugin/arrow/TestArrowColumnHandle.java +++ b/presto-base-arrow-flight/src/test/java/com/facebook/plugin/arrow/TestArrowColumnHandle.java @@ -17,8 +17,6 @@ import com.facebook.presto.spi.ColumnMetadata; import org.testng.annotations.Test; -import java.util.Locale; - import static com.facebook.presto.testing.assertions.Assert.assertEquals; import static org.testng.Assert.assertNotNull; @@ -67,7 +65,7 @@ public void testGetColumnMetadata() // Then assertNotNull(columnMetadata, "ColumnMetadata should not be null"); - assertEquals(columnMetadata.getName(), columnName.toLowerCase(Locale.ENGLISH), "ColumnMetadata name should match the column name"); + assertEquals(columnMetadata.getName(), columnName, "ColumnMetadata name should match the column name"); assertEquals(columnMetadata.getType(), IntegerType.INTEGER, "ColumnMetadata type should match the column type"); } diff --git a/presto-base-jdbc/src/main/java/com/facebook/presto/plugin/jdbc/JdbcColumnHandle.java b/presto-base-jdbc/src/main/java/com/facebook/presto/plugin/jdbc/JdbcColumnHandle.java index 3be953c156a89..ec7e1d1ac764b 100644 --- a/presto-base-jdbc/src/main/java/com/facebook/presto/plugin/jdbc/JdbcColumnHandle.java +++ b/presto-base-jdbc/src/main/java/com/facebook/presto/plugin/jdbc/JdbcColumnHandle.java @@ -16,6 +16,7 @@ import com.facebook.presto.common.type.Type; import com.facebook.presto.spi.ColumnHandle; import com.facebook.presto.spi.ColumnMetadata; +import com.facebook.presto.spi.ConnectorSession; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -98,6 +99,16 @@ public ColumnMetadata getColumnMetadata() .build(); } + public ColumnMetadata getColumnMetadata(ConnectorSession session, JdbcClient jdbcClient) + { + return ColumnMetadata.builder() + .setName(jdbcClient.normalizeIdentifier(session, columnName)) + .setType(columnType) + .setNullable(nullable) + .setComment(comment.orElse(null)) + .build(); + } + @Override public boolean equals(Object obj) { diff --git a/presto-base-jdbc/src/main/java/com/facebook/presto/plugin/jdbc/JdbcMetadata.java b/presto-base-jdbc/src/main/java/com/facebook/presto/plugin/jdbc/JdbcMetadata.java index ae0768913587e..94fa1035de425 100644 --- a/presto-base-jdbc/src/main/java/com/facebook/presto/plugin/jdbc/JdbcMetadata.java +++ b/presto-base-jdbc/src/main/java/com/facebook/presto/plugin/jdbc/JdbcMetadata.java @@ -104,7 +104,7 @@ public ConnectorTableMetadata getTableMetadata(ConnectorSession session, Connect ImmutableList.Builder columnMetadata = ImmutableList.builder(); for (JdbcColumnHandle column : jdbcMetadataCache.getColumns(session, handle)) { - columnMetadata.add(column.getColumnMetadata()); + columnMetadata.add(column.getColumnMetadata(session, jdbcClient)); } return new ConnectorTableMetadata(handle.getSchemaTableName(), columnMetadata.build()); } @@ -122,7 +122,7 @@ public Map getColumnHandles(ConnectorSession session, Conn ImmutableMap.Builder columnHandles = ImmutableMap.builder(); for (JdbcColumnHandle column : jdbcMetadataCache.getColumns(session, jdbcTableHandle)) { - columnHandles.put(column.getColumnMetadata().getName(), column); + columnHandles.put(column.getColumnMetadata(session, jdbcClient).getName(), column); } return columnHandles.build(); } diff --git a/presto-base-jdbc/src/test/java/com/facebook/presto/plugin/jdbc/TestingDatabase.java b/presto-base-jdbc/src/test/java/com/facebook/presto/plugin/jdbc/TestingDatabase.java index ad0b4163f8556..a62440a630436 100644 --- a/presto-base-jdbc/src/test/java/com/facebook/presto/plugin/jdbc/TestingDatabase.java +++ b/presto-base-jdbc/src/test/java/com/facebook/presto/plugin/jdbc/TestingDatabase.java @@ -117,7 +117,7 @@ public Map getColumnHandles(String schemaName, String ImmutableMap.Builder columnHandles = ImmutableMap.builder(); for (JdbcColumnHandle column : columns) { - columnHandles.put(column.getColumnMetadata().getName(), column); + columnHandles.put(column.getColumnMetadata(session, jdbcClient).getName(), column); } return columnHandles.build(); } diff --git a/presto-bigquery/src/main/java/com/facebook/presto/plugin/bigquery/BigQueryMetadata.java b/presto-bigquery/src/main/java/com/facebook/presto/plugin/bigquery/BigQueryMetadata.java index 8952eb3bbf87d..e48c5c3c7d7b5 100644 --- a/presto-bigquery/src/main/java/com/facebook/presto/plugin/bigquery/BigQueryMetadata.java +++ b/presto-bigquery/src/main/java/com/facebook/presto/plugin/bigquery/BigQueryMetadata.java @@ -48,6 +48,7 @@ import java.util.Set; import static com.facebook.presto.plugin.bigquery.BigQueryErrorCode.BIGQUERY_TABLE_DISAPPEAR_DURING_LIST; +import static com.facebook.presto.plugin.bigquery.Conversions.toColumnMetadata; import static com.google.cloud.bigquery.TableDefinition.Type.TABLE; import static com.google.cloud.bigquery.TableDefinition.Type.VIEW; import static com.google.common.collect.ImmutableList.toImmutableList; @@ -179,7 +180,7 @@ public ConnectorTableMetadata getTableMetadata(ConnectorSession session, Connect List columns = schema == null ? ImmutableList.of() : schema.getFields().stream() - .map(Conversions::toColumnMetadata) + .map(field -> toColumnMetadata(field, normalizeIdentifier(session, field.getName()))) .collect(toImmutableList()); return new ConnectorTableMetadata(schemaTableName, columns); } diff --git a/presto-bigquery/src/main/java/com/facebook/presto/plugin/bigquery/Conversions.java b/presto-bigquery/src/main/java/com/facebook/presto/plugin/bigquery/Conversions.java index ed2e88e3d9cba..5fa2f3ae785af 100644 --- a/presto-bigquery/src/main/java/com/facebook/presto/plugin/bigquery/Conversions.java +++ b/presto-bigquery/src/main/java/com/facebook/presto/plugin/bigquery/Conversions.java @@ -47,10 +47,10 @@ static BigQueryColumnHandle toColumnHandle(Field field) field.getDescription()); } - static ColumnMetadata toColumnMetadata(Field field) + static ColumnMetadata toColumnMetadata(Field field, String name) { return ColumnMetadata.builder() - .setName(field.getName()) + .setName(name) .setType(adapt(field).getPrestoType()) .setNullable(getMode(field) == NULLABLE) .setComment(field.getDescription()) diff --git a/presto-bigquery/src/test/java/com/facebook/presto/plugin/bigquery/TestTypeConversions.java b/presto-bigquery/src/test/java/com/facebook/presto/plugin/bigquery/TestTypeConversions.java index 4e6c6b3fe5111..e0e9698e5ac52 100644 --- a/presto-bigquery/src/test/java/com/facebook/presto/plugin/bigquery/TestTypeConversions.java +++ b/presto-bigquery/src/test/java/com/facebook/presto/plugin/bigquery/TestTypeConversions.java @@ -134,7 +134,7 @@ public void testConvertOneLevelRecordField() RECORD, Field.of("sub_s", STRING), Field.of("sub_i", INTEGER)); - ColumnMetadata metadata = Conversions.toColumnMetadata(field); + ColumnMetadata metadata = Conversions.toColumnMetadata(field, field.getName()); RowType targetType = RowType.from(ImmutableList.of( RowType.field("sub_s", VarcharType.VARCHAR), RowType.field("sub_i", BigintType.BIGINT))); @@ -152,7 +152,7 @@ public void testConvertTwoLevelsRecordField() Field.of("sub_sub_i", INTEGER)), Field.of("sub_s", STRING), Field.of("sub_i", INTEGER)); - ColumnMetadata metadata = Conversions.toColumnMetadata(field); + ColumnMetadata metadata = Conversions.toColumnMetadata(field, field.getName()); RowType targetType = RowType.from(ImmutableList.of( RowType.field("sub_rec", RowType.from(ImmutableList.of( RowType.field("sub_sub_s", VarcharType.VARCHAR), @@ -168,13 +168,13 @@ public void testConvertStringArrayField() Field field = Field.newBuilder("test", STRING) .setMode(REPEATED) .build(); - ColumnMetadata metadata = Conversions.toColumnMetadata(field); + ColumnMetadata metadata = Conversions.toColumnMetadata(field, field.getName()); assertThat(metadata.getType()).isEqualTo(new ArrayType(VarcharType.VARCHAR)); } void assertSimpleFieldTypeConversion(LegacySQLTypeName from, Type to) { - ColumnMetadata metadata = Conversions.toColumnMetadata(createField(from)); + ColumnMetadata metadata = Conversions.toColumnMetadata(createField(from), createField(from).getName()); assertThat(metadata.getType()).isEqualTo(to); } diff --git a/presto-blackhole/src/main/java/com/facebook/presto/plugin/blackhole/BlackHoleColumnHandle.java b/presto-blackhole/src/main/java/com/facebook/presto/plugin/blackhole/BlackHoleColumnHandle.java index f861b873a63ed..03b2dc317d847 100644 --- a/presto-blackhole/src/main/java/com/facebook/presto/plugin/blackhole/BlackHoleColumnHandle.java +++ b/presto-blackhole/src/main/java/com/facebook/presto/plugin/blackhole/BlackHoleColumnHandle.java @@ -61,6 +61,14 @@ public ColumnMetadata toColumnMetadata() .build(); } + public ColumnMetadata toColumnMetadata(String name) + { + return ColumnMetadata.builder() + .setName(name) + .setType(columnType) + .build(); + } + @Override public int hashCode() { diff --git a/presto-blackhole/src/main/java/com/facebook/presto/plugin/blackhole/BlackHoleMetadata.java b/presto-blackhole/src/main/java/com/facebook/presto/plugin/blackhole/BlackHoleMetadata.java index 51f0db43fc997..4c0495ca4a5c1 100644 --- a/presto-blackhole/src/main/java/com/facebook/presto/plugin/blackhole/BlackHoleMetadata.java +++ b/presto-blackhole/src/main/java/com/facebook/presto/plugin/blackhole/BlackHoleMetadata.java @@ -54,6 +54,7 @@ import static com.facebook.presto.plugin.blackhole.BlackHoleConnector.SPLIT_COUNT_PROPERTY; import static com.facebook.presto.spi.StandardErrorCode.ALREADY_EXISTS; import static com.facebook.presto.spi.StandardErrorCode.INVALID_TABLE_PROPERTY; +import static com.google.common.collect.ImmutableList.toImmutableList; import static java.lang.String.format; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; @@ -97,7 +98,16 @@ public ConnectorTableHandle getTableHandle(ConnectorSession session, SchemaTable public ConnectorTableMetadata getTableMetadata(ConnectorSession session, ConnectorTableHandle tableHandle) { BlackHoleTableHandle blackHoleTableHandle = (BlackHoleTableHandle) tableHandle; - return blackHoleTableHandle.toTableMetadata(); + return toTableMetadata(blackHoleTableHandle, session); + } + + public ConnectorTableMetadata toTableMetadata(BlackHoleTableHandle blackHoleTableHandle, ConnectorSession session) + { + List columns = blackHoleTableHandle.getColumnHandles().stream() + .map(column -> column.toColumnMetadata(normalizeIdentifier(session, column.getName()))) + .collect(toImmutableList()); + + return new ConnectorTableMetadata(blackHoleTableHandle.toSchemaTableName(), columns); } @Override @@ -129,7 +139,7 @@ public Map> listTableColumns(ConnectorSess { return tables.values().stream() .filter(table -> prefix.matches(table.toSchemaTableName())) - .collect(toMap(BlackHoleTableHandle::toSchemaTableName, handle -> handle.toTableMetadata().getColumns())); + .collect(toMap(BlackHoleTableHandle::toSchemaTableName, handle -> toTableMetadata(handle, session).getColumns())); } @Override diff --git a/presto-blackhole/src/main/java/com/facebook/presto/plugin/blackhole/BlackHoleTableHandle.java b/presto-blackhole/src/main/java/com/facebook/presto/plugin/blackhole/BlackHoleTableHandle.java index 8a83a209940f2..efa144a8aae4b 100644 --- a/presto-blackhole/src/main/java/com/facebook/presto/plugin/blackhole/BlackHoleTableHandle.java +++ b/presto-blackhole/src/main/java/com/facebook/presto/plugin/blackhole/BlackHoleTableHandle.java @@ -126,13 +126,6 @@ public Duration getPageProcessingDelay() return pageProcessingDelay; } - public ConnectorTableMetadata toTableMetadata() - { - return new ConnectorTableMetadata( - toSchemaTableName(), - columnHandles.stream().map(BlackHoleColumnHandle::toColumnMetadata).collect(toList())); - } - public SchemaTableName toSchemaTableName() { return new SchemaTableName(schemaName, tableName); diff --git a/presto-cassandra/src/main/java/com/facebook/presto/cassandra/CassandraColumnHandle.java b/presto-cassandra/src/main/java/com/facebook/presto/cassandra/CassandraColumnHandle.java index a5ca33a1a0ff1..56434ad7d889a 100644 --- a/presto-cassandra/src/main/java/com/facebook/presto/cassandra/CassandraColumnHandle.java +++ b/presto-cassandra/src/main/java/com/facebook/presto/cassandra/CassandraColumnHandle.java @@ -138,6 +138,15 @@ public ColumnMetadata getColumnMetadata() .build(); } + public ColumnMetadata getColumnMetadata(String name) + { + return ColumnMetadata.builder() + .setName(name) + .setType(cassandraType.getNativeType()) + .setHidden(hidden) + .build(); + } + public Type getType() { return cassandraType.getNativeType(); diff --git a/presto-cassandra/src/main/java/com/facebook/presto/cassandra/CassandraMetadata.java b/presto-cassandra/src/main/java/com/facebook/presto/cassandra/CassandraMetadata.java index c8e07887d091a..75f10c3c85404 100644 --- a/presto-cassandra/src/main/java/com/facebook/presto/cassandra/CassandraMetadata.java +++ b/presto-cassandra/src/main/java/com/facebook/presto/cassandra/CassandraMetadata.java @@ -53,6 +53,7 @@ import java.util.stream.Collectors; import static com.facebook.presto.cassandra.CassandraType.toCassandraType; +import static com.facebook.presto.cassandra.util.CassandraCqlUtils.cqlNameToSqlName; import static com.facebook.presto.cassandra.util.CassandraCqlUtils.validSchemaName; import static com.facebook.presto.cassandra.util.CassandraCqlUtils.validTableName; import static com.facebook.presto.spi.StandardErrorCode.NOT_SUPPORTED; @@ -62,7 +63,6 @@ import static com.google.common.collect.ImmutableList.toImmutableList; import static java.util.Locale.ENGLISH; import static java.util.Objects.requireNonNull; -import static java.util.stream.Collectors.toList; public class CassandraMetadata implements ConnectorMetadata @@ -121,15 +121,15 @@ private static SchemaTableName getTableName(ConnectorTableHandle tableHandle) public ConnectorTableMetadata getTableMetadata(ConnectorSession session, ConnectorTableHandle tableHandle) { requireNonNull(tableHandle, "tableHandle is null"); - return getTableMetadata(getTableName(tableHandle)); + return getTableMetadata(session, getTableName(tableHandle)); } - private ConnectorTableMetadata getTableMetadata(SchemaTableName tableName) + private ConnectorTableMetadata getTableMetadata(ConnectorSession session, SchemaTableName tableName) { CassandraTable table = cassandraSession.getTable(tableName); List columns = table.getColumns().stream() - .map(CassandraColumnHandle::getColumnMetadata) - .collect(toList()); + .map(column -> column.getColumnMetadata(normalizeIdentifier(session, cqlNameToSqlName(column.getName())))) + .collect(toImmutableList()); return new ConnectorTableMetadata(tableName, columns); } @@ -178,7 +178,7 @@ public Map> listTableColumns(ConnectorSess ImmutableMap.Builder> columns = ImmutableMap.builder(); for (SchemaTableName tableName : listTables(session, prefix)) { try { - columns.put(tableName, getTableMetadata(tableName).getColumns()); + columns.put(tableName, getTableMetadata(session, tableName).getColumns()); } catch (NotFoundException e) { // table disappeared during listing operation diff --git a/presto-clickhouse/src/main/java/com/facebook/presto/plugin/clickhouse/ClickHouseColumnHandle.java b/presto-clickhouse/src/main/java/com/facebook/presto/plugin/clickhouse/ClickHouseColumnHandle.java index 616715b7764dd..5cbfebc09e1b9 100755 --- a/presto-clickhouse/src/main/java/com/facebook/presto/plugin/clickhouse/ClickHouseColumnHandle.java +++ b/presto-clickhouse/src/main/java/com/facebook/presto/plugin/clickhouse/ClickHouseColumnHandle.java @@ -142,6 +142,17 @@ public ColumnMetadata getColumnMetadata() .build(); } + public ColumnMetadata getColumnMetadata(String name) + { + return ColumnMetadata.builder() + .setName(name) + .setType(columnType) + .setNullable(nullable) + .setHidden(false) + .setProperties(emptyMap()) + .build(); + } + @Override public boolean equals(Object obj) { diff --git a/presto-clickhouse/src/main/java/com/facebook/presto/plugin/clickhouse/ClickHouseMetadata.java b/presto-clickhouse/src/main/java/com/facebook/presto/plugin/clickhouse/ClickHouseMetadata.java index 07b2181812186..6e8fdf91e40ea 100755 --- a/presto-clickhouse/src/main/java/com/facebook/presto/plugin/clickhouse/ClickHouseMetadata.java +++ b/presto-clickhouse/src/main/java/com/facebook/presto/plugin/clickhouse/ClickHouseMetadata.java @@ -104,7 +104,7 @@ public ConnectorTableMetadata getTableMetadata(ConnectorSession session, Connect ImmutableList.Builder columnMetadata = ImmutableList.builder(); for (ClickHouseColumnHandle column : clickHouseClient.getColumns(session, handle)) { - columnMetadata.add(column.getColumnMetadata()); + columnMetadata.add(column.getColumnMetadata(normalizeIdentifier(session, column.getColumnName()))); } return new ConnectorTableMetadata(handle.getSchemaTableName(), columnMetadata.build()); } @@ -122,7 +122,7 @@ public Map getColumnHandles(ConnectorSession session, Conn ImmutableMap.Builder columnHandles = ImmutableMap.builder(); for (ClickHouseColumnHandle column : clickHouseClient.getColumns(session, clickHouseTableHandle)) { - columnHandles.put(column.getColumnMetadata().getName(), column); + columnHandles.put(normalizeIdentifier(session, column.getColumnMetadata(column.getColumnName()).getName()), column); } return columnHandles.build(); } diff --git a/presto-delta/src/main/java/com/facebook/presto/delta/DeltaMetadata.java b/presto-delta/src/main/java/com/facebook/presto/delta/DeltaMetadata.java index d76eed8e6cc40..c89e8204998e0 100644 --- a/presto-delta/src/main/java/com/facebook/presto/delta/DeltaMetadata.java +++ b/presto-delta/src/main/java/com/facebook/presto/delta/DeltaMetadata.java @@ -333,7 +333,7 @@ private ConnectorTableMetadata getTableMetadata(ConnectorSession session, Schema } List columnMetadata = tableHandle.getDeltaTable().getColumns().stream() - .map(this::getColumnMetadata) + .map(column -> getColumnMetadata(session, column)) .collect(Collectors.toList()); return new ConnectorTableMetadata(tableName, columnMetadata); @@ -362,10 +362,10 @@ private List listTables(ConnectorSession session, SchemaTablePr return ImmutableList.of(new SchemaTableName(prefix.getSchemaName(), prefix.getTableName())); } - private ColumnMetadata getColumnMetadata(DeltaColumn deltaColumn) + private ColumnMetadata getColumnMetadata(ConnectorSession session, DeltaColumn deltaColumn) { return ColumnMetadata.builder() - .setName(deltaColumn.getName()) + .setName(normalizeIdentifier(session, deltaColumn.getName())) .setType(typeManager.getType(deltaColumn.getType())) .build(); } diff --git a/presto-docs/src/main/sphinx/connector/hana.rst b/presto-docs/src/main/sphinx/connector/hana.rst index 7f18e3e156a26..7c53be61a2c45 100644 --- a/presto-docs/src/main/sphinx/connector/hana.rst +++ b/presto-docs/src/main/sphinx/connector/hana.rst @@ -91,6 +91,10 @@ Property Name Description cached. Set to ``0ms`` to disable the cache. ``1m`` ``list-schemas-ignored-schemas`` List of schemas to ignore when listing schemas. ``information_schema`` + +``case-sensitive-name-matching`` Enable case sensitive identifier support for schema and table ``false`` + names for the connector. When disabled, names are matched + case-insensitively using lowercase normalization. ================================================== ==================================================================== =========== Querying HANA diff --git a/presto-docs/src/main/sphinx/connector/oracle.rst b/presto-docs/src/main/sphinx/connector/oracle.rst index dfa84c873515d..3deb882b1fcd2 100644 --- a/presto-docs/src/main/sphinx/connector/oracle.rst +++ b/presto-docs/src/main/sphinx/connector/oracle.rst @@ -70,6 +70,10 @@ Property Name Description cached. Set to ``0ms`` to disable the cache. ``1m`` ``list-schemas-ignored-schemas`` List of schemas to ignore when listing schemas. ``information_schema`` + +``case-sensitive-name-matching`` Enable case sensitive identifier support for schema and table ``false`` + names for the connector. When disabled, names are matched + case-insensitively using lowercase normalization. ================================================== ==================================================================== =========== Querying Oracle diff --git a/presto-docs/src/main/sphinx/connector/postgresql.rst b/presto-docs/src/main/sphinx/connector/postgresql.rst index 29839d6613f6c..7d0a2a4a49feb 100644 --- a/presto-docs/src/main/sphinx/connector/postgresql.rst +++ b/presto-docs/src/main/sphinx/connector/postgresql.rst @@ -56,6 +56,10 @@ Property Name Description cached. Set to ``0ms`` to disable the cache. ``1m`` ``list-schemas-ignored-schemas`` List of schemas to ignore when listing schemas. ``information_schema`` + +``case-sensitive-name-matching`` Enable case sensitive identifier support for schema and table ``false`` + names for the connector. When disabled, names are matched + case-insensitively using lowercase normalization. ================================================== ==================================================================== =========== Querying PostgreSQL diff --git a/presto-docs/src/main/sphinx/connector/redshift.rst b/presto-docs/src/main/sphinx/connector/redshift.rst index b28960572f4e4..9ad6fa53dc53b 100644 --- a/presto-docs/src/main/sphinx/connector/redshift.rst +++ b/presto-docs/src/main/sphinx/connector/redshift.rst @@ -56,6 +56,10 @@ Property Name Description cached. Set to ``0ms`` to disable the cache. ``1m`` ``list-schemas-ignored-schemas`` List of schemas to ignore when listing schemas. ``information_schema`` + +``case-sensitive-name-matching`` Enable case sensitive identifier support for schema and table ``false`` + names for the connector. When disabled, names are matched + case-insensitively using lowercase normalization. ================================================== ==================================================================== =========== Querying Redshift diff --git a/presto-docs/src/main/sphinx/connector/sqlserver.rst b/presto-docs/src/main/sphinx/connector/sqlserver.rst index dc28f3a0ae603..0df4e755273f5 100644 --- a/presto-docs/src/main/sphinx/connector/sqlserver.rst +++ b/presto-docs/src/main/sphinx/connector/sqlserver.rst @@ -134,6 +134,10 @@ Property Name Description cached. Set to ``0ms`` to disable the cache. ``1m`` ``list-schemas-ignored-schemas`` List of schemas to ignore when listing schemas. ``information_schema`` + +``case-sensitive-name-matching`` Enable case sensitive identifier support for schema and table ``false`` + names for the connector. When disabled, names are matched + case-insensitively using lowercase normalization. ================================================== ==================================================================== =========== Querying SQL Server diff --git a/presto-druid/src/main/java/com/facebook/presto/druid/DruidMetadata.java b/presto-druid/src/main/java/com/facebook/presto/druid/DruidMetadata.java index 824fbf1c4e80f..0f4f58b29acc8 100644 --- a/presto-druid/src/main/java/com/facebook/presto/druid/DruidMetadata.java +++ b/presto-druid/src/main/java/com/facebook/presto/druid/DruidMetadata.java @@ -104,7 +104,7 @@ public ConnectorTableMetadata getTableMetadata(ConnectorSession session, Connect { DruidTableHandle druidTable = (DruidTableHandle) tableHandle; List columns = druidClient.getColumnDataType(druidTable.getTableName()).stream() - .map(column -> toColumnMetadata(column)) + .map(column -> toColumnMetadata(session, column)) .collect(toImmutableList()); return new ConnectorTableMetadata(druidTable.toSchemaTableName(), columns); @@ -198,10 +198,10 @@ private List listTables(ConnectorSession session, SchemaTablePr return ImmutableList.of(prefix.toSchemaTableName()); } - private static ColumnMetadata toColumnMetadata(DruidColumnInfo column) + private ColumnMetadata toColumnMetadata(ConnectorSession session, DruidColumnInfo column) { return ColumnMetadata.builder() - .setName(column.getColumnName()) + .setName(normalizeIdentifier(session, column.getColumnName())) .setType(column.getDataType().getPrestoType()) .build(); } diff --git a/presto-elasticsearch/src/main/java/com/facebook/presto/elasticsearch/ElasticsearchMetadata.java b/presto-elasticsearch/src/main/java/com/facebook/presto/elasticsearch/ElasticsearchMetadata.java index 6217ce9ce1e48..93bb8a3d0f13a 100644 --- a/presto-elasticsearch/src/main/java/com/facebook/presto/elasticsearch/ElasticsearchMetadata.java +++ b/presto-elasticsearch/src/main/java/com/facebook/presto/elasticsearch/ElasticsearchMetadata.java @@ -182,26 +182,26 @@ public ConnectorTableMetadata getTableMetadata(ConnectorSession session, Connect new SchemaTableName(handle.getSchema(), handle.getIndex()), ImmutableList.of(queryResultColumnMetadata)); } - return getTableMetadata(handle.getSchema(), handle.getIndex()); + return getTableMetadata(session, handle.getSchema(), handle.getIndex()); } - private ConnectorTableMetadata getTableMetadata(String schemaName, String tableName) + private ConnectorTableMetadata getTableMetadata(ConnectorSession session, String schemaName, String tableName) { - InternalTableMetadata internalTableMetadata = makeInternalTableMetadata(schemaName, tableName); + InternalTableMetadata internalTableMetadata = makeInternalTableMetadata(session, schemaName, tableName); return new ConnectorTableMetadata(new SchemaTableName(schemaName, tableName), internalTableMetadata.getColumnMetadata()); } - private InternalTableMetadata makeInternalTableMetadata(ConnectorTableHandle table) + private InternalTableMetadata makeInternalTableMetadata(ConnectorSession session, ConnectorTableHandle table) { ElasticsearchTableHandle handle = (ElasticsearchTableHandle) table; - return makeInternalTableMetadata(handle.getSchema(), handle.getIndex()); + return makeInternalTableMetadata(session, handle.getSchema(), handle.getIndex()); } - private InternalTableMetadata makeInternalTableMetadata(String schema, String tableName) + private InternalTableMetadata makeInternalTableMetadata(ConnectorSession session, String schema, String tableName) { IndexMetadata metadata = client.getIndexMetadata(tableName); List fields = getColumnFields(metadata); - return new InternalTableMetadata(new SchemaTableName(schema, tableName), makeColumnMetadata(fields), makeColumnHandles(fields)); + return new InternalTableMetadata(new SchemaTableName(schema, tableName), makeColumnMetadata(session, fields), makeColumnHandles(fields)); } private List getColumnFields(IndexMetadata metadata) @@ -222,7 +222,7 @@ private List getColumnFields(IndexMetadata metadata) return result.build(); } - private List makeColumnMetadata(List fields) + private List makeColumnMetadata(ConnectorSession session, List fields) { ImmutableList.Builder result = ImmutableList.builder(); @@ -231,7 +231,7 @@ private List makeColumnMetadata(List fields } for (IndexMetadata.Field field : fields) { - result.add(ColumnMetadata.builder().setName(field.getName()).setType(toPrestoType(field)).build()); + result.add(ColumnMetadata.builder().setName(normalizeIdentifier(session, field.getName())).setType(toPrestoType(field)).build()); } return result.build(); } @@ -374,7 +374,7 @@ public Map getColumnHandles(ConnectorSession session, Conn return queryTableColumns; } - InternalTableMetadata tableMetadata = makeInternalTableMetadata(tableHandle); + InternalTableMetadata tableMetadata = makeInternalTableMetadata(session, tableHandle); return tableMetadata.getColumnHandles(); } @@ -411,12 +411,12 @@ public Map> listTableColumns(ConnectorSess } if (prefix.getSchemaName() != null && prefix.getTableName() != null) { - ConnectorTableMetadata metadata = getTableMetadata(prefix.getSchemaName(), prefix.getTableName()); + ConnectorTableMetadata metadata = getTableMetadata(session, prefix.getSchemaName(), prefix.getTableName()); return ImmutableMap.of(metadata.getTable(), metadata.getColumns()); } return listTables(session, prefix.getSchemaName()).stream() - .map(name -> getTableMetadata(name.getSchemaName(), name.getTableName())) + .map(name -> getTableMetadata(session, name.getSchemaName(), name.getTableName())) .collect(toImmutableMap(ConnectorTableMetadata::getTable, ConnectorTableMetadata::getColumns)); } diff --git a/presto-example-http/src/main/java/com/facebook/presto/example/ExampleMetadata.java b/presto-example-http/src/main/java/com/facebook/presto/example/ExampleMetadata.java index b67bbcdde8afa..4a0b9b7a63564 100644 --- a/presto-example-http/src/main/java/com/facebook/presto/example/ExampleMetadata.java +++ b/presto-example-http/src/main/java/com/facebook/presto/example/ExampleMetadata.java @@ -38,6 +38,7 @@ import java.util.Set; import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.collect.ImmutableList.toImmutableList; import static java.util.Objects.requireNonNull; public class ExampleMetadata @@ -101,7 +102,7 @@ public ConnectorTableMetadata getTableMetadata(ConnectorSession session, Connect checkArgument(exampleTableHandle.getConnectorId().equals(connectorId), "tableHandle is not for this connector"); SchemaTableName tableName = new SchemaTableName(exampleTableHandle.getSchemaName(), exampleTableHandle.getTableName()); - return getTableMetadata(tableName); + return getTableMetadata(session, tableName); } @Override @@ -137,20 +138,25 @@ public Map getColumnHandles(ConnectorSession session, Conn ImmutableMap.Builder columnHandles = ImmutableMap.builder(); int index = 0; - for (ColumnMetadata column : table.getColumnsMetadata()) { + List columns = table.getColumnsMetadata().stream() + .map(column -> column.toBuilder() + .setName(normalizeIdentifier(session, column.getName())) + .build()) + .collect(toImmutableList()); + + for (ColumnMetadata column : columns) { columnHandles.put(column.getName(), new ExampleColumnHandle(connectorId, column.getName(), column.getType(), index)); index++; } return columnHandles.build(); } - @Override public Map> listTableColumns(ConnectorSession session, SchemaTablePrefix prefix) { requireNonNull(prefix, "prefix is null"); ImmutableMap.Builder> columns = ImmutableMap.builder(); for (SchemaTableName tableName : listTables(session, prefix)) { - ConnectorTableMetadata tableMetadata = getTableMetadata(tableName); + ConnectorTableMetadata tableMetadata = getTableMetadata(session, tableName); // table can disappear during listing operation if (tableMetadata != null) { columns.put(tableName, tableMetadata.getColumns()); @@ -159,7 +165,7 @@ public Map> listTableColumns(ConnectorSess return columns.build(); } - private ConnectorTableMetadata getTableMetadata(SchemaTableName tableName) + private ConnectorTableMetadata getTableMetadata(ConnectorSession session, SchemaTableName tableName) { if (!listSchemaNames().contains(tableName.getSchemaName())) { return null; @@ -169,8 +175,13 @@ private ConnectorTableMetadata getTableMetadata(SchemaTableName tableName) if (table == null) { return null; } + List columns = table.getColumnsMetadata().stream() + .map(column -> column.toBuilder() + .setName(normalizeIdentifier(session, column.getName())) + .build()) + .collect(toImmutableList()); - return new ConnectorTableMetadata(tableName, table.getColumnsMetadata()); + return new ConnectorTableMetadata(tableName, columns); } private List listTables(ConnectorSession session, SchemaTablePrefix prefix) diff --git a/presto-google-sheets/src/main/java/com/facebook/presto/google/sheets/SheetsMetadata.java b/presto-google-sheets/src/main/java/com/facebook/presto/google/sheets/SheetsMetadata.java index 69b73d4c6915e..77efd180c6a86 100644 --- a/presto-google-sheets/src/main/java/com/facebook/presto/google/sheets/SheetsMetadata.java +++ b/presto-google-sheets/src/main/java/com/facebook/presto/google/sheets/SheetsMetadata.java @@ -100,21 +100,27 @@ public ConnectorTableLayout getTableLayout(ConnectorSession session, ConnectorTa @Override public ConnectorTableMetadata getTableMetadata(ConnectorSession session, ConnectorTableHandle table) { - Optional connectorTableMetadata = getTableMetadata(((SheetsTableHandle) table).toSchemaTableName()); + Optional connectorTableMetadata = getTableMetadata(session, ((SheetsTableHandle) table).toSchemaTableName()); if (!connectorTableMetadata.isPresent()) { throw new PrestoException(SHEETS_UNKNOWN_TABLE_ERROR, "Metadata not found for table " + ((SheetsTableHandle) table).getTableName()); } return connectorTableMetadata.get(); } - private Optional getTableMetadata(SchemaTableName tableName) + private Optional getTableMetadata(ConnectorSession session, SchemaTableName tableName) { if (!listSchemaNames().contains(tableName.getSchemaName())) { return Optional.empty(); } Optional table = sheetsClient.getTable(tableName.getTableName()); if (table.isPresent()) { - return Optional.of(new ConnectorTableMetadata(tableName, table.get().getColumnsMetadata())); + List columns = table.get().getColumnsMetadata().stream() + .map(column -> column.toBuilder() + .setName(normalizeIdentifier(session, column.getName())) + .build()) + .collect(toImmutableList()); + + return Optional.of(new ConnectorTableMetadata(tableName, columns)); } return Optional.empty(); } @@ -130,7 +136,13 @@ public Map getColumnHandles(ConnectorSession session, Conn ImmutableMap.Builder columnHandles = ImmutableMap.builder(); int index = 0; - for (ColumnMetadata column : table.get().getColumnsMetadata()) { + List columns = table.get().getColumnsMetadata().stream() + .map(column -> column.toBuilder() + .setName(normalizeIdentifier(session, column.getName())) + .build()) + .collect(toImmutableList()); + + for (ColumnMetadata column : columns) { columnHandles.put(column.getName(), new SheetsColumnHandle(column.getName(), column.getType(), index)); index++; } @@ -149,7 +161,7 @@ public Map> listTableColumns(ConnectorSess requireNonNull(prefix, "prefix is null"); ImmutableMap.Builder> columns = ImmutableMap.builder(); for (SchemaTableName tableName : listTables(session, Optional.of(prefix.getSchemaName()))) { - Optional tableMetadata = getTableMetadata(tableName); + Optional tableMetadata = getTableMetadata(session, tableName); // table can disappear during listing operation if (tableMetadata.isPresent()) { columns.put(tableName, tableMetadata.get().getColumns()); diff --git a/presto-hana/src/main/java/com/facebook/presto/plugin/hana/HanaClient.java b/presto-hana/src/main/java/com/facebook/presto/plugin/hana/HanaClient.java index 3873eb729f897..eb621be50a31e 100644 --- a/presto-hana/src/main/java/com/facebook/presto/plugin/hana/HanaClient.java +++ b/presto-hana/src/main/java/com/facebook/presto/plugin/hana/HanaClient.java @@ -145,4 +145,10 @@ private static String singleQuote(String literal) // HANA only accepts upper case return "\"" + literal.toUpperCase() + "\""; } + + @Override + public String normalizeIdentifier(ConnectorSession session, String identifier) + { + return caseSensitiveNameMatchingEnabled ? identifier : identifier.toLowerCase(ENGLISH); + } } diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/HiveColumnHandle.java b/presto-hive/src/main/java/com/facebook/presto/hive/HiveColumnHandle.java index 1e0bcb904cf07..ae0619790c6a1 100644 --- a/presto-hive/src/main/java/com/facebook/presto/hive/HiveColumnHandle.java +++ b/presto-hive/src/main/java/com/facebook/presto/hive/HiveColumnHandle.java @@ -145,6 +145,15 @@ public ColumnMetadata getColumnMetadata(TypeManager typeManager) .build(); } + public ColumnMetadata getColumnMetadata(TypeManager typeManager, String name) + { + return ColumnMetadata.builder() + .setName(name) + .setType(typeManager.getType(typeName)) + .setHidden(isHidden()) + .build(); + } + @JsonProperty public Optional getPartialAggregation() { diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/HiveMetadata.java b/presto-hive/src/main/java/com/facebook/presto/hive/HiveMetadata.java index 8f7e202fde63f..04e211b3c98ab 100644 --- a/presto-hive/src/main/java/com/facebook/presto/hive/HiveMetadata.java +++ b/presto-hive/src/main/java/com/facebook/presto/hive/HiveMetadata.java @@ -592,7 +592,7 @@ private Optional getPropertiesSystemTable(ConnectorSession session, } Map sortedTableParameters = ImmutableSortedMap.copyOf(table.get().getParameters()); List columns = sortedTableParameters.keySet().stream() - .map(key -> ColumnMetadata.builder().setName(key).setType(VARCHAR).build()) + .map(key -> ColumnMetadata.builder().setName(normalizeIdentifier(session, key)).setType(VARCHAR).build()) .collect(toImmutableList()); List types = columns.stream() .map(ColumnMetadata::getType) @@ -625,7 +625,7 @@ private Optional getPartitionsSystemTable(ConnectorSession session, List partitionSystemTableColumns = partitionColumns.stream() .map(column -> ColumnMetadata.builder() - .setName(column.getName()) + .setName(normalizeIdentifier(session, column.getName())) .setType(typeManager.getType(column.getTypeSignature())) .setComment(column.getComment().orElse(null)) .setHidden(column.isHidden()) @@ -2874,7 +2874,8 @@ public ConnectorTableLayout getTableLayout(ConnectorSession session, ConnectorTa // capture subfields from domainPredicate to add to remainingPredicate // so those filters don't get lost Map columnTypes = hiveColumnHandles(table).stream() - .collect(toImmutableMap(HiveColumnHandle::getName, columnHandle -> columnHandle.getColumnMetadata(typeManager).getType())); + .collect(toImmutableMap(HiveColumnHandle::getName, columnHandle -> columnHandle.getColumnMetadata(typeManager, + normalizeIdentifier(session, columnHandle.getName())).getType())); subfieldPredicate = getSubfieldPredicate(session, hiveLayoutHandle, columnTypes, functionResolution, rowExpressionService); } diff --git a/presto-hudi/src/main/java/com/facebook/presto/hudi/HudiColumnHandle.java b/presto-hudi/src/main/java/com/facebook/presto/hudi/HudiColumnHandle.java index 4d29649c7be28..4e5a1b6154392 100644 --- a/presto-hudi/src/main/java/com/facebook/presto/hudi/HudiColumnHandle.java +++ b/presto-hudi/src/main/java/com/facebook/presto/hudi/HudiColumnHandle.java @@ -123,6 +123,15 @@ public ColumnMetadata toColumnMetadata(TypeManager typeManager) .build(); } + public ColumnMetadata toColumnMetadata(TypeManager typeManager, String name) + { + return ColumnMetadata.builder() + .setName(name) + .setType(hiveType.getType(typeManager)) + .setExtraInfo(getExtraInfo().orElse(null)) + .build(); + } + @Override public String toString() { diff --git a/presto-hudi/src/main/java/com/facebook/presto/hudi/HudiMetadata.java b/presto-hudi/src/main/java/com/facebook/presto/hudi/HudiMetadata.java index dbbedd4feff9c..4e9c4e0248c5a 100644 --- a/presto-hudi/src/main/java/com/facebook/presto/hudi/HudiMetadata.java +++ b/presto-hudi/src/main/java/com/facebook/presto/hudi/HudiMetadata.java @@ -206,7 +206,7 @@ private ConnectorTableMetadata getTableMetadata(ConnectorSession session, Schema tableName.getTableName()).orElseThrow(() -> new TableNotFoundException(tableName)); List columnMetadatas = allColumnHandles(table) - .map(columnHandle -> columnHandle.toColumnMetadata(typeManager)) + .map(columnHandle -> columnHandle.toColumnMetadata(typeManager, normalizeIdentifier(session, columnHandle.getName()))) .collect(toList()); return new ConnectorTableMetadata(tableName, columnMetadatas); } diff --git a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergAbstractMetadata.java b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergAbstractMetadata.java index 035d7bcccd5b2..ec29d0aa07eca 100644 --- a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergAbstractMetadata.java +++ b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergAbstractMetadata.java @@ -430,7 +430,7 @@ protected ConnectorTableMetadata getTableOrViewMetadata(ConnectorSession session try { Table icebergTable = getIcebergTable(session, schemaTableName); ImmutableList.Builder columns = ImmutableList.builder(); - columns.addAll(getColumnMetadata(icebergTable)); + columns.addAll(getColumnMetadata(session, icebergTable)); if (icebergTableName.getTableType() == CHANGELOG) { return ChangelogUtil.getChangelogTableMeta(table, typeManager, columns.build()); } @@ -448,7 +448,7 @@ protected ConnectorTableMetadata getTableOrViewMetadata(ConnectorSession session // try to load it as a view when getting an `NoSuchTableException`. This will be more efficient. try { View icebergView = getIcebergView(session, schemaTableName); - return new ConnectorTableMetadata(table, getColumnMetadata(icebergView), createViewMetadataProperties(icebergView), getViewComment(icebergView)); + return new ConnectorTableMetadata(table, getColumnMetadata(session, icebergView), createViewMetadataProperties(icebergView), getViewComment(icebergView)); } catch (NoSuchViewException noSuchViewException) { throw new TableNotFoundException(schemaTableName); @@ -706,12 +706,12 @@ public boolean isLegacyGetLayoutSupported(ConnectorSession session, ConnectorTab return !isPushdownFilterEnabled(session); } - protected List getColumnMetadata(Table table) + protected List getColumnMetadata(ConnectorSession session, Table table) { Map> partitionFields = getPartitionFields(table.spec(), ALL); return table.schema().columns().stream() .map(column -> ColumnMetadata.builder() - .setName(column.name()) + .setName(normalizeIdentifier(session, column.name())) .setType(toPrestoType(column.type(), typeManager)) .setComment(column.doc()) .setHidden(false) @@ -722,11 +722,11 @@ protected List getColumnMetadata(Table table) .collect(toImmutableList()); } - protected List getColumnMetadata(View view) + protected List getColumnMetadata(ConnectorSession session, View view) { return view.schema().columns().stream() .map(column -> ColumnMetadata.builder() - .setName(column.name()) + .setName(normalizeIdentifier(session, column.name())) .setType(toPrestoType(column.type(), typeManager)) .setComment(column.doc()) .setHidden(false) @@ -927,7 +927,7 @@ public Map getColumnHandles(ConnectorSession session, Conn Table icebergTable = getIcebergTable(session, table.getSchemaTableName()); Schema schema; if (table.getIcebergTableName().getTableType() == CHANGELOG) { - schema = ChangelogUtil.changelogTableSchema(getRowTypeFromColumnMeta(getColumnMetadata(icebergTable))); + schema = ChangelogUtil.changelogTableSchema(getRowTypeFromColumnMeta(getColumnMetadata(session, icebergTable))); } else { schema = icebergTable.schema(); diff --git a/presto-jmx/src/main/java/com/facebook/presto/connector/jmx/JmxColumnHandle.java b/presto-jmx/src/main/java/com/facebook/presto/connector/jmx/JmxColumnHandle.java index ff3883e022f84..d30bac91441b4 100644 --- a/presto-jmx/src/main/java/com/facebook/presto/connector/jmx/JmxColumnHandle.java +++ b/presto-jmx/src/main/java/com/facebook/presto/connector/jmx/JmxColumnHandle.java @@ -87,4 +87,12 @@ public ColumnMetadata getColumnMetadata() .setType(columnType) .build(); } + + public ColumnMetadata getColumnMetadata(String name) + { + return ColumnMetadata.builder() + .setName(name) + .setType(columnType) + .build(); + } } diff --git a/presto-jmx/src/main/java/com/facebook/presto/connector/jmx/JmxMetadata.java b/presto-jmx/src/main/java/com/facebook/presto/connector/jmx/JmxMetadata.java index d67b76c046a64..d257c138e7a52 100644 --- a/presto-jmx/src/main/java/com/facebook/presto/connector/jmx/JmxMetadata.java +++ b/presto-jmx/src/main/java/com/facebook/presto/connector/jmx/JmxMetadata.java @@ -175,7 +175,22 @@ private Stream getColumnHandles(MBeanInfo mbeanInfo) @Override public ConnectorTableMetadata getTableMetadata(ConnectorSession session, ConnectorTableHandle tableHandle) { - return ((JmxTableHandle) tableHandle).getTableMetadata(); + JmxTableHandle jmxTableHandle = (JmxTableHandle) tableHandle; + return getTableMetadata(session, getTableName(jmxTableHandle), jmxTableHandle.getColumnHandles()); + } + + public ConnectorTableMetadata getTableMetadata(ConnectorSession session, SchemaTableName schemaTableName, List columnHandles) + { + List columns = columnHandles.stream() + .map(column -> column.getColumnMetadata(normalizeIdentifier(session, column.getColumnName()))) + .collect(toImmutableList()); + + return new ConnectorTableMetadata(schemaTableName, columns); + } + + private static SchemaTableName getTableName(ConnectorTableHandle tableHandle) + { + return ((JmxTableHandle) tableHandle).getTableName(); } @Override @@ -216,7 +231,7 @@ private List listJmxTables() public Map getColumnHandles(ConnectorSession session, ConnectorTableHandle tableHandle) { JmxTableHandle jmxTableHandle = (JmxTableHandle) tableHandle; - return ImmutableMap.copyOf(Maps.uniqueIndex(jmxTableHandle.getColumnHandles(), column -> column.getColumnName().toLowerCase(ENGLISH))); + return ImmutableMap.copyOf(Maps.uniqueIndex(jmxTableHandle.getColumnHandles(), column -> normalizeIdentifier(session, column.getColumnName()))); } @Override diff --git a/presto-kafka/src/main/java/com/facebook/presto/kafka/KafkaInternalFieldDescription.java b/presto-kafka/src/main/java/com/facebook/presto/kafka/KafkaInternalFieldDescription.java index 9de72206eb06c..8d4a42510d63f 100644 --- a/presto-kafka/src/main/java/com/facebook/presto/kafka/KafkaInternalFieldDescription.java +++ b/presto-kafka/src/main/java/com/facebook/presto/kafka/KafkaInternalFieldDescription.java @@ -131,10 +131,10 @@ KafkaColumnHandle getColumnHandle(String connectorId, int index, boolean hidden) true); } - ColumnMetadata getColumnMetadata(boolean hidden) + ColumnMetadata getColumnMetadata(boolean hidden, String name) { return ColumnMetadata.builder() - .setName(columnName) + .setName(name) .setType(type) .setComment(comment) .setHidden(hidden) diff --git a/presto-kafka/src/main/java/com/facebook/presto/kafka/KafkaMetadata.java b/presto-kafka/src/main/java/com/facebook/presto/kafka/KafkaMetadata.java index 468b3a29068b9..842f54f7825aa 100644 --- a/presto-kafka/src/main/java/com/facebook/presto/kafka/KafkaMetadata.java +++ b/presto-kafka/src/main/java/com/facebook/presto/kafka/KafkaMetadata.java @@ -113,7 +113,7 @@ private static String getDataFormat(Optional fieldGroup) @Override public ConnectorTableMetadata getTableMetadata(ConnectorSession session, ConnectorTableHandle tableHandle) { - return getTableMetadata(convertTableHandle(tableHandle).toSchemaTableName()); + return getTableMetadata(session, convertTableHandle(tableHandle).toSchemaTableName()); } @Override @@ -183,7 +183,7 @@ public Map> listTableColumns(ConnectorSess for (SchemaTableName tableName : tableNames) { try { - columns.put(tableName, getTableMetadata(tableName).getColumns()); + columns.put(tableName, getTableMetadata(session, tableName).getColumns()); } catch (TableNotFoundException e) { // Normally it would mean the table disappeared during listing operation @@ -234,7 +234,7 @@ public ConnectorTableLayout getTableLayout(ConnectorSession session, ConnectorTa return new ConnectorTableLayout(handle); } - private ConnectorTableMetadata getTableMetadata(SchemaTableName schemaTableName) + private ConnectorTableMetadata getTableMetadata(ConnectorSession session, SchemaTableName schemaTableName) { KafkaTopicDescription table = getRequiredTopicDescription(schemaTableName); @@ -244,7 +244,7 @@ private ConnectorTableMetadata getTableMetadata(SchemaTableName schemaTableName) List fields = key.getFields(); if (fields != null) { for (KafkaTopicFieldDescription fieldDescription : fields) { - builder.add(fieldDescription.getColumnMetadata()); + builder.add(fieldDescription.getColumnMetadata(normalizeIdentifier(session, fieldDescription.getName()))); } } }); @@ -253,13 +253,13 @@ private ConnectorTableMetadata getTableMetadata(SchemaTableName schemaTableName) List fields = message.getFields(); if (fields != null) { for (KafkaTopicFieldDescription fieldDescription : fields) { - builder.add(fieldDescription.getColumnMetadata()); + builder.add(fieldDescription.getColumnMetadata(normalizeIdentifier(session, fieldDescription.getName()))); } } }); for (KafkaInternalFieldDescription fieldDescription : KafkaInternalFieldDescription.values()) { - builder.add(fieldDescription.getColumnMetadata(hideInternalColumns)); + builder.add(fieldDescription.getColumnMetadata(hideInternalColumns, normalizeIdentifier(session, fieldDescription.getColumnName()))); } return new ConnectorTableMetadata(schemaTableName, builder.build()); diff --git a/presto-kafka/src/main/java/com/facebook/presto/kafka/KafkaTopicFieldDescription.java b/presto-kafka/src/main/java/com/facebook/presto/kafka/KafkaTopicFieldDescription.java index 73751a2091155..8ceb909bb5906 100644 --- a/presto-kafka/src/main/java/com/facebook/presto/kafka/KafkaTopicFieldDescription.java +++ b/presto-kafka/src/main/java/com/facebook/presto/kafka/KafkaTopicFieldDescription.java @@ -114,10 +114,10 @@ KafkaColumnHandle getColumnHandle(String connectorId, boolean keyCodec, int inde false); } - ColumnMetadata getColumnMetadata() + ColumnMetadata getColumnMetadata(String name) { return ColumnMetadata.builder() - .setName(getName()) + .setName(name) .setType(getType()) .setComment(getComment()) .setHidden(isHidden()) diff --git a/presto-kudu/src/main/java/com/facebook/presto/kudu/KuduMetadata.java b/presto-kudu/src/main/java/com/facebook/presto/kudu/KuduMetadata.java index b5f63ae0b1323..845e6e17fa8d7 100755 --- a/presto-kudu/src/main/java/com/facebook/presto/kudu/KuduMetadata.java +++ b/presto-kudu/src/main/java/com/facebook/presto/kudu/KuduMetadata.java @@ -100,14 +100,14 @@ public Map> listTableColumns(ConnectorSess for (SchemaTableName tableName : tables) { KuduTableHandle tableHandle = getTableHandle(session, tableName); if (tableHandle != null) { - ConnectorTableMetadata tableMetadata = getTableMetadata(tableHandle); + ConnectorTableMetadata tableMetadata = getTableMetadata(session, tableHandle); columns.put(tableName, tableMetadata.getColumns()); } } return columns.build(); } - private ColumnMetadata getColumnMetadata(ColumnSchema column) + private ColumnMetadata getColumnMetadata(ConnectorSession session, ColumnSchema column) { Map properties = new LinkedHashMap<>(); StringBuilder extra = new StringBuilder(); @@ -135,7 +135,7 @@ private ColumnMetadata getColumnMetadata(ColumnSchema column) Type prestoType = TypeHelper.fromKuduColumn(column); return ColumnMetadata.builder() - .setName(column.getName()) + .setName(normalizeIdentifier(session, column.getName())) .setType(prestoType) .setExtraInfo(extra.toString()) .setHidden(false) @@ -143,14 +143,14 @@ private ColumnMetadata getColumnMetadata(ColumnSchema column) .build(); } - private ConnectorTableMetadata getTableMetadata(KuduTableHandle tableHandle) + private ConnectorTableMetadata getTableMetadata(ConnectorSession session, KuduTableHandle tableHandle) { KuduTable table = tableHandle.getTable(clientSession); Schema schema = table.getSchema(); List columnsMetaList = schema.getColumns().stream() .filter(column -> !column.isKey() || !column.getName().equals(KuduColumnHandle.ROW_ID)) - .map(this::getColumnMetadata) + .map(column -> getColumnMetadata(session, column)) .collect(toImmutableList()); Map properties = clientSession.getTableProperties(tableHandle); @@ -225,7 +225,7 @@ public ConnectorTableLayout getTableLayout(ConnectorSession session, ConnectorTa public ConnectorTableMetadata getTableMetadata(ConnectorSession session, ConnectorTableHandle tableHandle) { KuduTableHandle kuduTableHandle = (KuduTableHandle) tableHandle; - return getTableMetadata(kuduTableHandle); + return getTableMetadata(session, kuduTableHandle); } @Override @@ -325,7 +325,7 @@ public ConnectorOutputTableHandle beginCreateTable(ConnectorSession session, Map columnProperties = new HashMap<>(); columnProperties.put(KuduTableProperties.PRIMARY_KEY, true); copy.add(0, ColumnMetadata.builder() - .setName(rowId) + .setName(normalizeIdentifier(session, rowId)) .setType(VARCHAR) .setComment("key=true") .setHidden(true) diff --git a/presto-lark-sheets/src/main/java/com/facebook/presto/lark/sheets/LarkSheetsColumnHandle.java b/presto-lark-sheets/src/main/java/com/facebook/presto/lark/sheets/LarkSheetsColumnHandle.java index e62306dcf2494..35dc5d0bd0186 100644 --- a/presto-lark-sheets/src/main/java/com/facebook/presto/lark/sheets/LarkSheetsColumnHandle.java +++ b/presto-lark-sheets/src/main/java/com/facebook/presto/lark/sheets/LarkSheetsColumnHandle.java @@ -61,6 +61,11 @@ public ColumnMetadata toColumnMetadata() return ColumnMetadata.builder().setName(name).setType(type).build(); } + public ColumnMetadata toColumnMetadata(String name) + { + return ColumnMetadata.builder().setName(name).setType(type).build(); + } + @Override public boolean equals(Object o) { diff --git a/presto-lark-sheets/src/main/java/com/facebook/presto/lark/sheets/LarkSheetsMetadata.java b/presto-lark-sheets/src/main/java/com/facebook/presto/lark/sheets/LarkSheetsMetadata.java index 33d48235df28e..a164da3b0aabb 100644 --- a/presto-lark-sheets/src/main/java/com/facebook/presto/lark/sheets/LarkSheetsMetadata.java +++ b/presto-lark-sheets/src/main/java/com/facebook/presto/lark/sheets/LarkSheetsMetadata.java @@ -149,7 +149,7 @@ public ConnectorTableMetadata getTableMetadata(ConnectorSession session, Connect { LarkSheetsTableHandle sheetsTable = (LarkSheetsTableHandle) table; List sheetsColumns = getColumns(sheetsTable); - List columnMetadatas = toColumnMetadatas(sheetsColumns); + List columnMetadatas = toColumnMetadatas(session, sheetsColumns); return new ConnectorTableMetadata(sheetsTable.getSchemaTableName(), columnMetadatas); } @@ -197,7 +197,7 @@ public Map> listTableColumns(ConnectorSess for (SheetInfo sheet : metaInfo.getSheets()) { SchemaTableName tableName = new SchemaTableName(schemaName, sheet.getTitle()); List columnHandles = getColumns(toSheetsTableHandle(sheet)); - List columnMetadatas = toColumnMetadatas(columnHandles); + List columnMetadatas = toColumnMetadatas(session, columnHandles); builder.put(tableName, columnMetadatas); } } @@ -209,7 +209,7 @@ public Map> listTableColumns(ConnectorSess // in order to make queries like `DESC "@sheetId"` or `DESC "#1"` work SchemaTableName tableName = new SchemaTableName(schemaName, prefixTableName); List columnHandles = getColumns(toSheetsTableHandle(sheet)); - List columnMetadatas = toColumnMetadatas(columnHandles); + List columnMetadatas = toColumnMetadatas(session, columnHandles); builder.put(tableName, columnMetadatas); } } @@ -337,8 +337,10 @@ private static LarkSheetsTableHandle toSheetsTableHandle(SheetInfo sheet) return new LarkSheetsTableHandle(sheet.getToken(), sheet.getSheetId(), sheet.getTitle(), sheet.getIndex(), sheet.getColumnCount(), sheet.getRowCount()); } - private static List toColumnMetadatas(List columnHandles) + private List toColumnMetadatas(ConnectorSession session, List columnHandles) { - return columnHandles.stream().map(LarkSheetsColumnHandle::toColumnMetadata).collect(toImmutableList()); + return columnHandles.stream() + .map(column -> column.toColumnMetadata(normalizeIdentifier(session, column.getName()))) + .collect(toImmutableList()); } } diff --git a/presto-main-base/src/main/java/com/facebook/presto/execution/AddColumnTask.java b/presto-main-base/src/main/java/com/facebook/presto/execution/AddColumnTask.java index c10e2d1694a01..3fbe29ff989a2 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/execution/AddColumnTask.java +++ b/presto-main-base/src/main/java/com/facebook/presto/execution/AddColumnTask.java @@ -29,6 +29,7 @@ import com.facebook.presto.sql.tree.AddColumn; import com.facebook.presto.sql.tree.ColumnDefinition; import com.facebook.presto.sql.tree.Expression; +import com.facebook.presto.sql.tree.Identifier; import com.facebook.presto.transaction.TransactionManager; import com.google.common.util.concurrent.ListenableFuture; @@ -114,8 +115,11 @@ public ListenableFuture execute(AddColumn statement, TransactionManager trans metadata, parameterExtractor(statement, parameters)); + Identifier columnIdentifier = element.getName(); + String name = metadata.normalizeIdentifier(session, tableName.getCatalogName(), columnIdentifier.getValue()); + ColumnMetadata column = ColumnMetadata.builder() - .setName(element.getName().getValue()) + .setName(name) .setType(type) .setNullable(element.isNullable()) .setComment(element.getComment().orElse(null)) diff --git a/presto-main-base/src/main/java/com/facebook/presto/execution/AlterColumnNotNullTask.java b/presto-main-base/src/main/java/com/facebook/presto/execution/AlterColumnNotNullTask.java index fdf78196c7a1a..851546b9fbf59 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/execution/AlterColumnNotNullTask.java +++ b/presto-main-base/src/main/java/com/facebook/presto/execution/AlterColumnNotNullTask.java @@ -82,8 +82,7 @@ public ListenableFuture execute(AlterColumnNotNull statement, TransactionMana } TableHandle tableHandle = tableHandleOptional.get(); - - String column = statement.getColumn().getValueLowerCase(); + String column = metadata.normalizeIdentifier(session, tableName.getCatalogName(), statement.getColumn().getValue()); accessControl.checkCanAddConstraints(session.getRequiredTransactionId(), session.getIdentity(), session.getAccessControlContext(), tableName); diff --git a/presto-main-base/src/main/java/com/facebook/presto/execution/CreateMaterializedViewTask.java b/presto-main-base/src/main/java/com/facebook/presto/execution/CreateMaterializedViewTask.java index 7fa707e6089aa..a17e67a0b7b97 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/execution/CreateMaterializedViewTask.java +++ b/presto-main-base/src/main/java/com/facebook/presto/execution/CreateMaterializedViewTask.java @@ -95,7 +95,7 @@ public ListenableFuture execute(CreateMaterializedView statement, Transaction List columnMetadata = analysis.getOutputDescriptor(statement.getQuery()) .getVisibleFields().stream() .map(field -> ColumnMetadata.builder() - .setName(field.getName().get()) + .setName(metadata.normalizeIdentifier(session, viewName.getCatalogName(), field.getName().get())) .setType(field.getType()) .build()) .collect(toImmutableList()); diff --git a/presto-main-base/src/main/java/com/facebook/presto/execution/CreateTableTask.java b/presto-main-base/src/main/java/com/facebook/presto/execution/CreateTableTask.java index f1c56285859c9..f2199283cf43b 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/execution/CreateTableTask.java +++ b/presto-main-base/src/main/java/com/facebook/presto/execution/CreateTableTask.java @@ -48,7 +48,6 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -121,7 +120,8 @@ public ListenableFuture internalExecute(CreateTable statement, Metadata metad for (TableElement element : statement.getElements()) { if (element instanceof ColumnDefinition) { ColumnDefinition column = (ColumnDefinition) element; - String name = column.getName().getValue().toLowerCase(Locale.ENGLISH); + String columnName = column.getName().getValue(); + String name = metadata.normalizeIdentifier(session, tableName.getCatalogName(), columnName); Type type; try { type = metadata.getType(parseTypeSignature(column.getType())); @@ -180,10 +180,10 @@ else if (element instanceof LikeClause) { likeTableMetadata.getColumns().stream() .filter(column -> !column.isHidden()) .forEach(column -> { - if (columns.containsKey(column.getName().toLowerCase(Locale.ENGLISH))) { + if (columns.containsKey(column.getName())) { throw new SemanticException(DUPLICATE_COLUMN_NAME, element, "Column name '%s' specified more than once", column.getName()); } - columns.put(column.getName().toLowerCase(Locale.ENGLISH), column); + columns.put(column.getName(), column); }); } else if (element instanceof ConstraintSpecification) { diff --git a/presto-main-base/src/main/java/com/facebook/presto/execution/CreateViewTask.java b/presto-main-base/src/main/java/com/facebook/presto/execution/CreateViewTask.java index 495b8368b006f..0e2b650e08e4c 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/execution/CreateViewTask.java +++ b/presto-main-base/src/main/java/com/facebook/presto/execution/CreateViewTask.java @@ -95,7 +95,7 @@ public ListenableFuture execute(CreateView statement, TransactionManager tran List columnMetadata = columns.stream() .map(column -> ColumnMetadata.builder() - .setName(column.getName()) + .setName(metadata.normalizeIdentifier(session, name.getCatalogName(), column.getName())) .setType(column.getType()) .build()) .collect(toImmutableList()); diff --git a/presto-main-base/src/main/java/com/facebook/presto/execution/DropColumnTask.java b/presto-main-base/src/main/java/com/facebook/presto/execution/DropColumnTask.java index fa7e418f940f3..1414786384b8e 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/execution/DropColumnTask.java +++ b/presto-main-base/src/main/java/com/facebook/presto/execution/DropColumnTask.java @@ -24,6 +24,7 @@ import com.facebook.presto.sql.analyzer.SemanticException; import com.facebook.presto.sql.tree.DropColumn; import com.facebook.presto.sql.tree.Expression; +import com.facebook.presto.sql.tree.Identifier; import com.facebook.presto.transaction.TransactionManager; import com.google.common.util.concurrent.ListenableFuture; @@ -67,7 +68,8 @@ public ListenableFuture execute(DropColumn statement, TransactionManager tran } TableHandle tableHandle = tableHandleOptional.get(); - String column = statement.getColumn().getValueLowerCase(); + Identifier columnIdentifier = statement.getColumn(); + String column = metadata.normalizeIdentifier(session, tableName.getCatalogName(), columnIdentifier.getValue()); accessControl.checkCanDropColumn(session.getRequiredTransactionId(), session.getIdentity(), session.getAccessControlContext(), tableName); diff --git a/presto-main-base/src/main/java/com/facebook/presto/execution/RenameColumnTask.java b/presto-main-base/src/main/java/com/facebook/presto/execution/RenameColumnTask.java index a8b48a1fb7239..6488deb47cf89 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/execution/RenameColumnTask.java +++ b/presto-main-base/src/main/java/com/facebook/presto/execution/RenameColumnTask.java @@ -23,6 +23,7 @@ import com.facebook.presto.spi.security.AccessControl; import com.facebook.presto.sql.analyzer.SemanticException; import com.facebook.presto.sql.tree.Expression; +import com.facebook.presto.sql.tree.Identifier; import com.facebook.presto.sql.tree.RenameColumn; import com.facebook.presto.transaction.TransactionManager; import com.google.common.util.concurrent.ListenableFuture; @@ -69,8 +70,10 @@ public ListenableFuture execute(RenameColumn statement, TransactionManager tr TableHandle tableHandle = tableHandleOptional.get(); - String source = statement.getSource().getValueLowerCase(); - String target = statement.getTarget().getValueLowerCase(); + Identifier sourceName = statement.getSource(); + String source = metadata.normalizeIdentifier(session, tableName.getCatalogName(), sourceName.getValue()); + Identifier targetName = statement.getTarget(); + String target = metadata.normalizeIdentifier(session, tableName.getCatalogName(), targetName.getValue()); accessControl.checkCanRenameColumn(session.getRequiredTransactionId(), session.getIdentity(), session.getAccessControlContext(), tableName); diff --git a/presto-main-base/src/main/java/com/facebook/presto/metadata/MetadataManager.java b/presto-main-base/src/main/java/com/facebook/presto/metadata/MetadataManager.java index ab5fb961c103c..a7cc33eeaf456 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/metadata/MetadataManager.java +++ b/presto-main-base/src/main/java/com/facebook/presto/metadata/MetadataManager.java @@ -106,6 +106,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.stream.Collectors; import static com.facebook.airlift.concurrent.MoreFutures.toListenableFuture; import static com.facebook.presto.SystemSessionProperties.isIgnoreStatsCalculatorFailures; @@ -530,7 +531,7 @@ public Map getColumnHandles(Session session, TableHandle t ImmutableMap.Builder map = ImmutableMap.builder(); for (Entry mapEntry : handles.entrySet()) { - map.put(mapEntry.getKey().toLowerCase(ENGLISH), mapEntry.getValue()); + map.put(normalizeIdentifier(session, connectorId.getCatalogName(), mapEntry.getKey()), mapEntry.getValue()); } return map.build(); } @@ -543,7 +544,10 @@ public ColumnMetadata getColumnMetadata(Session session, TableHandle tableHandle ConnectorId connectorId = tableHandle.getConnectorId(); ConnectorMetadata metadata = getMetadata(session, connectorId); - return metadata.getColumnMetadata(session.toConnectorSession(connectorId), tableHandle.getConnectorHandle(), columnHandle); + ColumnMetadata columnMetadata = metadata.getColumnMetadata(session.toConnectorSession(connectorId), tableHandle.getConnectorHandle(), columnHandle); + ColumnMetadata normalizedColumnMetadata = normalizedColumnMetadata(session, connectorId.getCatalogName(), columnMetadata); + + return normalizedColumnMetadata; } @Override @@ -598,7 +602,12 @@ public Map> listTableColumns(Session s prefix.getCatalogName(), entry.getKey().getSchemaName(), entry.getKey().getTableName()); - tableColumns.put(tableName, entry.getValue()); + + ImmutableList.Builder normalizedColumns = ImmutableList.builder(); + for (ColumnMetadata column : entry.getValue()) { + normalizedColumns.add(normalizedColumnMetadata(session, connectorId.getCatalogName(), column)); + } + tableColumns.put(tableName, normalizedColumns.build()); } // if table and view names overlap, the view wins @@ -611,7 +620,7 @@ public Map> listTableColumns(Session s ImmutableList.Builder columns = ImmutableList.builder(); for (ViewColumn column : deserializeView(entry.getValue().getViewData()).getColumns()) { columns.add(ColumnMetadata.builder() - .setName(column.getName()) + .setName(normalizeIdentifier(session, connectorId.getCatalogName(), column.getName())) .setType(column.getType()) .build()); } @@ -665,9 +674,13 @@ public TableHandle createTemporaryTable(Session session, String catalogName, Lis CatalogMetadata catalogMetadata = getCatalogMetadataForWrite(session, catalogName); ConnectorId connectorId = catalogMetadata.getConnectorId(); ConnectorMetadata metadata = catalogMetadata.getMetadata(); + List normalizedColumns = columns.stream() + .map(column -> normalizedColumnMetadata(session, connectorId.getCatalogName(), column)) + .collect(Collectors.toList()); + ConnectorTableHandle connectorTableHandle = metadata.createTemporaryTable( session.toConnectorSession(connectorId), - columns, + normalizedColumns, partitioningMetadata.map(partitioning -> createConnectorPartitioningMetadata(connectorId, partitioning))); return new TableHandle(connectorId, connectorTableHandle, catalogMetadata.getTransactionHandleFor(connectorId), Optional.empty()); } @@ -713,7 +726,7 @@ public void renameColumn(Session session, TableHandle tableHandle, ColumnHandle { ConnectorId connectorId = tableHandle.getConnectorId(); ConnectorMetadata metadata = getMetadataForWrite(session, connectorId); - metadata.renameColumn(session.toConnectorSession(connectorId), tableHandle.getConnectorHandle(), source, target.toLowerCase(ENGLISH)); + metadata.renameColumn(session.toConnectorSession(connectorId), tableHandle.getConnectorHandle(), source, normalizeIdentifier(session, connectorId.getCatalogName(), target)); } @Override @@ -1521,6 +1534,19 @@ public String normalizeIdentifier(Session session, String catalogName, String id return normalizedString; } + private ColumnMetadata normalizedColumnMetadata(Session session, String catalogName, ColumnMetadata columnMetadata) + { + return ColumnMetadata.builder() + .setName(normalizeIdentifier(session, catalogName, columnMetadata.getName())) + .setType(columnMetadata.getType()) + .setHidden(columnMetadata.isHidden()) + .setNullable(columnMetadata.isNullable()) + .setComment(columnMetadata.getComment().orElse(null)) + .setProperties(columnMetadata.getProperties()) + .setExtraInfo(columnMetadata.getExtraInfo().orElse(null)) + .build(); + } + private ViewDefinition deserializeView(String data) { try { diff --git a/presto-main-base/src/main/java/com/facebook/presto/sql/TemporaryTableUtil.java b/presto-main-base/src/main/java/com/facebook/presto/sql/TemporaryTableUtil.java index 7108270078d07..bc2b3d97805e8 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/sql/TemporaryTableUtil.java +++ b/presto-main-base/src/main/java/com/facebook/presto/sql/TemporaryTableUtil.java @@ -139,7 +139,11 @@ public static TableScanNode createTemporaryTableScan( cteId.map(CteMaterializationInfo::new)); } - public static Map assignTemporaryTableColumnNames(Collection outputVariables, + public static Map assignTemporaryTableColumnNames( + Metadata metadata, + Session session, + String catalogName, + Collection outputVariables, Collection constantPartitioningVariables) { ImmutableMap.Builder result = ImmutableMap.builder(); @@ -147,7 +151,7 @@ public static Map assignTemporaryTa for (VariableReferenceExpression outputVariable : concat(outputVariables, constantPartitioningVariables)) { String columnName = format("_c%d_%s", column, outputVariable.getName()); result.put(outputVariable, ColumnMetadata.builder() - .setName(columnName) + .setName(metadata.normalizeIdentifier(session, catalogName, columnName)) .setType(outputVariable.getType()) .build()); column++; @@ -155,9 +159,13 @@ public static Map assignTemporaryTa return result.build(); } - public static Map assignTemporaryTableColumnNames(Collection outputVariables) + public static Map assignTemporaryTableColumnNames( + Metadata metadata, + Session session, + String catalogName, + Collection outputVariables) { - return assignTemporaryTableColumnNames(outputVariables, Collections.emptyList()); + return assignTemporaryTableColumnNames(metadata, session, catalogName, outputVariables, Collections.emptyList()); } public static BasePlanFragmenter.PartitioningVariableAssignments assignPartitioningVariables(VariableAllocator variableAllocator, diff --git a/presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java b/presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java index 04f87c20bb89c..1b4f0567e1212 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java +++ b/presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java @@ -438,7 +438,7 @@ protected Scope visitInsert(Insert insert, Optional scope) if (insert.getColumns().isPresent()) { insertColumns = insert.getColumns().get().stream() .map(Identifier::getValue) - .map(column -> column.toLowerCase(ENGLISH)) + .map(column -> metadata.normalizeIdentifier(session, targetTable.getCatalogName(), column)) .collect(toImmutableList()); Set columnNames = new HashSet<>(); diff --git a/presto-main-base/src/main/java/com/facebook/presto/sql/planner/BasePlanFragmenter.java b/presto-main-base/src/main/java/com/facebook/presto/sql/planner/BasePlanFragmenter.java index 927f6ca7e6a11..bc77373a5ecbd 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/sql/planner/BasePlanFragmenter.java +++ b/presto-main-base/src/main/java/com/facebook/presto/sql/planner/BasePlanFragmenter.java @@ -283,7 +283,7 @@ public PlanNode visitExchange(ExchangeNode exchange, RewriteContext context) + private PlanNode createRemoteMaterializedExchange(Metadata metadata, Session session, ExchangeNode exchange, RewriteContext context) { checkArgument(exchange.getType() == REPARTITION, "Unexpected exchange type: %s", exchange.getType()); checkArgument(exchange.getScope() == REMOTE_MATERIALIZED, "Unexpected exchange scope: %s", exchange.getScope()); @@ -352,7 +352,8 @@ private PlanNode createRemoteMaterializedExchange(ExchangeNode exchange, Rewrite Partitioning partitioning = partitioningScheme.getPartitioning(); PartitioningVariableAssignments partitioningVariableAssignments = assignPartitioningVariables(variableAllocator, partitioning); - Map variableToColumnMap = assignTemporaryTableColumnNames(exchange.getOutputVariables(), partitioningVariableAssignments.getConstants().keySet()); + Map variableToColumnMap = assignTemporaryTableColumnNames(metadata, + session, connectorId.getCatalogName(), exchange.getOutputVariables(), partitioningVariableAssignments.getConstants().keySet()); List partitioningVariables = partitioningVariableAssignments.getVariables(); List partitionColumns = partitioningVariables.stream() .map(variable -> variableToColumnMap.get(variable).getName()) diff --git a/presto-main-base/src/main/java/com/facebook/presto/sql/planner/LogicalPlanner.java b/presto-main-base/src/main/java/com/facebook/presto/sql/planner/LogicalPlanner.java index 4f2f6b826b221..cf748ba0eb44e 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/sql/planner/LogicalPlanner.java +++ b/presto-main-base/src/main/java/com/facebook/presto/sql/planner/LogicalPlanner.java @@ -271,7 +271,7 @@ private RelationPlan createTableCreationPlan(Analysis analysis, Query query) ConnectorTableMetadata tableMetadata = createTableMetadata( destination, - getOutputTableColumns(plan, analysis.getColumnAliases()), + getOutputTableColumns(metadata, session, destination.getCatalogName(), plan, analysis.getColumnAliases()), analysis.getCreateTableProperties(), analysis.getParameters(), analysis.getCreateTableComment()); @@ -589,14 +589,14 @@ private RowExpression rowExpression(Expression expression, SqlPlannerContext con context.getTranslatorContext()); } - private static List getOutputTableColumns(RelationPlan plan, Optional> columnAliases) + private static List getOutputTableColumns(Metadata metadata, Session session, String catalogName, RelationPlan plan, Optional> columnAliases) { ImmutableList.Builder columns = ImmutableList.builder(); int aliasPosition = 0; for (Field field : plan.getDescriptor().getVisibleFields()) { String columnName = columnAliases.isPresent() ? columnAliases.get().get(aliasPosition).getValue() : field.getName().get(); columns.add(ColumnMetadata.builder() - .setName(columnName) + .setName(metadata.normalizeIdentifier(session, catalogName, columnName)) .setType(field.getType()) .build()); aliasPosition++; diff --git a/presto-main-base/src/main/java/com/facebook/presto/sql/planner/optimizations/PhysicalCteOptimizer.java b/presto-main-base/src/main/java/com/facebook/presto/sql/planner/optimizations/PhysicalCteOptimizer.java index 91f2c36d1099f..d18cbcd4f1ab7 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/sql/planner/optimizations/PhysicalCteOptimizer.java +++ b/presto-main-base/src/main/java/com/facebook/presto/sql/planner/optimizations/PhysicalCteOptimizer.java @@ -120,7 +120,7 @@ public PlanNode visitCteProducer(CteProducerNode node, RewriteContext variableToColumnMap = - assignTemporaryTableColumnNames(actualSource.getOutputVariables()); + assignTemporaryTableColumnNames(metadata, session, partitioningProviderCatalog, actualSource.getOutputVariables()); TableHandle temporaryTableHandle; try { temporaryTableHandle = metadata.createTemporaryTable( diff --git a/presto-main-base/src/main/java/com/facebook/presto/testing/TestingMetadata.java b/presto-main-base/src/main/java/com/facebook/presto/testing/TestingMetadata.java index 0c84187591563..0cdd1bdbd1641 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/testing/TestingMetadata.java +++ b/presto-main-base/src/main/java/com/facebook/presto/testing/TestingMetadata.java @@ -146,7 +146,7 @@ public Map> listTableColumns(ConnectorSess ImmutableList.Builder columns = ImmutableList.builder(); for (ColumnMetadata column : tables.get(tableName).getColumns()) { columns.add(ColumnMetadata.builder() - .setName(column.getName()) + .setName(normalizeIdentifier(session, column.getName())) .setType(column.getType()) .build()); } @@ -289,7 +289,7 @@ public void renameColumn(ConnectorSession session, ConnectorTableHandle tableHan ColumnMetadata columnMetadata = getColumnMetadata(session, tableHandle, source); List columns = new ArrayList<>(tableMetadata.getColumns()); columns.set(columns.indexOf(columnMetadata), ColumnMetadata.builder() - .setName(target) + .setName(normalizeIdentifier(session, target)) .setType(columnMetadata.getType()) .setComment(columnMetadata.getComment().orElse(null)) .setHidden(columnMetadata.isHidden()) diff --git a/presto-memory/src/main/java/com/facebook/presto/plugin/memory/MemoryColumnHandle.java b/presto-memory/src/main/java/com/facebook/presto/plugin/memory/MemoryColumnHandle.java index bf0fb7a3cc33d..b440acd42ae1f 100644 --- a/presto-memory/src/main/java/com/facebook/presto/plugin/memory/MemoryColumnHandle.java +++ b/presto-memory/src/main/java/com/facebook/presto/plugin/memory/MemoryColumnHandle.java @@ -75,6 +75,14 @@ public ColumnMetadata toColumnMetadata() .build(); } + public ColumnMetadata toColumnMetadata(String name) + { + return ColumnMetadata.builder() + .setName(name) + .setType(columnType) + .build(); + } + @Override public int hashCode() { diff --git a/presto-memory/src/main/java/com/facebook/presto/plugin/memory/MemoryMetadata.java b/presto-memory/src/main/java/com/facebook/presto/plugin/memory/MemoryMetadata.java index b600eabc8ea16..620f2da4aae29 100644 --- a/presto-memory/src/main/java/com/facebook/presto/plugin/memory/MemoryMetadata.java +++ b/presto-memory/src/main/java/com/facebook/presto/plugin/memory/MemoryMetadata.java @@ -169,7 +169,16 @@ public synchronized Map> listTableColumns( { return tables.values().stream() .filter(table -> prefix.matches(table.toSchemaTableName())) - .collect(toMap(MemoryTableHandle::toSchemaTableName, handle -> handle.toTableMetadata().getColumns())); + .collect(toImmutableMap(MemoryTableHandle::toSchemaTableName, handle -> toTableMetadata(handle, session).getColumns())); + } + + public ConnectorTableMetadata toTableMetadata(MemoryTableHandle memoryTableHandle, ConnectorSession session) + { + List columns = memoryTableHandle.getColumnHandles().stream() + .map(column -> column.toColumnMetadata(normalizeIdentifier(session, column.getName()))) + .collect(toImmutableList()); + + return new ConnectorTableMetadata(memoryTableHandle.toSchemaTableName(), columns); } @Override diff --git a/presto-mongodb/src/main/java/com/facebook/presto/mongodb/MongoColumnHandle.java b/presto-mongodb/src/main/java/com/facebook/presto/mongodb/MongoColumnHandle.java index 582ff78bbfe5f..909ff6bc27fbb 100644 --- a/presto-mongodb/src/main/java/com/facebook/presto/mongodb/MongoColumnHandle.java +++ b/presto-mongodb/src/main/java/com/facebook/presto/mongodb/MongoColumnHandle.java @@ -72,6 +72,15 @@ public ColumnMetadata toColumnMetadata() .build(); } + public ColumnMetadata toColumnMetadata(String name) + { + return ColumnMetadata.builder() + .setName(name) + .setType(type) + .setHidden(hidden) + .build(); + } + public Document getDocument() { return new Document().append("name", name) diff --git a/presto-mongodb/src/main/java/com/facebook/presto/mongodb/MongoMetadata.java b/presto-mongodb/src/main/java/com/facebook/presto/mongodb/MongoMetadata.java index a7868852e55f0..1a75bcfe2feea 100644 --- a/presto-mongodb/src/main/java/com/facebook/presto/mongodb/MongoMetadata.java +++ b/presto-mongodb/src/main/java/com/facebook/presto/mongodb/MongoMetadata.java @@ -281,7 +281,7 @@ private ConnectorTableMetadata getTableMetadata(ConnectorSession session, Schema List columns = ImmutableList.copyOf( getColumnHandles(session, tableHandle).values().stream() .map(MongoColumnHandle.class::cast) - .map(MongoColumnHandle::toColumnMetadata) + .map(column -> column.toColumnMetadata(normalizeIdentifier(session, column.getName()))) .collect(toList())); return new ConnectorTableMetadata(tableName, columns); diff --git a/presto-mysql/src/test/java/com/facebook/presto/plugin/mysql/TestMySqlIntegrationMixedCaseTest.java b/presto-mysql/src/test/java/com/facebook/presto/plugin/mysql/TestMySqlIntegrationMixedCaseTest.java index 9af93187a1824..16be5f5f981ad 100644 --- a/presto-mysql/src/test/java/com/facebook/presto/plugin/mysql/TestMySqlIntegrationMixedCaseTest.java +++ b/presto-mysql/src/test/java/com/facebook/presto/plugin/mysql/TestMySqlIntegrationMixedCaseTest.java @@ -187,11 +187,11 @@ public void testDuplicatedRowCreateTable() "line 1:49: Column name 'orderkey' specified more than once"); assertQueryFails("CREATE TABLE test (a integer, A integer)", - "line 1:31: Column name 'A' specified more than once"); + "Duplicate column name 'A'"); assertQueryFails("CREATE TABLE TEST (a integer, A integer)", - "line 1:31: Column name 'A' specified more than once"); + "Duplicate column name 'A'"); assertQueryFails("CREATE TABLE test (a integer, OrderKey integer, LIKE orders INCLUDING PROPERTIES)", - "line 1:49: Column name 'orderkey' specified more than once"); + "Duplicate column name 'orderkey'"); } private void execute(String sql) diff --git a/presto-oracle/src/main/java/com/facebook/presto/plugin/oracle/OracleClient.java b/presto-oracle/src/main/java/com/facebook/presto/plugin/oracle/OracleClient.java index 67149ff9b4405..d5713fb2595a2 100644 --- a/presto-oracle/src/main/java/com/facebook/presto/plugin/oracle/OracleClient.java +++ b/presto-oracle/src/main/java/com/facebook/presto/plugin/oracle/OracleClient.java @@ -167,4 +167,10 @@ public Optional toPrestoType(ConnectorSession session, JdbcTypeHand } return super.toPrestoType(session, typeHandle); } + + @Override + public String normalizeIdentifier(ConnectorSession session, String identifier) + { + return caseSensitiveNameMatchingEnabled ? identifier : identifier.toLowerCase(ENGLISH); + } } diff --git a/presto-postgresql/src/main/java/com/facebook/presto/plugin/postgresql/PostgreSqlClient.java b/presto-postgresql/src/main/java/com/facebook/presto/plugin/postgresql/PostgreSqlClient.java index 01214d57d70e4..b6e2be78eb1bf 100644 --- a/presto-postgresql/src/main/java/com/facebook/presto/plugin/postgresql/PostgreSqlClient.java +++ b/presto-postgresql/src/main/java/com/facebook/presto/plugin/postgresql/PostgreSqlClient.java @@ -62,6 +62,7 @@ import static java.lang.Long.reverseBytes; import static java.lang.String.format; import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.Locale.ENGLISH; public class PostgreSqlClient extends BaseJdbcClient @@ -201,4 +202,10 @@ private static Slice uuidSlice(UUID uuid) reverseBytes(uuid.getMostSignificantBits()), reverseBytes(uuid.getLeastSignificantBits())); } + + @Override + public String normalizeIdentifier(ConnectorSession session, String identifier) + { + return caseSensitiveNameMatchingEnabled ? identifier : identifier.toLowerCase(ENGLISH); + } } diff --git a/presto-product-tests/src/main/java/com/facebook/presto/tests/hive/TestHiveMixedCaseSupport.java b/presto-product-tests/src/main/java/com/facebook/presto/tests/hive/TestHiveMixedCaseSupport.java index 8d3acea1fce70..06c6ef486095b 100644 --- a/presto-product-tests/src/main/java/com/facebook/presto/tests/hive/TestHiveMixedCaseSupport.java +++ b/presto-product-tests/src/main/java/com/facebook/presto/tests/hive/TestHiveMixedCaseSupport.java @@ -128,12 +128,16 @@ public void testInsertDataWithMixedCaseNames() assertThat(query("SELECT * FROM " + SCHEMA_NAME + ".testtable")) .containsOnly(row("amy", 112), row("mia", 123)); + assertThat(query("SELECT name, ID FROM " + SCHEMA_NAME + ".testtable")) + .containsOnly(row("amy", 112), row("mia", 123)); assertThat(query("SELECT * FROM " + SCHEMA_NAME + ".TESTTABLE2")) .containsOnly(row("ann", 112), row("mary", 123)); assertThat(query("SELECT * FROM " + SCHEMA_NAME_UPPER + ".testtable02")) .containsOnly(row("emma", 112, 200.002), row("mark", 123, 300.003)); assertThat(query("SELECT * FROM " + SCHEMA_NAME_UPPER + ".TESTTABLE3")) .containsOnly(row("emma", 112, 200.002), row("mark", 123, 300.003)); + assertThat(query("SELECT name, ID, NUM FROM " + SCHEMA_NAME_UPPER + ".TESTTABLE3")) + .containsOnly(row("emma", 112, 200.002), row("mark", 123, 300.003)); assertThat(query("SELECT * FROM \"" + SCHEMA_NAME_MIXED + "\".\"TestTable\"")).containsOnly( row("amy1", 112), row("mary1", 123), @@ -151,26 +155,73 @@ public void testInsertDataWithMixedCaseNames() public void testTableAlterWithMixedCaseNames() { query("ALTER TABLE " + SCHEMA_NAME + ".testtable ADD COLUMN num REAL"); - query("ALTER TABLE " + SCHEMA_NAME_UPPER + ".testtable02 ADD COLUMN num1 REAL"); + query("ALTER TABLE " + SCHEMA_NAME + ".testtable ADD COLUMN NuM2 REAL"); + query("ALTER TABLE " + SCHEMA_NAME + ".TESTTABLE2 ADD COLUMN num01 REAL"); - query("ALTER TABLE " + SCHEMA_NAME_UPPER + ".TESTTABLE02 ADD COLUMN num2 REAL"); + query("ALTER TABLE " + SCHEMA_NAME + ".TESTTABLE2 ADD COLUMN NuM2 REAL"); - assertThat(query("DESCRIBE " + SCHEMA_NAME + ".testtable")) - .contains(row("num", "real", "", "")); - assertThat(query("DESCRIBE " + SCHEMA_NAME_UPPER + ".testtable02")) - .contains(row("num1", "real", "", "")); - assertThat(query("DESCRIBE " + SCHEMA_NAME + ".TESTTABLE2")) - .contains(row("num01", "real", "", "")); - assertThat(query("DESCRIBE " + SCHEMA_NAME_UPPER + ".TESTTABLE02")) - .contains(row("num2", "real", "", "")); + query("ALTER TABLE " + SCHEMA_NAME_UPPER + ".testtable02 ADD COLUMN num1 REAL"); + query("ALTER TABLE " + SCHEMA_NAME_UPPER + ".TESTTABLE02 ADD COLUMN NuM2 REAL"); + // Negative test: Creating a duplicate column with different case should fail in mysql + assertThat(() -> query("ALTER TABLE " + SCHEMA_NAME_UPPER + ".TESTTABLE02 ADD COLUMN num2 REAL")) + .failsWithMessage("line 1:1: Column 'num2' already exists"); + + assertThat(query("DESCRIBE " + SCHEMA_NAME + ".testtable")).containsOnly( + row("name", "varchar(50)", "", ""), + row("id", "integer", "", ""), + row("num", "real", "", ""), + row("num2", "real", "", "")); + + assertThat(query("DESCRIBE " + SCHEMA_NAME + ".TESTTABLE2")).containsOnly( + row("name", "varchar(50)", "", ""), + row("id", "integer", "", ""), + row("num01", "real", "", ""), + row("num2", "real", "", "")); + + assertThat(query("DESCRIBE " + SCHEMA_NAME_UPPER + ".testtable02")).containsOnly( + row("name", "varchar(50)", "", ""), + row("id", "integer", "", ""), + row("num", "double", "", ""), + row("num1", "real", "", ""), + row("num2", "real", "", "")); + + assertThat(query("DESCRIBE " + SCHEMA_NAME_UPPER + ".TESTTABLE02")).containsOnly( + row("name", "varchar(50)", "", ""), + row("id", "integer", "", ""), + row("num", "double", "", ""), + row("num1", "real", "", ""), + row("num2", "real", "", "")); query("ALTER TABLE " + SCHEMA_NAME + ".testtable RENAME COLUMN num TO numb"); + query("ALTER TABLE " + SCHEMA_NAME + ".testtable RENAME COLUMN NuM2 TO NuM02"); query("ALTER TABLE " + SCHEMA_NAME_UPPER + ".testtable02 RENAME COLUMN num1 TO numb01"); - - assertThat(query("DESCRIBE " + SCHEMA_NAME + ".testtable")) - .contains(row("numb", "real", "", "")); - assertThat(query("DESCRIBE " + SCHEMA_NAME_UPPER + ".testtable02")) - .contains(row("numb01", "real", "", "")); + query("ALTER TABLE " + SCHEMA_NAME_UPPER + ".testtable02 RENAME COLUMN NuM2 TO NuM02"); + + assertThat(query("DESCRIBE " + SCHEMA_NAME + ".testtable")).containsOnly( + row("name", "varchar(50)", "", ""), + row("id", "integer", "", ""), + row("numb", "real", "", ""), + row("num02", "real", "", "")); + assertThat(query("DESCRIBE " + SCHEMA_NAME_UPPER + ".testtable02")).containsOnly( + row("name", "varchar(50)", "", ""), + row("id", "integer", "", ""), + row("num", "double", "", ""), + row("numb01", "real", "", ""), + row("num02", "real", "", "")); + + // drop column + query("ALTER TABLE " + SCHEMA_NAME + ".testtable DROP COLUMN NuM02"); + query("ALTER TABLE " + SCHEMA_NAME_UPPER + ".testtable02 DROP COLUMN numb01"); + + assertThat(query("DESCRIBE " + SCHEMA_NAME + ".testtable")).containsOnly( + row("name", "varchar(50)", "", ""), + row("id", "integer", "", ""), + row("numb", "real", "", "")); + assertThat(query("DESCRIBE " + SCHEMA_NAME_UPPER + ".testtable02")).containsOnly( + row("name", "varchar(50)", "", ""), + row("id", "integer", "", ""), + row("num", "double", "", ""), + row("num02", "real", "", "")); } @Test(groups = {MIXED_CASE}, dependsOnMethods = "testTableAlterWithMixedCaseNames") diff --git a/presto-product-tests/src/main/java/com/facebook/presto/tests/mysql/TestMySQLMixedCaseSupportOff.java b/presto-product-tests/src/main/java/com/facebook/presto/tests/mysql/TestMySQLMixedCaseSupportOff.java index b70aea36fab8f..c154ed5b290b0 100644 --- a/presto-product-tests/src/main/java/com/facebook/presto/tests/mysql/TestMySQLMixedCaseSupportOff.java +++ b/presto-product-tests/src/main/java/com/facebook/presto/tests/mysql/TestMySQLMixedCaseSupportOff.java @@ -76,6 +76,10 @@ public void testInsertDataWithMixedCaseNames() assertThat(query("SELECT * FROM " + CATALOG + "." + SCHEMA_NAME + "." + TABLE_NAME)) .containsOnly(row("amy", 112), row("mia", 123)); + // Even if we define a column as ID, we can refer to it as id, ID, or anything else in any case — with or without backticks. + assertThat(query("SELECT name, id FROM " + CATALOG + "." + SCHEMA_NAME + "." + TABLE_NAME)) + .containsOnly(row("amy", 112), row("mia", 123)); + assertThat(query("SELECT * FROM " + CATALOG + "." + SCHEMA_NAME + "." + TABLE_NAME_UPPER_2)) .containsOnly(row("ann", 112), row("mary", 123)); @@ -102,26 +106,70 @@ public void testInsertDataWithMixedCaseNames() public void testTableAlterWithMixedCaseNames() { query("ALTER TABLE " + CATALOG + "." + SCHEMA_NAME + "." + TABLE_NAME + " ADD COLUMN num REAL"); - query("ALTER TABLE " + CATALOG + "." + SCHEMA_NAME_UPPER + "." + TABLE_NAME_UPPER_SCHEMA_02 + " ADD COLUMN num1 REAL"); + query("ALTER TABLE " + CATALOG + "." + SCHEMA_NAME + "." + TABLE_NAME + " ADD COLUMN NuM2 REAL"); + query("ALTER TABLE " + CATALOG + "." + SCHEMA_NAME + "." + TABLE_NAME_UPPER_2 + " ADD COLUMN num01 REAL"); - query("ALTER TABLE " + CATALOG + "." + SCHEMA_NAME_UPPER + "." + TABLE_NAME_UPPER_SCHEMA_02.toUpperCase() + " ADD COLUMN num2 REAL"); + query("ALTER TABLE " + CATALOG + "." + SCHEMA_NAME + "." + TABLE_NAME_UPPER_2 + " ADD COLUMN NuM2 REAL"); - assertThat(query("DESCRIBE " + CATALOG + "." + SCHEMA_NAME + "." + TABLE_NAME)) - .contains(row("num", "real", "", "")); - assertThat(query("DESCRIBE " + CATALOG + "." + SCHEMA_NAME_UPPER + "." + TABLE_NAME_UPPER_SCHEMA_02)) - .contains(row("num1", "real", "", "")); - assertThat(query("DESCRIBE " + CATALOG + "." + SCHEMA_NAME + "." + TABLE_NAME_UPPER_2)) - .contains(row("num01", "real", "", "")); - assertThat(query("DESCRIBE " + CATALOG + "." + SCHEMA_NAME_UPPER + "." + TABLE_NAME_UPPER_SCHEMA_02.toUpperCase())) - .contains(row("num2", "real", "", "")); + query("ALTER TABLE " + CATALOG + "." + SCHEMA_NAME_UPPER + "." + TABLE_NAME_UPPER_SCHEMA_02 + " ADD COLUMN num1 REAL"); + query("ALTER TABLE " + CATALOG + "." + SCHEMA_NAME_UPPER + "." + TABLE_NAME_UPPER_SCHEMA_02.toUpperCase() + " ADD COLUMN num2 REAL"); + // Negative test: Creating a duplicate column with different case should fail in mysql + assertThat(() -> query("ALTER TABLE " + CATALOG + "." + SCHEMA_NAME_UPPER + "." + TABLE_NAME_UPPER_SCHEMA_02 + " ADD COLUMN NuM2 REAL")) + .failsWithMessage("line 1:1: Column 'NuM2' already exists"); + + assertThat(query("DESCRIBE " + CATALOG + "." + SCHEMA_NAME + "." + TABLE_NAME)).containsOnly( + row("name", "varchar(255)", "", ""), + row("id", "integer", "", ""), + row("num", "real", "", ""), + row("num2", "real", "", "")); + assertThat(query("DESCRIBE " + CATALOG + "." + SCHEMA_NAME + "." + TABLE_NAME_UPPER_2)).containsOnly( + row("name", "varchar(255)", "", ""), + row("id", "integer", "", ""), + row("num01", "real", "", ""), + row("num2", "real", "", "")); + assertThat(query("DESCRIBE " + CATALOG + "." + SCHEMA_NAME_UPPER + "." + TABLE_NAME_UPPER_SCHEMA_02)).containsOnly( + row("name", "varchar(255)", "", ""), + row("id", "integer", "", ""), + row("num", "double", "", ""), + row("num1", "real", "", ""), + row("num2", "real", "", "")); + assertThat(query("DESCRIBE " + CATALOG + "." + SCHEMA_NAME_UPPER + "." + TABLE_NAME_UPPER_SCHEMA_02.toUpperCase())).containsOnly( + row("name", "varchar(255)", "", ""), + row("id", "integer", "", ""), + row("num", "double", "", ""), + row("num1", "real", "", ""), + row("num2", "real", "", "")); query("ALTER TABLE " + CATALOG + "." + SCHEMA_NAME + "." + TABLE_NAME + " RENAME COLUMN num TO numb"); + query("ALTER TABLE " + CATALOG + "." + SCHEMA_NAME + "." + TABLE_NAME + " RENAME COLUMN NuM2 TO NuM02"); query("ALTER TABLE " + CATALOG + "." + SCHEMA_NAME_UPPER + "." + TABLE_NAME_UPPER_SCHEMA_02 + " RENAME COLUMN num1 TO numb01"); - - assertThat(query("DESCRIBE " + CATALOG + "." + SCHEMA_NAME + "." + TABLE_NAME)) - .contains(row("numb", "real", "", "")); - assertThat(query("DESCRIBE " + CATALOG + "." + SCHEMA_NAME_UPPER + "." + TABLE_NAME_UPPER_SCHEMA_02)) - .contains(row("numb01", "real", "", "")); + query("ALTER TABLE " + CATALOG + "." + SCHEMA_NAME_UPPER + "." + TABLE_NAME_UPPER_SCHEMA_02 + " RENAME COLUMN NuM2 TO NuM02"); + + assertThat(query("DESCRIBE " + CATALOG + "." + SCHEMA_NAME + "." + TABLE_NAME)).containsOnly( + row("name", "varchar(255)", "", ""), + row("id", "integer", "", ""), + row("numb", "real", "", ""), + row("num02", "real", "", "")); + assertThat(query("DESCRIBE " + CATALOG + "." + SCHEMA_NAME_UPPER + "." + TABLE_NAME_UPPER_SCHEMA_02)).containsOnly( + row("name", "varchar(255)", "", ""), + row("id", "integer", "", ""), + row("num", "double", "", ""), + row("numb01", "real", "", ""), + row("num02", "real", "", "")); + + // drop column + query("ALTER TABLE " + CATALOG + "." + SCHEMA_NAME + "." + TABLE_NAME + " DROP COLUMN NuM02"); + query("ALTER TABLE " + CATALOG + "." + SCHEMA_NAME_UPPER + "." + TABLE_NAME_UPPER_SCHEMA_02 + " DROP COLUMN numb01"); + + assertThat(query("DESCRIBE " + CATALOG + "." + SCHEMA_NAME + "." + TABLE_NAME)).containsOnly( + row("name", "varchar(255)", "", ""), + row("id", "integer", "", ""), + row("numb", "real", "", "")); + assertThat(query("DESCRIBE " + CATALOG + "." + SCHEMA_NAME_UPPER + "." + TABLE_NAME_UPPER_SCHEMA_02)).containsOnly( + row("name", "varchar(255)", "", ""), + row("id", "integer", "", ""), + row("num", "double", "", ""), + row("num02", "real", "", "")); } @Test(groups = {MYSQL}, dependsOnMethods = "testTableAlterWithMixedCaseNames") diff --git a/presto-product-tests/src/main/java/com/facebook/presto/tests/mysql/TestMySQLMixedCaseSupportOn.java b/presto-product-tests/src/main/java/com/facebook/presto/tests/mysql/TestMySQLMixedCaseSupportOn.java index a4bddeed2abbd..196653fce831c 100644 --- a/presto-product-tests/src/main/java/com/facebook/presto/tests/mysql/TestMySQLMixedCaseSupportOn.java +++ b/presto-product-tests/src/main/java/com/facebook/presto/tests/mysql/TestMySQLMixedCaseSupportOn.java @@ -21,6 +21,7 @@ import static io.prestodb.tempto.assertions.QueryAssert.Row.row; import static io.prestodb.tempto.assertions.QueryAssert.assertThat; import static io.prestodb.tempto.query.QueryExecutor.query; + public class TestMySQLMixedCaseSupportOn extends ProductTest { @@ -140,7 +141,11 @@ public void testInsertDataIntoExistingMixedCaseTables() @Test(groups = {MYSQL_MIXED_CASE}, dependsOnMethods = "testInsertDataIntoExistingMixedCaseTables") public void testSelectDataWithMixedCaseNames() { - assertThat(query("SELECT * FROM " + CATALOG + ".\"" + SCHEMA_NAME + "\".\"" + TABLE_NAME + "\"")) + assertThat(query("SELECT name, ID FROM " + CATALOG + ".\"" + SCHEMA_NAME + "\".\"" + TABLE_NAME + "\"")) + .containsOnly(row("eva", 301), row("lisa", 302), row("ivan", 401), row("nora", 402), row("eva", 301), row("lisa", 302)); + + // Even if we define a column as ID, we can refer to it as id, ID, or anything else in any case — with or without backticks. + assertThat(query("SELECT name, id FROM " + CATALOG + "." + SCHEMA_NAME + "." + TABLE_NAME)) .containsOnly(row("eva", 301), row("lisa", 302), row("ivan", 401), row("nora", 402), row("eva", 301), row("lisa", 302)); assertThat(query("SELECT name FROM " + CATALOG + ".\"" + SCHEMA_NAME + "\".\"" + TABLE_NAME_MIXED_1 + "\" WHERE id = 401")) @@ -175,31 +180,67 @@ public void testSelectDataWithMixedCaseNames() @Test(groups = {MYSQL_MIXED_CASE}, dependsOnMethods = "testSelectDataWithMixedCaseNames") public void testTableAlterWithMixedCaseNames() { + // add column query("ALTER TABLE " + CATALOG + ".\"" + SCHEMA_NAME + "\".\"" + TABLE_NAME + "\" ADD COLUMN num REAL"); - query("ALTER TABLE " + CATALOG + ".\"" + SCHEMA_NAME_UPPER + "\".\"" + TABLE_NAME_UPPER_SCHEMA_02 + "\" ADD COLUMN num1 REAL"); - query("ALTER TABLE " + CATALOG + ".\"" + SCHEMA_NAME + "\".\"" + TABLE_NAME_UPPER_2 + "\" ADD COLUMN num01 REAL"); - query("ALTER TABLE " + CATALOG + ".\"" + SCHEMA_NAME_UPPER + "\".\"" + TABLE_NAME_UPPER_SCHEMA_02 + "\" ADD COLUMN num2 REAL"); + query("ALTER TABLE " + CATALOG + ".\"" + SCHEMA_NAME + "\".\"" + TABLE_NAME + "\" ADD COLUMN NuM2 REAL"); - assertThat(query("DESCRIBE " + CATALOG + ".\"" + SCHEMA_NAME + "\".\"" + TABLE_NAME + "\"")) - .contains(row("num", "real", "", "")); - - assertThat(query("DESCRIBE " + CATALOG + ".\"" + SCHEMA_NAME_UPPER + "\".\"" + TABLE_NAME_UPPER_SCHEMA_02 + "\"")) - .contains(row("num1", "real", "", "")); + query("ALTER TABLE " + CATALOG + ".\"" + SCHEMA_NAME + "\".\"" + TABLE_NAME_UPPER_2 + "\" ADD COLUMN num01 REAL"); + query("ALTER TABLE " + CATALOG + ".\"" + SCHEMA_NAME + "\".\"" + TABLE_NAME_UPPER_2 + "\" ADD COLUMN NuM2 REAL"); - assertThat(query("DESCRIBE " + CATALOG + ".\"" + SCHEMA_NAME + "\".\"" + TABLE_NAME_UPPER_2 + "\"")) - .contains(row("num01", "real", "", "")); + query("ALTER TABLE " + CATALOG + ".\"" + SCHEMA_NAME_UPPER + "\".\"" + TABLE_NAME_UPPER_SCHEMA_02 + "\" ADD COLUMN num1 REAL"); + query("ALTER TABLE " + CATALOG + ".\"" + SCHEMA_NAME_UPPER + "\".\"" + TABLE_NAME_UPPER_SCHEMA_02 + "\" ADD COLUMN NuM2 REAL"); + // Negative test: Creating a duplicate column with different case should fail in mysql + assertThat(() -> query("ALTER TABLE " + CATALOG + ".\"" + SCHEMA_NAME_UPPER + "\".\"" + TABLE_NAME_UPPER_SCHEMA_02 + "\" ADD COLUMN num2 REAL")) + .failsWithMessage("Duplicate column name 'num2'"); - assertThat(query("DESCRIBE " + CATALOG + ".\"" + SCHEMA_NAME_UPPER + "\".\"" + TABLE_NAME_UPPER_SCHEMA_02 + "\"")) - .contains(row("num2", "real", "", "")); + assertThat(query("DESCRIBE " + CATALOG + ".\"" + SCHEMA_NAME + "\".\"" + TABLE_NAME + "\"")).containsOnly( + row("name", "varchar(255)", "", ""), + row("ID", "integer", "", ""), + row("num", "real", "", ""), + row("NuM2", "real", "", "")); + assertThat(query("DESCRIBE " + CATALOG + ".\"" + SCHEMA_NAME + "\".\"" + TABLE_NAME_UPPER_2 + "\"")).containsOnly( + row("Name", "varchar(255)", "", ""), + row("ID", "integer", "", ""), + row("num01", "real", "", ""), + row("NuM2", "real", "", "")); + assertThat(query("DESCRIBE " + CATALOG + ".\"" + SCHEMA_NAME_UPPER + "\".\"" + TABLE_NAME_UPPER_SCHEMA_02 + "\"")).containsOnly( + row("name", "varchar(255)", "", ""), + row("id", "integer", "", ""), + row("num", "double", "", ""), + row("num1", "real", "", ""), + row("NuM2", "real", "", "")); + // rename column query("ALTER TABLE " + CATALOG + ".\"" + SCHEMA_NAME + "\".\"" + TABLE_NAME + "\" RENAME COLUMN num TO numb"); + query("ALTER TABLE " + CATALOG + ".\"" + SCHEMA_NAME + "\".\"" + TABLE_NAME + "\" RENAME COLUMN NuM2 TO NuM02"); query("ALTER TABLE " + CATALOG + ".\"" + SCHEMA_NAME_UPPER + "\".\"" + TABLE_NAME_UPPER_SCHEMA_02 + "\" RENAME COLUMN num1 TO numb01"); + query("ALTER TABLE " + CATALOG + ".\"" + SCHEMA_NAME_UPPER + "\".\"" + TABLE_NAME_UPPER_SCHEMA_02 + "\" RENAME COLUMN NuM2 TO NuM02"); + + assertThat(query("DESCRIBE " + CATALOG + ".\"" + SCHEMA_NAME + "\".\"" + TABLE_NAME + "\"")).containsOnly( + row("name", "varchar(255)", "", ""), + row("ID", "integer", "", ""), + row("numb", "real", "", ""), + row("NuM02", "real", "", "")); + assertThat(query("DESCRIBE " + CATALOG + ".\"" + SCHEMA_NAME_UPPER + "\".\"" + TABLE_NAME_UPPER_SCHEMA_02 + "\"")).containsOnly( + row("name", "varchar(255)", "", ""), + row("id", "integer", "", ""), + row("num", "double", "", ""), + row("numb01", "real", "", ""), + row("NuM02", "real", "", "")); - assertThat(query("DESCRIBE " + CATALOG + ".\"" + SCHEMA_NAME + "\".\"" + TABLE_NAME + "\"")) - .contains(row("numb", "real", "", "")); + // drop column + query("ALTER TABLE " + CATALOG + ".\"" + SCHEMA_NAME + "\".\"" + TABLE_NAME + "\" DROP COLUMN NuM02"); + query("ALTER TABLE " + CATALOG + ".\"" + SCHEMA_NAME_UPPER + "\".\"" + TABLE_NAME_UPPER_SCHEMA_02 + "\" DROP COLUMN numb01"); - assertThat(query("DESCRIBE " + CATALOG + ".\"" + SCHEMA_NAME_UPPER + "\".\"" + TABLE_NAME_UPPER_SCHEMA_02 + "\"")) - .contains(row("numb01", "real", "", "")); + assertThat(query("DESCRIBE " + CATALOG + ".\"" + SCHEMA_NAME + "\".\"" + TABLE_NAME + "\"")).containsOnly( + row("name", "varchar(255)", "", ""), + row("ID", "integer", "", ""), + row("numb", "real", "", "")); + assertThat(query("DESCRIBE " + CATALOG + ".\"" + SCHEMA_NAME_UPPER + "\".\"" + TABLE_NAME_UPPER_SCHEMA_02 + "\"")).containsOnly( + row("name", "varchar(255)", "", ""), + row("id", "integer", "", ""), + row("num", "double", "", ""), + row("NuM02", "real", "", "")); } @Test(groups = {MYSQL_MIXED_CASE}, dependsOnMethods = "testTableAlterWithMixedCaseNames") diff --git a/presto-redis/src/main/java/com/facebook/presto/redis/RedisInternalFieldDescription.java b/presto-redis/src/main/java/com/facebook/presto/redis/RedisInternalFieldDescription.java index 3a8b36cbf78a9..b7c390f42c24b 100644 --- a/presto-redis/src/main/java/com/facebook/presto/redis/RedisInternalFieldDescription.java +++ b/presto-redis/src/main/java/com/facebook/presto/redis/RedisInternalFieldDescription.java @@ -116,10 +116,10 @@ RedisColumnHandle getColumnHandle(String connectorId, int index, boolean hidden) true); } - ColumnMetadata getColumnMetadata(boolean hidden) + ColumnMetadata getColumnMetadata(boolean hidden, String name) { return ColumnMetadata.builder() - .setName(columnName) + .setName(name) .setType(type) .setComment(comment) .setHidden(hidden) diff --git a/presto-redis/src/main/java/com/facebook/presto/redis/RedisMetadata.java b/presto-redis/src/main/java/com/facebook/presto/redis/RedisMetadata.java index 8caa7c9753293..9b88039f75385 100644 --- a/presto-redis/src/main/java/com/facebook/presto/redis/RedisMetadata.java +++ b/presto-redis/src/main/java/com/facebook/presto/redis/RedisMetadata.java @@ -121,7 +121,7 @@ private static String getDataFormat(RedisTableFieldGroup fieldGroup) @Override public ConnectorTableMetadata getTableMetadata(ConnectorSession session, ConnectorTableHandle tableHandle) { - return getTableMetadata(convertTableHandle(tableHandle).toSchemaTableName()); + return getTableMetadata(session, convertTableHandle(tableHandle).toSchemaTableName()); } @Override @@ -221,7 +221,7 @@ public Map> listTableColumns(ConnectorSess } for (SchemaTableName tableName : tableNames) { - ConnectorTableMetadata tableMetadata = getTableMetadata(tableName); + ConnectorTableMetadata tableMetadata = getTableMetadata(session, tableName); // table can disappear during listing operation if (tableMetadata != null) { columns.put(tableName, tableMetadata.getColumns()); @@ -243,7 +243,7 @@ Map getDefinedTables() return redisTableDescriptionSupplier.get(); } - private ConnectorTableMetadata getTableMetadata(SchemaTableName schemaTableName) + private ConnectorTableMetadata getTableMetadata(ConnectorSession session, SchemaTableName schemaTableName) { RedisTableDescription table = getDefinedTables().get(schemaTableName); if (table == null) { @@ -252,23 +252,23 @@ private ConnectorTableMetadata getTableMetadata(SchemaTableName schemaTableName) ImmutableList.Builder builder = ImmutableList.builder(); - appendFields(builder, table.getKey()); - appendFields(builder, table.getValue()); + appendFields(session, builder, table.getKey()); + appendFields(session, builder, table.getValue()); for (RedisInternalFieldDescription fieldDescription : RedisInternalFieldDescription.values()) { - builder.add(fieldDescription.getColumnMetadata(hideInternalColumns)); + builder.add(fieldDescription.getColumnMetadata(hideInternalColumns, normalizeIdentifier(session, fieldDescription.getColumnName()))); } return new ConnectorTableMetadata(schemaTableName, builder.build()); } - private static void appendFields(ImmutableList.Builder builder, RedisTableFieldGroup group) + private void appendFields(ConnectorSession session, ImmutableList.Builder builder, RedisTableFieldGroup group) { if (group != null) { List fields = group.getFields(); if (fields != null) { for (RedisTableFieldDescription fieldDescription : fields) { - builder.add(fieldDescription.getColumnMetadata()); + builder.add(fieldDescription.getColumnMetadata(normalizeIdentifier(session, fieldDescription.getName()))); } } } diff --git a/presto-redis/src/main/java/com/facebook/presto/redis/RedisTableFieldDescription.java b/presto-redis/src/main/java/com/facebook/presto/redis/RedisTableFieldDescription.java index 942c04e7ffeab..13a9373b01725 100644 --- a/presto-redis/src/main/java/com/facebook/presto/redis/RedisTableFieldDescription.java +++ b/presto-redis/src/main/java/com/facebook/presto/redis/RedisTableFieldDescription.java @@ -115,10 +115,10 @@ RedisColumnHandle getColumnHandle(String connectorId, boolean keyDecoder, int in false); } - ColumnMetadata getColumnMetadata() + ColumnMetadata getColumnMetadata(String name) { return ColumnMetadata.builder() - .setName(getName()) + .setName(name) .setType(getType()) .setComment(getComment()) .setHidden(isHidden()) diff --git a/presto-redshift/src/main/java/com/facebook/presto/plugin/redshift/RedshiftClient.java b/presto-redshift/src/main/java/com/facebook/presto/plugin/redshift/RedshiftClient.java index 2266603937f6c..dba751740a4d5 100644 --- a/presto-redshift/src/main/java/com/facebook/presto/plugin/redshift/RedshiftClient.java +++ b/presto-redshift/src/main/java/com/facebook/presto/plugin/redshift/RedshiftClient.java @@ -35,6 +35,7 @@ import static com.facebook.presto.plugin.jdbc.JdbcErrorCode.JDBC_ERROR; import static com.facebook.presto.plugin.jdbc.StandardReadMappings.varbinaryReadMapping; import static java.lang.String.format; +import static java.util.Locale.ENGLISH; public class RedshiftClient extends BaseJdbcClient @@ -83,4 +84,10 @@ public Optional toPrestoType(ConnectorSession session, JdbcTypeHand return super.toPrestoType(session, typeHandle); } + + @Override + public String normalizeIdentifier(ConnectorSession session, String identifier) + { + return caseSensitiveNameMatchingEnabled ? identifier : identifier.toLowerCase(ENGLISH); + } } diff --git a/presto-singlestore/src/main/java/com/facebook/presto/plugin/singlestore/SingleStoreClient.java b/presto-singlestore/src/main/java/com/facebook/presto/plugin/singlestore/SingleStoreClient.java index 996a2452b4dab..679bbb09f50a6 100644 --- a/presto-singlestore/src/main/java/com/facebook/presto/plugin/singlestore/SingleStoreClient.java +++ b/presto-singlestore/src/main/java/com/facebook/presto/plugin/singlestore/SingleStoreClient.java @@ -200,4 +200,10 @@ protected void renameTable(JdbcIdentity identity, String catalogName, SchemaTabl { super.renameTable(identity, null, oldTable, newTable); } + + @Override + public String normalizeIdentifier(ConnectorSession session, String identifier) + { + return caseSensitiveNameMatchingEnabled ? identifier : identifier.toLowerCase(ENGLISH); + } } diff --git a/presto-spi/src/main/java/com/facebook/presto/spi/ColumnMetadata.java b/presto-spi/src/main/java/com/facebook/presto/spi/ColumnMetadata.java index 1a358756e4788..91c0e4c1cb3bf 100644 --- a/presto-spi/src/main/java/com/facebook/presto/spi/ColumnMetadata.java +++ b/presto-spi/src/main/java/com/facebook/presto/spi/ColumnMetadata.java @@ -23,7 +23,6 @@ import static com.facebook.presto.spi.SchemaUtil.checkNotEmpty; import static java.util.Collections.emptyMap; import static java.util.Collections.unmodifiableMap; -import static java.util.Locale.ENGLISH; import static java.util.Objects.requireNonNull; public class ColumnMetadata @@ -42,7 +41,7 @@ private ColumnMetadata(String name, Type type, boolean nullable, String comment, requireNonNull(type, "type is null"); requireNonNull(properties, "properties is null"); - this.name = name.toLowerCase(ENGLISH); + this.name = name; this.type = type; this.nullable = nullable; this.comment = comment; @@ -90,6 +89,17 @@ public Map getProperties() { return properties; } + public Builder toBuilder() + { + return ColumnMetadata.builder() + .setName(getName()) + .setType(getType()) + .setNullable(isNullable()) + .setComment(getComment().orElse(null)) + .setExtraInfo(getExtraInfo().orElse(null)) + .setHidden(isHidden()) + .setProperties(getProperties()); + } @Override public String toString() diff --git a/presto-sqlserver/src/main/java/com/facebook/presto/plugin/sqlserver/SqlServerClient.java b/presto-sqlserver/src/main/java/com/facebook/presto/plugin/sqlserver/SqlServerClient.java index cbb07ff03f504..1c3d9071b3862 100644 --- a/presto-sqlserver/src/main/java/com/facebook/presto/plugin/sqlserver/SqlServerClient.java +++ b/presto-sqlserver/src/main/java/com/facebook/presto/plugin/sqlserver/SqlServerClient.java @@ -33,6 +33,7 @@ import static com.facebook.presto.plugin.jdbc.JdbcErrorCode.JDBC_ERROR; import static java.lang.String.format; +import static java.util.Locale.ENGLISH; public class SqlServerClient extends BaseJdbcClient @@ -84,4 +85,10 @@ private static String singleQuote(String literal) { return "\'" + literal + "\'"; } + + @Override + public String normalizeIdentifier(ConnectorSession session, String identifier) + { + return caseSensitiveNameMatchingEnabled ? identifier : identifier.toLowerCase(ENGLISH); + } } diff --git a/presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsMetadata.java b/presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsMetadata.java index 946a4c6148f68..ab57475bb199a 100644 --- a/presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsMetadata.java +++ b/presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsMetadata.java @@ -137,15 +137,15 @@ public ConnectorTableMetadata getTableMetadata(ConnectorSession session, Connect Table table = Table.getTable(tpcdsTableHandle.getTableName()); String schemaName = scaleFactorSchemaName(tpcdsTableHandle.getScaleFactor()); - return getTableMetadata(schemaName, table, useVarcharType); + return getTableMetadata(session, schemaName, table, useVarcharType); } - private static ConnectorTableMetadata getTableMetadata(String schemaName, Table tpcdsTable, boolean useVarcharType) + private ConnectorTableMetadata getTableMetadata(ConnectorSession session, String schemaName, Table tpcdsTable, boolean useVarcharType) { ImmutableList.Builder columns = ImmutableList.builder(); for (Column column : tpcdsTable.getColumns()) { columns.add(ColumnMetadata.builder() - .setName(column.getName()) + .setName(normalizeIdentifier(session, column.getName())) .setType(getPrestoType(column.getType(), useVarcharType)) .build()); } @@ -195,7 +195,7 @@ public Map> listTableColumns(ConnectorSess for (String schemaName : getSchemaNames(session, Optional.ofNullable(prefix.getSchemaName()))) { for (Table tpcdsTable : Table.getBaseTables()) { if (prefix.getTableName() == null || tpcdsTable.getName().equals(prefix.getTableName())) { - ConnectorTableMetadata tableMetadata = getTableMetadata(schemaName, tpcdsTable, useVarcharType); + ConnectorTableMetadata tableMetadata = getTableMetadata(session, schemaName, tpcdsTable, useVarcharType); tableColumns.put(new SchemaTableName(schemaName, tpcdsTable.getName()), tableMetadata.getColumns()); } } diff --git a/presto-tpch/src/main/java/com/facebook/presto/tpch/TpchMetadata.java b/presto-tpch/src/main/java/com/facebook/presto/tpch/TpchMetadata.java index 29feeebf3072c..6e27f7df994b6 100644 --- a/presto-tpch/src/main/java/com/facebook/presto/tpch/TpchMetadata.java +++ b/presto-tpch/src/main/java/com/facebook/presto/tpch/TpchMetadata.java @@ -282,15 +282,15 @@ public ConnectorTableMetadata getTableMetadata(ConnectorSession session, Connect TpchTable tpchTable = TpchTable.getTable(tpchTableHandle.getTableName()); String schemaName = scaleFactorSchemaName(tpchTableHandle.getScaleFactor()); - return getTableMetadata(schemaName, tpchTable, columnNaming); + return getTableMetadata(session, schemaName, tpchTable, columnNaming); } - private static ConnectorTableMetadata getTableMetadata(String schemaName, TpchTable tpchTable, ColumnNaming columnNaming) + private ConnectorTableMetadata getTableMetadata(ConnectorSession session, String schemaName, TpchTable tpchTable, ColumnNaming columnNaming) { ImmutableList.Builder columns = ImmutableList.builder(); for (TpchColumn column : tpchTable.getColumns()) { columns.add(ColumnMetadata.builder() - .setName(columnNaming.getName(column)) + .setName(normalizeIdentifier(session, columnNaming.getName(column))) .setType(getPrestoType(column)) .setNullable(false) .build()); @@ -322,7 +322,7 @@ public Map> listTableColumns(ConnectorSess for (String schemaName : getSchemaNames(session, Optional.ofNullable(prefix.getSchemaName()))) { for (TpchTable tpchTable : TpchTable.getTables()) { if (prefix.getTableName() == null || tpchTable.getTableName().equals(prefix.getTableName())) { - ConnectorTableMetadata tableMetadata = getTableMetadata(schemaName, tpchTable, columnNaming); + ConnectorTableMetadata tableMetadata = getTableMetadata(session, schemaName, tpchTable, columnNaming); tableColumns.put(new SchemaTableName(schemaName, tpchTable.getTableName()), tableMetadata.getColumns()); } }