diff --git a/plugin/trino-accumulo/src/main/java/io/trino/plugin/accumulo/AccumuloMetadata.java b/plugin/trino-accumulo/src/main/java/io/trino/plugin/accumulo/AccumuloMetadata.java index 5b08f50b5d75..15e91744961d 100644 --- a/plugin/trino-accumulo/src/main/java/io/trino/plugin/accumulo/AccumuloMetadata.java +++ b/plugin/trino-accumulo/src/main/java/io/trino/plugin/accumulo/AccumuloMetadata.java @@ -102,6 +102,9 @@ public ConnectorOutputTableHandle beginCreateTable(ConnectorSession session, Con if (retryMode != NO_RETRIES) { throw new TrinoException(NOT_SUPPORTED, "This connector does not support query retries"); } + if (tableMetadata.getComment().isPresent()) { + throw new TrinoException(NOT_SUPPORTED, "This connector does not support creating tables with table comment"); + } checkNoRollback(); @@ -136,6 +139,9 @@ private void rollbackCreateTable(AccumuloTable table) @Override public void createTable(ConnectorSession session, ConnectorTableMetadata tableMetadata, boolean ignoreExisting) { + if (tableMetadata.getComment().isPresent()) { + throw new TrinoException(NOT_SUPPORTED, "This connector does not support creating tables with table comment"); + } client.createTable(tableMetadata); } diff --git a/plugin/trino-accumulo/src/test/java/io/trino/plugin/accumulo/TestAccumuloConnectorTest.java b/plugin/trino-accumulo/src/test/java/io/trino/plugin/accumulo/TestAccumuloConnectorTest.java index 6404b1049d5c..1c108b17b78a 100644 --- a/plugin/trino-accumulo/src/test/java/io/trino/plugin/accumulo/TestAccumuloConnectorTest.java +++ b/plugin/trino-accumulo/src/test/java/io/trino/plugin/accumulo/TestAccumuloConnectorTest.java @@ -68,6 +68,9 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior) case SUPPORTS_DROP_COLUMN: return false; + case SUPPORTS_CREATE_TABLE_WITH_TABLE_COMMENT: + return false; + case SUPPORTS_COMMENT_ON_TABLE: case SUPPORTS_COMMENT_ON_COLUMN: return false; diff --git a/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/BaseJdbcClient.java b/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/BaseJdbcClient.java index e5c5e44e1d52..0c6063b14013 100644 --- a/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/BaseJdbcClient.java +++ b/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/BaseJdbcClient.java @@ -540,6 +540,9 @@ protected JdbcOutputTableHandle createTable(ConnectorSession session, ConnectorT protected String createTableSql(RemoteTableName remoteTableName, List columns, ConnectorTableMetadata tableMetadata) { + if (tableMetadata.getComment().isPresent()) { + throw new TrinoException(NOT_SUPPORTED, "This connector does not support creating tables with table comment"); + } checkArgument(tableMetadata.getProperties().isEmpty(), "Unsupported table properties: %s", tableMetadata.getProperties()); return format("CREATE TABLE %s (%s)", quoted(remoteTableName), join(", ", columns)); } diff --git a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestJdbcConnectorTest.java b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestJdbcConnectorTest.java index d7282558a929..5cc211a85b61 100644 --- a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestJdbcConnectorTest.java +++ b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestJdbcConnectorTest.java @@ -66,6 +66,7 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior) case SUPPORTS_RENAME_TABLE_ACROSS_SCHEMAS: return false; + case SUPPORTS_CREATE_TABLE_WITH_TABLE_COMMENT: case SUPPORTS_COMMENT_ON_TABLE: case SUPPORTS_COMMENT_ON_COLUMN: case SUPPORTS_ADD_COLUMN_WITH_COMMENT: diff --git a/plugin/trino-bigquery/src/main/java/io/trino/plugin/bigquery/BigQueryMetadata.java b/plugin/trino-bigquery/src/main/java/io/trino/plugin/bigquery/BigQueryMetadata.java index 9efb930d6ec3..4f49a1f289e7 100644 --- a/plugin/trino-bigquery/src/main/java/io/trino/plugin/bigquery/BigQueryMetadata.java +++ b/plugin/trino-bigquery/src/main/java/io/trino/plugin/bigquery/BigQueryMetadata.java @@ -79,6 +79,7 @@ import static io.trino.plugin.bigquery.BigQueryTableHandle.BigQueryPartitionType.INGESTION; import static io.trino.plugin.bigquery.BigQueryType.toField; import static io.trino.plugin.bigquery.BigQueryUtil.isWildcardTable; +import static io.trino.spi.StandardErrorCode.NOT_SUPPORTED; import static java.util.Locale.ENGLISH; import static java.util.Objects.requireNonNull; import static java.util.function.Function.identity; @@ -371,6 +372,9 @@ public void dropSchema(ConnectorSession session, String schemaName) @Override public void createTable(ConnectorSession session, ConnectorTableMetadata tableMetadata, boolean ignoreExisting) { + if (tableMetadata.getComment().isPresent()) { + throw new TrinoException(NOT_SUPPORTED, "This connector does not support creating tables with table comment"); + } try { createTable(session, tableMetadata); } diff --git a/plugin/trino-bigquery/src/test/java/io/trino/plugin/bigquery/TestBigQueryConnectorTest.java b/plugin/trino-bigquery/src/test/java/io/trino/plugin/bigquery/TestBigQueryConnectorTest.java index 51047711468e..63659840d546 100644 --- a/plugin/trino-bigquery/src/test/java/io/trino/plugin/bigquery/TestBigQueryConnectorTest.java +++ b/plugin/trino-bigquery/src/test/java/io/trino/plugin/bigquery/TestBigQueryConnectorTest.java @@ -69,6 +69,7 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior) case SUPPORTS_RENAME_TABLE: case SUPPORTS_NOT_NULL_CONSTRAINT: case SUPPORTS_CREATE_TABLE_WITH_DATA: + case SUPPORTS_CREATE_TABLE_WITH_TABLE_COMMENT: case SUPPORTS_DELETE: case SUPPORTS_INSERT: case SUPPORTS_ADD_COLUMN: diff --git a/plugin/trino-cassandra/src/main/java/io/trino/plugin/cassandra/CassandraMetadata.java b/plugin/trino-cassandra/src/main/java/io/trino/plugin/cassandra/CassandraMetadata.java index 1740cbbd599f..289f54aed946 100644 --- a/plugin/trino-cassandra/src/main/java/io/trino/plugin/cassandra/CassandraMetadata.java +++ b/plugin/trino-cassandra/src/main/java/io/trino/plugin/cassandra/CassandraMetadata.java @@ -288,6 +288,9 @@ public ConnectorOutputTableHandle beginCreateTable(ConnectorSession session, Con private CassandraOutputTableHandle createTable(ConnectorTableMetadata tableMetadata) { + if (tableMetadata.getComment().isPresent()) { + throw new TrinoException(NOT_SUPPORTED, "This connector does not support creating tables with table comment"); + } ImmutableList.Builder columnNames = ImmutableList.builder(); ImmutableList.Builder columnTypes = ImmutableList.builder(); ImmutableList.Builder columnExtra = ImmutableList.builder(); diff --git a/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestCassandraConnectorTest.java b/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestCassandraConnectorTest.java index 8ec93a8d2707..18c5f24d47df 100644 --- a/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestCassandraConnectorTest.java +++ b/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestCassandraConnectorTest.java @@ -95,6 +95,9 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior) case SUPPORTS_CREATE_VIEW: return false; + case SUPPORTS_CREATE_TABLE_WITH_TABLE_COMMENT: + return false; + case SUPPORTS_RENAME_TABLE: return false; diff --git a/plugin/trino-clickhouse/src/test/java/io/trino/plugin/clickhouse/TestClickHouseConnectorTest.java b/plugin/trino-clickhouse/src/test/java/io/trino/plugin/clickhouse/TestClickHouseConnectorTest.java index 86c326527099..907ae0ee4053 100644 --- a/plugin/trino-clickhouse/src/test/java/io/trino/plugin/clickhouse/TestClickHouseConnectorTest.java +++ b/plugin/trino-clickhouse/src/test/java/io/trino/plugin/clickhouse/TestClickHouseConnectorTest.java @@ -42,4 +42,20 @@ public void testCommentTable() assertThatThrownBy(super::testCommentTable) .hasMessageContaining("Code: 62, e.displayText() = DB::Exception: Syntax error"); } + + @Override + public void testCreateTableWithTableComment() + { + // Table comment is unsupported in old ClickHouse version + assertThatThrownBy(super::testCreateTableWithTableComment) + .hasMessageMatching("(?s).* Syntax error: .* COMMENT 'test comment'.*"); + } + + @Override + public void testCreateTableAsSelectWithTableComment() + { + // Table comment is unsupported in old ClickHouse version + assertThatThrownBy(super::testCreateTableAsSelectWithTableComment) + .hasMessageMatching("(?s).* Syntax error: .* COMMENT 'test comment'.*"); + } } diff --git a/plugin/trino-delta-lake/src/main/java/io/trino/plugin/deltalake/DeltaLakeMetadata.java b/plugin/trino-delta-lake/src/main/java/io/trino/plugin/deltalake/DeltaLakeMetadata.java index d573e627c742..f0a218432f9f 100644 --- a/plugin/trino-delta-lake/src/main/java/io/trino/plugin/deltalake/DeltaLakeMetadata.java +++ b/plugin/trino-delta-lake/src/main/java/io/trino/plugin/deltalake/DeltaLakeMetadata.java @@ -403,7 +403,7 @@ public ConnectorTableMetadata getTableMetadata(ConnectorSession session, Connect tableHandle.getSchemaTableName(), columns, properties.buildOrThrow(), - Optional.empty()); + Optional.ofNullable(tableHandle.getMetadataEntry().getDescription())); } @Override @@ -626,7 +626,8 @@ public void createTable(ConnectorSession session, ConnectorTableMetadata tableMe CREATE_TABLE_OPERATION, session, nodeVersion, - nodeId); + nodeId, + tableMetadata.getComment()); setRollback(() -> deleteRecursivelyIfExists(new HdfsContext(session), hdfsEnvironment, deltaLogDirectory)); transactionLogWriter.flush(); @@ -735,7 +736,8 @@ public DeltaLakeOutputTableHandle beginCreateTable(ConnectorSession session, Con tableMetadata.getColumns().stream().map(column -> toColumnHandle(column, partitionedBy)).collect(toImmutableList()), location, DeltaLakeTableProperties.getCheckpointInterval(tableMetadata.getProperties()), - external); + external, + tableMetadata.getComment()); } private Optional getSchemaLocation(Database database) @@ -885,7 +887,8 @@ public Optional finishCreateTable( CREATE_TABLE_AS_OPERATION, session, nodeVersion, - nodeId); + nodeId, + handle.getComment()); appendAddFileEntries(transactionLogWriter, dataFileInfos, handle.getPartitionedBy(), true); transactionLogWriter.flush(); PrincipalPrivileges principalPrivileges = buildInitialPrivilegeSet(table.getOwner().orElseThrow()); @@ -960,7 +963,8 @@ public void addColumn(ConnectorSession session, ConnectorTableHandle tableHandle ADD_COLUMN_OPERATION, session, nodeVersion, - nodeId); + nodeId, + Optional.ofNullable(handle.getMetadataEntry().getDescription())); transactionLogWriter.flush(); } catch (Exception e) { @@ -978,7 +982,8 @@ private static void appendTableEntries( String operation, ConnectorSession session, String nodeVersion, - String nodeId) + String nodeId, + Optional comment) { long createdTime = System.currentTimeMillis(); transactionLogWriter.appendCommitInfoEntry( @@ -1002,7 +1007,7 @@ private static void appendTableEntries( new MetadataEntry( tableId, null, - null, + comment.orElse(null), new Format("parquet", ImmutableMap.of()), serializeSchemaAsJson(columns), partitionColumnNames, diff --git a/plugin/trino-delta-lake/src/main/java/io/trino/plugin/deltalake/DeltaLakeOutputTableHandle.java b/plugin/trino-delta-lake/src/main/java/io/trino/plugin/deltalake/DeltaLakeOutputTableHandle.java index d99a4097e7fb..838655db7088 100644 --- a/plugin/trino-delta-lake/src/main/java/io/trino/plugin/deltalake/DeltaLakeOutputTableHandle.java +++ b/plugin/trino-delta-lake/src/main/java/io/trino/plugin/deltalake/DeltaLakeOutputTableHandle.java @@ -35,6 +35,7 @@ public class DeltaLakeOutputTableHandle private final String location; private final Optional checkpointInterval; private final boolean external; + private final Optional comment; @JsonCreator public DeltaLakeOutputTableHandle( @@ -43,7 +44,8 @@ public DeltaLakeOutputTableHandle( @JsonProperty("inputColumns") List inputColumns, @JsonProperty("location") String location, @JsonProperty("checkpointInterval") Optional checkpointInterval, - @JsonProperty("external") boolean external) + @JsonProperty("external") boolean external, + @JsonProperty("comment") Optional comment) { this.schemaName = requireNonNull(schemaName, "schemaName is null"); this.tableName = requireNonNull(tableName, "tableName is null"); @@ -51,6 +53,7 @@ public DeltaLakeOutputTableHandle( this.location = requireNonNull(location, "location is null"); this.checkpointInterval = checkpointInterval; this.external = external; + this.comment = requireNonNull(comment, "comment is null"); } @JsonProperty @@ -97,4 +100,10 @@ public boolean isExternal() { return external; } + + @JsonProperty + public Optional getComment() + { + return comment; + } } diff --git a/plugin/trino-delta-lake/src/main/java/io/trino/plugin/deltalake/transactionlog/checkpoint/CheckpointEntryIterator.java b/plugin/trino-delta-lake/src/main/java/io/trino/plugin/deltalake/transactionlog/checkpoint/CheckpointEntryIterator.java index 353a291027eb..63109b854b93 100644 --- a/plugin/trino-delta-lake/src/main/java/io/trino/plugin/deltalake/transactionlog/checkpoint/CheckpointEntryIterator.java +++ b/plugin/trino-delta-lake/src/main/java/io/trino/plugin/deltalake/transactionlog/checkpoint/CheckpointEntryIterator.java @@ -521,23 +521,30 @@ private DeltaLakeTransactionLogEntry buildTxnEntry(ConnectorSession session, Blo return DeltaLakeTransactionLogEntry.transactionEntry(result); } + @Nullable private String getString(Block block, int position) { + if (block.isNull(position)) { + return null; + } return block.getSlice(position, 0, block.getSliceLength(position)).toString(UTF_8); } private long getLong(Block block, int position) { + checkArgument(!block.isNull(position)); return block.getLong(position, 0); } private int getInt(Block block, int position) { + checkArgument(!block.isNull(position)); return block.getInt(position, 0); } private byte getByte(Block block, int position) { + checkArgument(!block.isNull(position)); return block.getByte(position, 0); } diff --git a/plugin/trino-delta-lake/src/test/java/io/trino/plugin/deltalake/TestDeltaLakePageSink.java b/plugin/trino-delta-lake/src/test/java/io/trino/plugin/deltalake/TestDeltaLakePageSink.java index b0b8bc66fabc..e7365729bf0d 100644 --- a/plugin/trino-delta-lake/src/test/java/io/trino/plugin/deltalake/TestDeltaLakePageSink.java +++ b/plugin/trino-delta-lake/src/test/java/io/trino/plugin/deltalake/TestDeltaLakePageSink.java @@ -164,7 +164,8 @@ private static ConnectorPageSink createPageSink(Path outputPath, DeltaLakeWriter getColumnHandles(), outputPath.toString(), Optional.of(deltaLakeConfig.getDefaultCheckpointWritingInterval()), - true); + true, + Optional.empty()); DeltaLakePageSinkProvider provider = new DeltaLakePageSinkProvider( new GroupByHashPageIndexerFactory(new JoinCompiler(new TypeOperators()), new BlockTypeOperators()), diff --git a/plugin/trino-delta-lake/src/test/java/io/trino/plugin/deltalake/transactionlog/checkpoint/TestCheckpointEntryIterator.java b/plugin/trino-delta-lake/src/test/java/io/trino/plugin/deltalake/transactionlog/checkpoint/TestCheckpointEntryIterator.java index 984ad11f7823..3c8109f189c1 100644 --- a/plugin/trino-delta-lake/src/test/java/io/trino/plugin/deltalake/transactionlog/checkpoint/TestCheckpointEntryIterator.java +++ b/plugin/trino-delta-lake/src/test/java/io/trino/plugin/deltalake/transactionlog/checkpoint/TestCheckpointEntryIterator.java @@ -87,8 +87,8 @@ public void testReadMetadataEntry() .isEqualTo( new MetadataEntry( "b6aeffad-da73-4dde-b68e-937e468b1fde", - "", - "", + null, + null, new MetadataEntry.Format("parquet", Map.of()), "{\"type\":\"struct\",\"fields\":[" + "{\"name\":\"name\",\"type\":\"string\",\"nullable\":true,\"metadata\":{}}," + diff --git a/plugin/trino-kudu/src/main/java/io/trino/plugin/kudu/KuduMetadata.java b/plugin/trino-kudu/src/main/java/io/trino/plugin/kudu/KuduMetadata.java index 92a5f3fac2ff..a352f06f23fd 100755 --- a/plugin/trino-kudu/src/main/java/io/trino/plugin/kudu/KuduMetadata.java +++ b/plugin/trino-kudu/src/main/java/io/trino/plugin/kudu/KuduMetadata.java @@ -247,6 +247,9 @@ public void dropSchema(ConnectorSession session, String schemaName) @Override public void createTable(ConnectorSession session, ConnectorTableMetadata tableMetadata, boolean ignoreExisting) { + if (tableMetadata.getComment().isPresent()) { + throw new TrinoException(NOT_SUPPORTED, "This connector does not support creating tables with table comment"); + } clientSession.createTable(tableMetadata, ignoreExisting); } @@ -329,6 +332,9 @@ public ConnectorOutputTableHandle beginCreateTable( if (retryMode != NO_RETRIES) { throw new TrinoException(NOT_SUPPORTED, "This connector does not support query retries"); } + if (tableMetadata.getComment().isPresent()) { + throw new TrinoException(NOT_SUPPORTED, "This connector does not support creating tables with table comment"); + } PartitionDesign design = KuduTableProperties.getPartitionDesign(tableMetadata.getProperties()); boolean generateUUID = !design.hasPartitions(); ConnectorTableMetadata finalTableMetadata = tableMetadata; diff --git a/plugin/trino-kudu/src/test/java/io/trino/plugin/kudu/AbstractKuduConnectorTest.java b/plugin/trino-kudu/src/test/java/io/trino/plugin/kudu/AbstractKuduConnectorTest.java index 3eba6155be7c..defd869c8cda 100644 --- a/plugin/trino-kudu/src/test/java/io/trino/plugin/kudu/AbstractKuduConnectorTest.java +++ b/plugin/trino-kudu/src/test/java/io/trino/plugin/kudu/AbstractKuduConnectorTest.java @@ -70,6 +70,7 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior) case SUPPORTS_DELETE: return true; case SUPPORTS_RENAME_SCHEMA: + case SUPPORTS_CREATE_TABLE_WITH_TABLE_COMMENT: case SUPPORTS_COMMENT_ON_TABLE: case SUPPORTS_COMMENT_ON_COLUMN: case SUPPORTS_ARRAY: diff --git a/plugin/trino-memory/src/main/java/io/trino/plugin/memory/MemoryMetadata.java b/plugin/trino-memory/src/main/java/io/trino/plugin/memory/MemoryMetadata.java index b5991e8614e5..cd0f44aeb09f 100644 --- a/plugin/trino-memory/src/main/java/io/trino/plugin/memory/MemoryMetadata.java +++ b/plugin/trino-memory/src/main/java/io/trino/plugin/memory/MemoryMetadata.java @@ -67,6 +67,7 @@ import static com.google.common.collect.ImmutableMap.toImmutableMap; import static io.trino.spi.StandardErrorCode.ALREADY_EXISTS; import static io.trino.spi.StandardErrorCode.NOT_FOUND; +import static io.trino.spi.StandardErrorCode.NOT_SUPPORTED; import static io.trino.spi.StandardErrorCode.SCHEMA_NOT_EMPTY; import static io.trino.spi.connector.RetryMode.NO_RETRIES; import static io.trino.spi.connector.SampleType.SYSTEM; @@ -235,6 +236,9 @@ public synchronized void createTable(ConnectorSession session, ConnectorTableMet @Override public synchronized MemoryOutputTableHandle beginCreateTable(ConnectorSession session, ConnectorTableMetadata tableMetadata, Optional layout, RetryMode retryMode) { + if (tableMetadata.getComment().isPresent()) { + throw new TrinoException(NOT_SUPPORTED, "This connector does not support creating tables with table comment"); + } checkSchemaExists(tableMetadata.getTable().getSchemaName()); checkTableNotExists(tableMetadata.getTable()); long tableId = nextTableId.getAndIncrement(); diff --git a/plugin/trino-memory/src/test/java/io/trino/plugin/memory/TestMemoryConnectorTest.java b/plugin/trino-memory/src/test/java/io/trino/plugin/memory/TestMemoryConnectorTest.java index 9fef9673f399..09db864f8b12 100644 --- a/plugin/trino-memory/src/test/java/io/trino/plugin/memory/TestMemoryConnectorTest.java +++ b/plugin/trino-memory/src/test/java/io/trino/plugin/memory/TestMemoryConnectorTest.java @@ -97,6 +97,7 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior) case SUPPORTS_RENAME_COLUMN: return false; + case SUPPORTS_CREATE_TABLE_WITH_TABLE_COMMENT: case SUPPORTS_COMMENT_ON_TABLE: case SUPPORTS_COMMENT_ON_COLUMN: return false; diff --git a/plugin/trino-oracle/src/test/java/io/trino/plugin/oracle/BaseOracleConnectorTest.java b/plugin/trino-oracle/src/test/java/io/trino/plugin/oracle/BaseOracleConnectorTest.java index 41cc083d9faa..733b6b81145c 100644 --- a/plugin/trino-oracle/src/test/java/io/trino/plugin/oracle/BaseOracleConnectorTest.java +++ b/plugin/trino-oracle/src/test/java/io/trino/plugin/oracle/BaseOracleConnectorTest.java @@ -61,6 +61,9 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior) case SUPPORTS_JOIN_PUSHDOWN_WITH_DISTINCT_FROM: return false; + case SUPPORTS_CREATE_TABLE_WITH_TABLE_COMMENT: + return false; + case SUPPORTS_COMMENT_ON_TABLE: return false; diff --git a/plugin/trino-phoenix/src/main/java/io/trino/plugin/phoenix/PhoenixClient.java b/plugin/trino-phoenix/src/main/java/io/trino/plugin/phoenix/PhoenixClient.java index be6abb7b03e0..7b2864c209a1 100644 --- a/plugin/trino-phoenix/src/main/java/io/trino/plugin/phoenix/PhoenixClient.java +++ b/plugin/trino-phoenix/src/main/java/io/trino/plugin/phoenix/PhoenixClient.java @@ -572,6 +572,9 @@ public Optional getTableComment(ResultSet resultSet) @Override public JdbcOutputTableHandle beginCreateTable(ConnectorSession session, ConnectorTableMetadata tableMetadata) { + if (tableMetadata.getComment().isPresent()) { + throw new TrinoException(NOT_SUPPORTED, "This connector does not support creating tables with table comment"); + } SchemaTableName schemaTableName = tableMetadata.getTable(); String schema = schemaTableName.getSchemaName(); String table = schemaTableName.getTableName(); diff --git a/plugin/trino-phoenix/src/test/java/io/trino/plugin/phoenix/TestPhoenixConnectorTest.java b/plugin/trino-phoenix/src/test/java/io/trino/plugin/phoenix/TestPhoenixConnectorTest.java index 8c85600d63e7..2fdf20e3b73b 100644 --- a/plugin/trino-phoenix/src/test/java/io/trino/plugin/phoenix/TestPhoenixConnectorTest.java +++ b/plugin/trino-phoenix/src/test/java/io/trino/plugin/phoenix/TestPhoenixConnectorTest.java @@ -71,6 +71,7 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior) case SUPPORTS_AGGREGATION_PUSHDOWN: return false; + case SUPPORTS_CREATE_TABLE_WITH_TABLE_COMMENT: case SUPPORTS_COMMENT_ON_TABLE: case SUPPORTS_COMMENT_ON_COLUMN: case SUPPORTS_ADD_COLUMN_WITH_COMMENT: diff --git a/plugin/trino-phoenix5/src/main/java/io/trino/plugin/phoenix5/PhoenixClient.java b/plugin/trino-phoenix5/src/main/java/io/trino/plugin/phoenix5/PhoenixClient.java index a0f861e870f8..caa049cf9591 100644 --- a/plugin/trino-phoenix5/src/main/java/io/trino/plugin/phoenix5/PhoenixClient.java +++ b/plugin/trino-phoenix5/src/main/java/io/trino/plugin/phoenix5/PhoenixClient.java @@ -564,6 +564,9 @@ public Optional getTableComment(ResultSet resultSet) @Override public JdbcOutputTableHandle beginCreateTable(ConnectorSession session, ConnectorTableMetadata tableMetadata) { + if (tableMetadata.getComment().isPresent()) { + throw new TrinoException(NOT_SUPPORTED, "This connector does not support creating tables with table comment"); + } SchemaTableName schemaTableName = tableMetadata.getTable(); String schema = schemaTableName.getSchemaName(); String table = schemaTableName.getTableName(); diff --git a/plugin/trino-phoenix5/src/test/java/io/trino/plugin/phoenix5/TestPhoenixConnectorTest.java b/plugin/trino-phoenix5/src/test/java/io/trino/plugin/phoenix5/TestPhoenixConnectorTest.java index c9ecc7ee83eb..acf256c4c979 100644 --- a/plugin/trino-phoenix5/src/test/java/io/trino/plugin/phoenix5/TestPhoenixConnectorTest.java +++ b/plugin/trino-phoenix5/src/test/java/io/trino/plugin/phoenix5/TestPhoenixConnectorTest.java @@ -89,6 +89,7 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior) case SUPPORTS_AGGREGATION_PUSHDOWN: return false; + case SUPPORTS_CREATE_TABLE_WITH_TABLE_COMMENT: case SUPPORTS_COMMENT_ON_TABLE: case SUPPORTS_COMMENT_ON_COLUMN: case SUPPORTS_ADD_COLUMN_WITH_COMMENT: diff --git a/plugin/trino-postgresql/src/test/java/io/trino/plugin/postgresql/TestPostgreSqlConnectorTest.java b/plugin/trino-postgresql/src/test/java/io/trino/plugin/postgresql/TestPostgreSqlConnectorTest.java index b61f2bcfa551..06a68035e2fc 100644 --- a/plugin/trino-postgresql/src/test/java/io/trino/plugin/postgresql/TestPostgreSqlConnectorTest.java +++ b/plugin/trino-postgresql/src/test/java/io/trino/plugin/postgresql/TestPostgreSqlConnectorTest.java @@ -118,6 +118,7 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior) case SUPPORTS_JOIN_PUSHDOWN: return true; + case SUPPORTS_CREATE_TABLE_WITH_TABLE_COMMENT: case SUPPORTS_COMMENT_ON_TABLE: case SUPPORTS_ADD_COLUMN_WITH_COMMENT: return false; diff --git a/plugin/trino-raptor-legacy/src/main/java/io/trino/plugin/raptor/legacy/RaptorMetadata.java b/plugin/trino-raptor-legacy/src/main/java/io/trino/plugin/raptor/legacy/RaptorMetadata.java index b074e38d0016..9f9e611c3bd5 100644 --- a/plugin/trino-raptor-legacy/src/main/java/io/trino/plugin/raptor/legacy/RaptorMetadata.java +++ b/plugin/trino-raptor-legacy/src/main/java/io/trino/plugin/raptor/legacy/RaptorMetadata.java @@ -550,6 +550,9 @@ public ConnectorOutputTableHandle beginCreateTable(ConnectorSession session, Con if (retryMode != NO_RETRIES) { throw new TrinoException(NOT_SUPPORTED, "This connector does not support query retries"); } + if (tableMetadata.getComment().isPresent()) { + throw new TrinoException(NOT_SUPPORTED, "This connector does not support creating tables with table comment"); + } if (viewExists(session, tableMetadata.getTable())) { throw new TrinoException(ALREADY_EXISTS, "View already exists: " + tableMetadata.getTable()); diff --git a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/BaseRaptorConnectorTest.java b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/BaseRaptorConnectorTest.java index 33924f2c21b7..b1356409f7f0 100644 --- a/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/BaseRaptorConnectorTest.java +++ b/plugin/trino-raptor-legacy/src/test/java/io/trino/plugin/raptor/legacy/BaseRaptorConnectorTest.java @@ -74,6 +74,7 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior) return true; case SUPPORTS_CREATE_SCHEMA: case SUPPORTS_RENAME_SCHEMA: + case SUPPORTS_CREATE_TABLE_WITH_TABLE_COMMENT: case SUPPORTS_COMMENT_ON_TABLE: case SUPPORTS_COMMENT_ON_COLUMN: case SUPPORTS_ADD_COLUMN_WITH_COMMENT: diff --git a/plugin/trino-singlestore/src/test/java/io/trino/plugin/singlestore/TestSingleStoreConnectorTest.java b/plugin/trino-singlestore/src/test/java/io/trino/plugin/singlestore/TestSingleStoreConnectorTest.java index ed01249d589f..14279cfc97a4 100644 --- a/plugin/trino-singlestore/src/test/java/io/trino/plugin/singlestore/TestSingleStoreConnectorTest.java +++ b/plugin/trino-singlestore/src/test/java/io/trino/plugin/singlestore/TestSingleStoreConnectorTest.java @@ -79,6 +79,7 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior) case SUPPORTS_JOIN_PUSHDOWN_WITH_DISTINCT_FROM: return false; + case SUPPORTS_CREATE_TABLE_WITH_TABLE_COMMENT: case SUPPORTS_COMMENT_ON_TABLE: case SUPPORTS_COMMENT_ON_COLUMN: case SUPPORTS_ADD_COLUMN_WITH_COMMENT: diff --git a/plugin/trino-sqlserver/src/main/java/io/trino/plugin/sqlserver/SqlServerClient.java b/plugin/trino-sqlserver/src/main/java/io/trino/plugin/sqlserver/SqlServerClient.java index f690bb644c90..3d6ae8d2c8fe 100644 --- a/plugin/trino-sqlserver/src/main/java/io/trino/plugin/sqlserver/SqlServerClient.java +++ b/plugin/trino-sqlserver/src/main/java/io/trino/plugin/sqlserver/SqlServerClient.java @@ -858,6 +858,9 @@ protected boolean isSupportedJoinCondition(ConnectorSession session, JdbcJoinCon @Override protected String createTableSql(RemoteTableName remoteTableName, List columns, ConnectorTableMetadata tableMetadata) { + if (tableMetadata.getComment().isPresent()) { + throw new TrinoException(NOT_SUPPORTED, "This connector does not support creating tables with table comment"); + } return format( "CREATE TABLE %s (%s) %s", quoted(remoteTableName), diff --git a/plugin/trino-sqlserver/src/test/java/io/trino/plugin/sqlserver/BaseSqlServerConnectorTest.java b/plugin/trino-sqlserver/src/test/java/io/trino/plugin/sqlserver/BaseSqlServerConnectorTest.java index 24d9a6a31af0..7c8dae460edb 100644 --- a/plugin/trino-sqlserver/src/test/java/io/trino/plugin/sqlserver/BaseSqlServerConnectorTest.java +++ b/plugin/trino-sqlserver/src/test/java/io/trino/plugin/sqlserver/BaseSqlServerConnectorTest.java @@ -71,6 +71,9 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior) case SUPPORTS_JOIN_PUSHDOWN_WITH_DISTINCT_FROM: return false; + case SUPPORTS_CREATE_TABLE_WITH_TABLE_COMMENT: + return false; + case SUPPORTS_COMMENT_ON_TABLE: case SUPPORTS_COMMENT_ON_COLUMN: return false; diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-delta-lake-databricks/delta.properties b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-delta-lake-databricks/delta.properties index dcf0881785bc..d84e99d50230 100644 --- a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-delta-lake-databricks/delta.properties +++ b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/singlenode-delta-lake-databricks/delta.properties @@ -2,6 +2,5 @@ connector.name=delta-lake hive.metastore.uri=${ENV:HIVE_METASTORE_URI} # We need to give access to bucket owner (the AWS account integrated with Databricks), otherwise files won't be readable from Databricks hive.s3.upload-acl-type=BUCKET_OWNER_FULL_CONTROL -hive.security=allow-all delta.enable-non-concurrent-writes=true delta.hive-catalog-name=hive diff --git a/testing/trino-product-tests/src/main/java/io/trino/tests/product/deltalake/TestDeltaLakeDatabricksCreateTableCompatibility.java b/testing/trino-product-tests/src/main/java/io/trino/tests/product/deltalake/TestDeltaLakeDatabricksCreateTableCompatibility.java index 990f33ca231e..d92c661da249 100644 --- a/testing/trino-product-tests/src/main/java/io/trino/tests/product/deltalake/TestDeltaLakeDatabricksCreateTableCompatibility.java +++ b/testing/trino-product-tests/src/main/java/io/trino/tests/product/deltalake/TestDeltaLakeDatabricksCreateTableCompatibility.java @@ -15,6 +15,7 @@ import com.google.common.collect.ImmutableList; import io.trino.tempto.assertions.QueryAssert; +import io.trino.tempto.query.QueryResult; import org.testng.annotations.Test; import java.util.List; @@ -27,6 +28,7 @@ import static io.trino.tests.product.utils.QueryExecutors.onDelta; import static io.trino.tests.product.utils.QueryExecutors.onTrino; import static java.lang.String.format; +import static org.testng.Assert.assertEquals; public class TestDeltaLakeDatabricksCreateTableCompatibility extends BaseTestDeltaLakeS3Storage @@ -171,4 +173,35 @@ private void testInsert(String tableName, List existingRows) assertThat(onTrino().executeQuery("SELECT integer, string, to_iso8601(timetz) FROM delta.default." + tableName)) .containsOnly(expected.build()); } + + @Test(groups = {DELTA_LAKE_DATABRICKS, PROFILE_SPECIFIC_TESTS}) + public void testCreateTableWithTableComment() + { + String tableName = "test_dl_create_table_comment_" + randomTableSuffix(); + String tableDirectory = "databricks-compatibility-test-" + tableName; + + onTrino().executeQuery(format("CREATE TABLE delta.default.%s (col INT) COMMENT 'test comment' WITH (location = 's3://%s/%s')", + tableName, + bucketName, + tableDirectory)); + + try { + assertThat(onTrino().executeQuery("SELECT comment FROM system.metadata.table_comments WHERE catalog_name = 'delta' AND schema_name = 'default' AND table_name = '" + tableName + "'")) + .containsOnly(row("test comment")); + + assertEquals(getTableCommentOnDelta("default", tableName), "test comment"); + } + finally { + onTrino().executeQuery("DROP TABLE delta.default." + tableName); + } + } + + private static String getTableCommentOnDelta(String schemaName, String tableName) + { + QueryResult result = onDelta().executeQuery(format("DESCRIBE EXTENDED %s.%s", schemaName, tableName)); + return (String) result.rows().stream() + .filter(row -> row.get(0).equals("Comment")) + .map(row -> row.get(1)) + .findFirst().orElseThrow(); + } } diff --git a/testing/trino-testing/src/main/java/io/trino/testing/BaseConnectorTest.java b/testing/trino-testing/src/main/java/io/trino/testing/BaseConnectorTest.java index 8851e7fa86cc..94a7def8999c 100644 --- a/testing/trino-testing/src/main/java/io/trino/testing/BaseConnectorTest.java +++ b/testing/trino-testing/src/main/java/io/trino/testing/BaseConnectorTest.java @@ -83,6 +83,7 @@ import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_CREATE_SCHEMA; import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_CREATE_TABLE; import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_CREATE_TABLE_WITH_DATA; +import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_CREATE_TABLE_WITH_TABLE_COMMENT; import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_CREATE_VIEW; import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_DELETE; import static io.trino.testing.TestingConnectorBehavior.SUPPORTS_DROP_COLUMN; @@ -1891,6 +1892,24 @@ public void testCreateTable() assertFalse(getQueryRunner().tableExists(getSession(), tableNameLike)); } + @Test + public void testCreateTableWithTableComment() + { + skipTestUnless(hasBehavior(SUPPORTS_CREATE_TABLE)); + + String tableName = "test_create_" + randomTableSuffix(); + + if (!hasBehavior(SUPPORTS_CREATE_TABLE_WITH_TABLE_COMMENT)) { + assertQueryFails("CREATE TABLE " + tableName + " (a bigint) COMMENT 'test comment'", "This connector does not support creating tables with table comment"); + return; + } + + assertUpdate("CREATE TABLE " + tableName + " (a bigint) COMMENT 'test comment'"); + assertEquals(getTableComment(getSession().getCatalog().orElseThrow(), getSession().getSchema().orElseThrow(), tableName), "test comment"); + + assertUpdate("DROP TABLE " + tableName); + } + @Test public void testCreateTableSchemaNotFound() { @@ -1980,6 +1999,24 @@ public void testCreateTableAsSelect() assertUpdate("DROP TABLE " + tableName); } + @Test + public void testCreateTableAsSelectWithTableComment() + { + skipTestUnless(hasBehavior(SUPPORTS_CREATE_TABLE_WITH_DATA)); + + String tableName = "test_ctas_" + randomTableSuffix(); + + if (!hasBehavior(SUPPORTS_CREATE_TABLE_WITH_TABLE_COMMENT)) { + assertQueryFails("CREATE TABLE " + tableName + " COMMENT 'test comment' AS SELECT name FROM nation", "This connector does not support creating tables with table comment"); + return; + } + + assertUpdate("CREATE TABLE " + tableName + " COMMENT 'test comment' AS SELECT name FROM nation", 25); + assertEquals(getTableComment(getSession().getCatalog().orElseThrow(), getSession().getSchema().orElseThrow(), tableName), "test comment"); + + assertUpdate("DROP TABLE " + tableName); + } + @Test public void testCreateTableAsSelectSchemaNotFound() { diff --git a/testing/trino-testing/src/main/java/io/trino/testing/TestingConnectorBehavior.java b/testing/trino-testing/src/main/java/io/trino/testing/TestingConnectorBehavior.java index 0863433cc245..40cb810eaaa9 100644 --- a/testing/trino-testing/src/main/java/io/trino/testing/TestingConnectorBehavior.java +++ b/testing/trino-testing/src/main/java/io/trino/testing/TestingConnectorBehavior.java @@ -54,6 +54,7 @@ public enum TestingConnectorBehavior SUPPORTS_CREATE_TABLE, SUPPORTS_CREATE_TABLE_WITH_DATA(SUPPORTS_CREATE_TABLE), + SUPPORTS_CREATE_TABLE_WITH_TABLE_COMMENT(SUPPORTS_CREATE_TABLE), SUPPORTS_RENAME_TABLE, SUPPORTS_RENAME_TABLE_ACROSS_SCHEMAS(SUPPORTS_RENAME_TABLE),