diff --git a/plugin/trino-hive-hadoop2/src/test/java/io/trino/plugin/hive/TestHiveAlluxioMetastore.java b/plugin/trino-hive-hadoop2/src/test/java/io/trino/plugin/hive/TestHiveAlluxioMetastore.java index 6b159364bcd1..ecd0326f00f3 100644 --- a/plugin/trino-hive-hadoop2/src/test/java/io/trino/plugin/hive/TestHiveAlluxioMetastore.java +++ b/plugin/trino-hive-hadoop2/src/test/java/io/trino/plugin/hive/TestHiveAlluxioMetastore.java @@ -166,6 +166,13 @@ public void testHideDeltaLakeTables() throw new SkipException("not supported"); } + @Override + public void testDisallowQueryingOfIcebergTables() + { + // Alluxio metastore does not support create operations + throw new SkipException("not supported"); + } + @Override public void testIllegalStorageFormatDuringTableScan() { diff --git a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/HiveMetadata.java b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/HiveMetadata.java index cc747f3325d9..f74aacdc784d 100644 --- a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/HiveMetadata.java +++ b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/HiveMetadata.java @@ -267,6 +267,7 @@ import static io.trino.plugin.hive.util.HiveUtil.hiveColumnHandles; import static io.trino.plugin.hive.util.HiveUtil.isDeltaLakeTable; import static io.trino.plugin.hive.util.HiveUtil.isHiveSystemSchema; +import static io.trino.plugin.hive.util.HiveUtil.isIcebergTable; import static io.trino.plugin.hive.util.HiveUtil.toPartitionValues; import static io.trino.plugin.hive.util.HiveUtil.verifyPartitionTypeSupported; import static io.trino.plugin.hive.util.HiveWriteUtils.checkTableIsWritable; @@ -436,6 +437,9 @@ public HiveTableHandle getTableHandle(ConnectorSession session, SchemaTableName if (isDeltaLakeTable(table)) { throw new TrinoException(HIVE_UNSUPPORTED_FORMAT, format("Cannot query Delta Lake table '%s'", tableName)); } + if (isIcebergTable(table)) { + throw new TrinoException(HIVE_UNSUPPORTED_FORMAT, format("Cannot query Iceberg table '%s'", tableName)); + } // we must not allow system tables due to how permissions are checked in SystemTableAwareAccessControl if (getSourceTableNameFromSystemTable(systemTableProviders, tableName).isPresent()) { diff --git a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/PartitionsSystemTableProvider.java b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/PartitionsSystemTableProvider.java index 896c939af899..7dcead9401b3 100644 --- a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/PartitionsSystemTableProvider.java +++ b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/PartitionsSystemTableProvider.java @@ -14,6 +14,7 @@ package io.trino.plugin.hive; import io.trino.plugin.hive.authentication.HiveIdentity; +import io.trino.plugin.hive.metastore.Table; import io.trino.spi.connector.ColumnMetadata; import io.trino.spi.connector.ConnectorSession; import io.trino.spi.connector.ConnectorTableMetadata; @@ -22,6 +23,7 @@ import io.trino.spi.connector.SchemaTableName; import io.trino.spi.connector.SystemTable; import io.trino.spi.type.Type; +import io.trino.spi.type.TypeManager; import javax.inject.Inject; @@ -33,7 +35,15 @@ import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.ImmutableMap.toImmutableMap; import static com.google.common.collect.Streams.stream; +import static io.trino.plugin.hive.HiveSessionProperties.getTimestampPrecision; import static io.trino.plugin.hive.SystemTableHandler.PARTITIONS; +import static io.trino.plugin.hive.metastore.MetastoreUtil.getProtectMode; +import static io.trino.plugin.hive.metastore.MetastoreUtil.verifyOnline; +import static io.trino.plugin.hive.util.HiveBucketing.getHiveBucketHandle; +import static io.trino.plugin.hive.util.HiveUtil.getPartitionKeyColumnHandles; +import static io.trino.plugin.hive.util.HiveUtil.getRegularColumnHandles; +import static io.trino.plugin.hive.util.HiveUtil.isDeltaLakeTable; +import static io.trino.plugin.hive.util.HiveUtil.isIcebergTable; import static io.trino.plugin.hive.util.SystemTables.createSystemTable; import static java.util.Objects.requireNonNull; import static java.util.function.Function.identity; @@ -43,11 +53,13 @@ public class PartitionsSystemTableProvider implements SystemTableProvider { private final HivePartitionManager partitionManager; + private final TypeManager typeManager; @Inject - public PartitionsSystemTableProvider(HivePartitionManager partitionManager) + public PartitionsSystemTableProvider(HivePartitionManager partitionManager, TypeManager typeManager) { this.partitionManager = requireNonNull(partitionManager, "partitionManager is null"); + this.typeManager = requireNonNull(typeManager, "typeManager is null"); } @Override @@ -68,11 +80,20 @@ public Optional getSystemTable(HiveMetadata metadata, ConnectorSess } SchemaTableName sourceTableName = PARTITIONS.getSourceTableName(tableName); - HiveTableHandle sourceTableHandle = metadata.getTableHandle(session, sourceTableName); - - if (sourceTableHandle == null) { + Table sourceTable = metadata.getMetastore() + .getTable(new HiveIdentity(session), sourceTableName.getSchemaName(), sourceTableName.getTableName()) + .orElse(null); + if (sourceTable == null || isDeltaLakeTable(sourceTable) || isIcebergTable(sourceTable)) { return Optional.empty(); } + verifyOnline(sourceTableName, Optional.empty(), getProtectMode(sourceTable), sourceTable.getParameters()); + HiveTableHandle sourceTableHandle = new HiveTableHandle( + sourceTableName.getSchemaName(), + sourceTableName.getTableName(), + sourceTable.getParameters(), + getPartitionKeyColumnHandles(sourceTable, typeManager), + getRegularColumnHandles(sourceTable, typeManager, getTimestampPrecision(session)), + getHiveBucketHandle(session, sourceTable, typeManager)); List partitionColumns = sourceTableHandle.getPartitionColumns(); if (partitionColumns.isEmpty()) { diff --git a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/PropertiesSystemTableProvider.java b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/PropertiesSystemTableProvider.java index 76da893961b2..af4fee2f1bd2 100644 --- a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/PropertiesSystemTableProvider.java +++ b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/PropertiesSystemTableProvider.java @@ -17,7 +17,6 @@ import com.google.common.collect.ImmutableSortedMap; import io.trino.plugin.hive.authentication.HiveIdentity; import io.trino.plugin.hive.metastore.Table; -import io.trino.spi.TrinoException; import io.trino.spi.connector.ColumnMetadata; import io.trino.spi.connector.ConnectorSession; import io.trino.spi.connector.ConnectorTableMetadata; @@ -33,11 +32,10 @@ import java.util.Optional; import static com.google.common.collect.ImmutableList.toImmutableList; -import static io.trino.plugin.hive.HiveErrorCode.HIVE_UNSUPPORTED_FORMAT; import static io.trino.plugin.hive.SystemTableHandler.PROPERTIES; import static io.trino.plugin.hive.util.HiveUtil.isDeltaLakeTable; +import static io.trino.plugin.hive.util.HiveUtil.isIcebergTable; import static io.trino.plugin.hive.util.SystemTables.createSystemTable; -import static java.lang.String.format; public class PropertiesSystemTableProvider implements SystemTableProvider @@ -64,8 +62,8 @@ public Optional getSystemTable(HiveMetadata metadata, ConnectorSess .getTable(new HiveIdentity(session), sourceTableName.getSchemaName(), sourceTableName.getTableName()) .orElseThrow(() -> new TableNotFoundException(tableName)); - if (isDeltaLakeTable(table)) { - throw new TrinoException(HIVE_UNSUPPORTED_FORMAT, format("Cannot query Delta Lake table '%s'", sourceTableName)); + if (isDeltaLakeTable(table) || isIcebergTable(table)) { + return Optional.empty(); } Map sortedTableParameters = ImmutableSortedMap.copyOf(table.getParameters()); List columns = sortedTableParameters.keySet().stream() diff --git a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/util/HiveUtil.java b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/util/HiveUtil.java index 02e4a8910433..35e8b959dea4 100644 --- a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/util/HiveUtil.java +++ b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/util/HiveUtil.java @@ -180,6 +180,9 @@ public final class HiveUtil public static final String SPARK_TABLE_PROVIDER_KEY = "spark.sql.sources.provider"; public static final String DELTA_LAKE_PROVIDER = "delta"; + public static final String ICEBERG_TABLE_TYPE_NAME = "table_type"; + public static final String ICEBERG_TABLE_TYPE_VALUE = "iceberg"; + private static final DateTimeFormatter HIVE_DATE_PARSER = ISODateTimeFormat.date().withZoneUTC(); private static final DateTimeFormatter HIVE_TIMESTAMP_PARSER; private static final Field COMPRESSION_CODECS_FIELD; @@ -191,8 +194,6 @@ public final class HiveUtil private static final String BIG_DECIMAL_POSTFIX = "BD"; private static final Splitter COLUMN_NAMES_SPLITTER = Splitter.on(',').trimResults().omitEmptyStrings(); - private static final String ICEBERG_TABLE_TYPE_NAME = "table_type"; - private static final String ICEBERG_TABLE_TYPE_VALUE = "iceberg"; static { DateTimeParser[] timestampWithoutTimeZoneParser = { diff --git a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/AbstractTestHive.java b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/AbstractTestHive.java index 2c0f06271104..10da35f2e44a 100644 --- a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/AbstractTestHive.java +++ b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/AbstractTestHive.java @@ -260,6 +260,8 @@ import static io.trino.plugin.hive.metastore.cache.CachingHiveMetastore.cachingHiveMetastore; import static io.trino.plugin.hive.util.HiveBucketing.BucketingVersion.BUCKETING_V1; import static io.trino.plugin.hive.util.HiveUtil.DELTA_LAKE_PROVIDER; +import static io.trino.plugin.hive.util.HiveUtil.ICEBERG_TABLE_TYPE_NAME; +import static io.trino.plugin.hive.util.HiveUtil.ICEBERG_TABLE_TYPE_VALUE; import static io.trino.plugin.hive.util.HiveUtil.SPARK_TABLE_PROVIDER_KEY; import static io.trino.plugin.hive.util.HiveUtil.columnExtraInfo; import static io.trino.plugin.hive.util.HiveUtil.toPartitionValues; @@ -839,7 +841,7 @@ protected final void setup(String databaseName, HiveConfig hiveConfig, HiveMetas TupleDomain.all())); }, ImmutableSet.of( - new PartitionsSystemTableProvider(partitionManager), + new PartitionsSystemTableProvider(partitionManager, TESTING_TYPE_MANAGER), new PropertiesSystemTableProvider()), (metastore) -> new NoneHiveMaterializedViewMetadata() { @@ -2899,22 +2901,14 @@ public void testHideDeltaLakeTables() .hasMessage(format("Cannot query Delta Lake table '%s'", tableName)); } - // Verify the hidden `$properties` Delta Lake table handle can't be obtained within the hive connector - SchemaTableName propertiesTableName = new SchemaTableName(tableName.getSchemaName(), format("%s$properties", tableName.getTableName())); + // Verify the hidden `$properties` and `$partitions` Delta Lake table handle can't be obtained within the hive connector try (Transaction transaction = newTransaction()) { ConnectorMetadata metadata = transaction.getMetadata(); metadata.beginQuery(session); - assertThatThrownBy(() -> metadata.getSystemTable(newSession(), propertiesTableName)) - .hasMessage(format("Cannot query Delta Lake table '%s'", tableName)); - } - - // Verify the hidden `$partitions` Delta Lake table handle can't be obtained within the hive connector - SchemaTableName partitionsTableName = new SchemaTableName(tableName.getSchemaName(), format("%s$partitions", tableName.getTableName())); - try (Transaction transaction = newTransaction()) { - ConnectorMetadata metadata = transaction.getMetadata(); - metadata.beginQuery(session); - assertThatThrownBy(() -> metadata.getSystemTable(newSession(), partitionsTableName)) - .hasMessage(format("Cannot query Delta Lake table '%s'", tableName)); + SchemaTableName propertiesTableName = new SchemaTableName(tableName.getSchemaName(), format("%s$properties", tableName.getTableName())); + assertThat(metadata.getSystemTable(newSession(), propertiesTableName)).isEmpty(); + SchemaTableName partitionsTableName = new SchemaTableName(tableName.getSchemaName(), format("%s$partitions", tableName.getTableName())); + assertThat(metadata.getSystemTable(newSession(), partitionsTableName)).isEmpty(); } // Assert that table is hidden @@ -2951,6 +2945,56 @@ public void testHideDeltaLakeTables() } } + @Test + public void testDisallowQueryingOfIcebergTables() + { + ConnectorSession session = newSession(); + HiveIdentity identity = new HiveIdentity(session); + SchemaTableName tableName = temporaryTable("trino_iceberg_table"); + + Table.Builder table = Table.builder() + .setDatabaseName(tableName.getSchemaName()) + .setTableName(tableName.getTableName()) + .setOwner(Optional.of(session.getUser())) + .setTableType(MANAGED_TABLE.name()) + .setPartitionColumns(List.of(new Column("a_partition_column", HIVE_INT, Optional.empty()))) + .setDataColumns(List.of(new Column("a_column", HIVE_STRING, Optional.empty()))) + .setParameter(ICEBERG_TABLE_TYPE_NAME, ICEBERG_TABLE_TYPE_VALUE); + table.getStorageBuilder() + .setStorageFormat(fromHiveStorageFormat(PARQUET)) + .setLocation(getTableDefaultLocation( + metastoreClient.getDatabase(tableName.getSchemaName()).orElseThrow(), + new HdfsContext(session.getIdentity()), + hdfsEnvironment, + tableName.getSchemaName(), + tableName.getTableName()).toString()); + metastoreClient.createTable(identity, table.build(), NO_PRIVILEGES); + + try { + // Verify that the table was created as a Iceberg table can't be queried in hive + try (Transaction transaction = newTransaction()) { + ConnectorMetadata metadata = transaction.getMetadata(); + metadata.beginQuery(session); + assertThatThrownBy(() -> getTableHandle(metadata, tableName)) + .hasMessage(format("Cannot query Iceberg table '%s'", tableName)); + } + + // Verify the hidden `$properties` and `$partitions` hive system tables table handle can't be obtained for the Iceberg tables + try (Transaction transaction = newTransaction()) { + ConnectorMetadata metadata = transaction.getMetadata(); + metadata.beginQuery(session); + SchemaTableName propertiesTableName = new SchemaTableName(tableName.getSchemaName(), format("%s$properties", tableName.getTableName())); + assertThat(metadata.getSystemTable(newSession(), propertiesTableName)).isEmpty(); + SchemaTableName partitionsTableName = new SchemaTableName(tableName.getSchemaName(), format("%s$partitions", tableName.getTableName())); + assertThat(metadata.getSystemTable(newSession(), partitionsTableName)).isEmpty(); + } + } + finally { + // Clean up + metastoreClient.dropTable(identity, tableName.getSchemaName(), tableName.getTableName(), true); + } + } + @Test public void testUpdateBasicTableStatistics() throws Exception diff --git a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/AbstractTestHiveFileSystem.java b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/AbstractTestHiveFileSystem.java index 41f2bf5edada..e86fb471367e 100644 --- a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/AbstractTestHiveFileSystem.java +++ b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/AbstractTestHiveFileSystem.java @@ -217,7 +217,7 @@ protected void setup(String host, int port, String databaseName, boolean s3Selec new NodeVersion("test_version"), new NoneHiveRedirectionsProvider(), ImmutableSet.of( - new PartitionsSystemTableProvider(hivePartitionManager), + new PartitionsSystemTableProvider(hivePartitionManager, TESTING_TYPE_MANAGER), new PropertiesSystemTableProvider()), new DefaultHiveMaterializedViewMetadataFactory(), SqlStandardAccessControlMetadata::new, diff --git a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/TestHiveInMemoryMetastore.java b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/TestHiveInMemoryMetastore.java index 8d2f3bde556d..44667f59d5c4 100644 --- a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/TestHiveInMemoryMetastore.java +++ b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/TestHiveInMemoryMetastore.java @@ -61,4 +61,10 @@ public void testHideDeltaLakeTables() { throw new SkipException("not supported"); } + + @Override + public void testDisallowQueryingOfIcebergTables() + { + throw new SkipException("not supported"); + } } diff --git a/testing/trino-product-tests/src/main/java/io/trino/tests/product/hive/TestHiveRedirectionToIceberg.java b/testing/trino-product-tests/src/main/java/io/trino/tests/product/hive/TestHiveRedirectionToIceberg.java index 4294080efcf0..4824f3c4caff 100644 --- a/testing/trino-product-tests/src/main/java/io/trino/tests/product/hive/TestHiveRedirectionToIceberg.java +++ b/testing/trino-product-tests/src/main/java/io/trino/tests/product/hive/TestHiveRedirectionToIceberg.java @@ -230,9 +230,9 @@ public void testDropTable() String icebergTableName = "iceberg.default." + tableName; createIcebergTable(icebergTableName, false); - onTrino().executeQuery("DROP TABLE " + hiveTableName); - assertQueryFailure(() -> onTrino().executeQuery("TABLE " + icebergTableName)) - .hasMessageMatching("\\QQuery failed (#\\E\\S+\\Q): line 1:1: Table '" + icebergTableName + "' does not exist"); + //TODO restore test assertions after adding redirection awareness to the DropTableTask + assertQueryFailure(() -> onTrino().executeQuery("DROP TABLE " + hiveTableName)) + .hasMessageMatching("\\QQuery failed (#\\E\\S+\\Q): Cannot query Iceberg table 'default." + tableName + "'"); } @Test(groups = {HIVE_ICEBERG_REDIRECTIONS, PROFILE_SPECIFIC_TESTS}) @@ -305,18 +305,11 @@ public void testAlterTableRename() createIcebergTable(icebergTableName, false); - onTrino().executeQuery("ALTER TABLE " + hiveTableName + " RENAME TO " + tableName + "_new"); + //TODO restore test assertions after adding redirection awareness to the RenameTableTask + assertQueryFailure(() -> onTrino().executeQuery("ALTER TABLE " + hiveTableName + " RENAME TO " + tableName + "_new")) + .hasMessageMatching("\\QQuery failed (#\\E\\S+\\Q): Cannot query Iceberg table 'default." + tableName + "'"); - assertQueryFailure(() -> onTrino().executeQuery("TABLE " + hiveTableName)) - .hasMessageMatching("\\QQuery failed (#\\E\\S+\\Q): line 1:1: Table '" + hiveTableName + "' does not exist"); - assertQueryFailure(() -> onTrino().executeQuery("TABLE " + icebergTableName)) - .hasMessageMatching("\\QQuery failed (#\\E\\S+\\Q): line 1:1: Table '" + icebergTableName + "' does not exist"); - - assertResultsEqual( - onTrino().executeQuery("TABLE " + icebergTableName + "_new"), - onTrino().executeQuery("TABLE " + hiveTableName + "_new")); - - onTrino().executeQuery("DROP TABLE " + icebergTableName + "_new"); + onTrino().executeQuery("DROP TABLE " + icebergTableName); } @Test(groups = {HIVE_ICEBERG_REDIRECTIONS, PROFILE_SPECIFIC_TESTS}) @@ -328,15 +321,9 @@ public void testAlterTableAddColumn() createIcebergTable(icebergTableName, false); - onTrino().executeQuery("ALTER TABLE " + hiveTableName + " ADD COLUMN some_new_column double"); - - // TODO: ALTER TABLE succeeded, but new column was not added - Assertions.assertThat(onTrino().executeQuery("DESCRIBE " + icebergTableName).column(1)) - .containsOnly("nationkey", "name", "regionkey", "comment"); - - assertResultsEqual( - onTrino().executeQuery("TABLE " + icebergTableName), - onTrino().executeQuery("SELECT * /*, NULL*/ FROM tpch.tiny.nation")); + //TODO restore test assertions after adding redirection awareness to the AddColumnTask + assertQueryFailure(() -> onTrino().executeQuery("ALTER TABLE " + hiveTableName + " ADD COLUMN some_new_column double")) + .hasMessageMatching("\\QQuery failed (#\\E\\S+\\Q): Cannot query Iceberg table 'default." + tableName + "'"); onTrino().executeQuery("DROP TABLE " + icebergTableName); } @@ -353,11 +340,9 @@ public void testCommentTable() assertTableComment("hive", "default", tableName).isNull(); assertTableComment("iceberg", "default", tableName).isNull(); - onTrino().executeQuery("COMMENT ON TABLE " + hiveTableName + " IS 'This is my table, there are many like it but this one is mine'"); - - // TODO: COMMENT ON TABLE succeeded, but comment was not preserved - assertTableComment("hive", "default", tableName).isNull(); - assertTableComment("iceberg", "default", tableName).isNull(); + //TODO restore test assertions after adding redirection awareness to the CommentTask + assertQueryFailure(() -> onTrino().executeQuery("COMMENT ON TABLE " + hiveTableName + " IS 'This is my table, there are many like it but this one is mine'")) + .hasMessageMatching("\\QQuery failed (#\\E\\S+\\Q): Cannot query Iceberg table 'default." + tableName + "'"); onTrino().executeQuery("DROP TABLE " + icebergTableName); } diff --git a/testing/trino-product-tests/src/main/java/io/trino/tests/product/iceberg/TestIcebergHiveTablesCompatibility.java b/testing/trino-product-tests/src/main/java/io/trino/tests/product/iceberg/TestIcebergHiveTablesCompatibility.java index 08213a85baed..a30250879ab7 100644 --- a/testing/trino-product-tests/src/main/java/io/trino/tests/product/iceberg/TestIcebergHiveTablesCompatibility.java +++ b/testing/trino-product-tests/src/main/java/io/trino/tests/product/iceberg/TestIcebergHiveTablesCompatibility.java @@ -17,12 +17,12 @@ import org.testng.annotations.Test; import static io.trino.tempto.assertions.QueryAssert.assertQueryFailure; -import static io.trino.tempto.assertions.QueryAssert.assertThat; import static io.trino.tests.product.TestGroups.HMS_ONLY; import static io.trino.tests.product.TestGroups.ICEBERG; import static io.trino.tests.product.TestGroups.STORAGE_FORMATS; import static io.trino.tests.product.hive.util.TemporaryHiveTable.randomTableSuffix; import static io.trino.tests.product.utils.QueryExecutors.onTrino; +import static java.lang.String.format; public class TestIcebergHiveTablesCompatibility extends ProductTest @@ -49,15 +49,13 @@ public void testHiveSelectFromIcebergTable() onTrino().executeQuery("CREATE TABLE iceberg.default." + tableName + "(a bigint)"); assertQueryFailure(() -> onTrino().executeQuery("SELECT * FROM hive.default." + tableName)) - // TODO (https://github.com/trinodb/trino/issues/8693) throw specific exception message - .hasMessageMatching("Query failed \\(#\\w+\\):\\Q Unable to create input format org.apache.hadoop.mapred.FileInputFormat"); + .hasMessageMatching(format("Query failed \\(#\\w+\\):\\Q Cannot query Iceberg table 'default.%s'", tableName)); assertQueryFailure(() -> onTrino().executeQuery("SELECT * FROM hive.default.\"" + tableName + "$partitions\"")) .hasMessageMatching("Query failed \\(#\\w+\\):\\Q line 1:15: Table 'hive.default." + tableName + "$partitions' does not exist"); - // TODO (https://github.com/trinodb/trino/issues/8693) should fail - assertThat(onTrino().executeQuery("SELECT * FROM hive.default.\"" + tableName + "$properties\"")) - .hasRowsCount(1); + assertQueryFailure(() -> onTrino().executeQuery("SELECT * FROM hive.default.\"" + tableName + "$properties\"")) + .hasMessageMatching("Query failed \\(#\\w+\\):\\Q line 1:15: Table 'hive.default." + tableName + "$properties' does not exist"); onTrino().executeQuery("DROP TABLE iceberg.default." + tableName); } diff --git a/testing/trino-product-tests/src/main/java/io/trino/tests/product/iceberg/TestIcebergHiveViewsCompatibility.java b/testing/trino-product-tests/src/main/java/io/trino/tests/product/iceberg/TestIcebergHiveViewsCompatibility.java index a22c63f4dbe2..1086060f4845 100644 --- a/testing/trino-product-tests/src/main/java/io/trino/tests/product/iceberg/TestIcebergHiveViewsCompatibility.java +++ b/testing/trino-product-tests/src/main/java/io/trino/tests/product/iceberg/TestIcebergHiveViewsCompatibility.java @@ -21,6 +21,7 @@ import java.util.List; import static io.trino.tempto.assertions.QueryAssert.Row.row; +import static io.trino.tempto.assertions.QueryAssert.assertQueryFailure; import static io.trino.tempto.assertions.QueryAssert.assertThat; import static io.trino.tests.product.TestGroups.HMS_ONLY; import static io.trino.tests.product.TestGroups.ICEBERG; @@ -53,8 +54,8 @@ public void testIcebergHiveViewsCompatibility() onTrino().executeQuery("CREATE VIEW hive.default.hive_view_qualified_hive AS SELECT * FROM hive.default.hive_table"); onTrino().executeQuery("CREATE VIEW hive.default.hive_view_unqualified_hive AS SELECT * FROM hive_table"); onTrino().executeQuery("CREATE VIEW hive.default.hive_view_qualified_iceberg AS SELECT * FROM iceberg.default.iceberg_table"); - // this should probably fail but it does not now; testing current behavior as a documentation - onTrino().executeQuery("CREATE VIEW hive.default.hive_view_unqualified_iceberg AS SELECT * FROM iceberg_table"); + assertQueryFailure(() -> onTrino().executeQuery("CREATE VIEW hive.default.hive_view_unqualified_iceberg AS SELECT * FROM iceberg_table")) + .hasMessageMatching("Query failed \\(#\\w+\\):\\Q Cannot query Iceberg table 'default.iceberg_table'"); onTrino().executeQuery("USE iceberg.default"); // for sake of unqualified table references onTrino().executeQuery("CREATE VIEW iceberg.default.iceberg_view_qualified_hive AS SELECT * FROM hive.default.hive_table"); @@ -75,7 +76,6 @@ public void testIcebergHiveViewsCompatibility() .add(row("hive_view_qualified_hive")) .add(row("hive_view_unqualified_hive")) .add(row("hive_view_qualified_iceberg")) - .add(row("hive_view_unqualified_iceberg")) .add(row("iceberg_view_qualified_hive")) .add(row("iceberg_view_qualified_iceberg")) .add(row("iceberg_view_unqualified_iceberg")) @@ -88,7 +88,6 @@ public void testIcebergHiveViewsCompatibility() .add(row("hive_view_qualified_hive")) .add(row("hive_view_unqualified_hive")) .add(row("hive_view_qualified_iceberg")) - .add(row("hive_view_unqualified_iceberg")) .add(row("iceberg_view_qualified_hive")) .add(row("iceberg_view_qualified_iceberg")) .add(row("iceberg_view_unqualified_iceberg")) @@ -98,10 +97,6 @@ public void testIcebergHiveViewsCompatibility() assertThat(onTrino().executeQuery("SELECT * FROM hive.default.hive_view_qualified_hive")).containsOnly(row(1)); assertThat(onTrino().executeQuery("SELECT * FROM hive.default.hive_view_unqualified_hive")).containsOnly(row(1)); assertThat(onTrino().executeQuery("SELECT * FROM hive.default.hive_view_qualified_iceberg")).containsOnly(row(2)); - assertThatThrownBy(() -> onTrino().executeQuery("SELECT * FROM hive.default.hive_view_unqualified_iceberg")) - // hive connector tries to read from iceberg table - // TODO: make query fail with nicer message - .hasMessageContaining("Unable to create input format org.apache.hadoop.mapred.FileInputFormat"); assertThat(onTrino().executeQuery("SELECT * FROM hive.default.iceberg_view_qualified_hive")).containsOnly(row(1)); assertThat(onTrino().executeQuery("SELECT * FROM hive.default.iceberg_view_qualified_iceberg")).containsOnly(row(2)); assertThat(onTrino().executeQuery("SELECT * FROM hive.default.iceberg_view_unqualified_iceberg")).containsOnly(row(2)); @@ -110,10 +105,6 @@ public void testIcebergHiveViewsCompatibility() assertThat(onTrino().executeQuery("SELECT * FROM iceberg.default.hive_view_qualified_hive")).containsOnly(row(1)); assertThat(onTrino().executeQuery("SELECT * FROM iceberg.default.hive_view_unqualified_hive")).containsOnly(row(1)); assertThat(onTrino().executeQuery("SELECT * FROM iceberg.default.hive_view_qualified_iceberg")).containsOnly(row(2)); - assertThatThrownBy(() -> onTrino().executeQuery("SELECT * FROM iceberg.default.hive_view_unqualified_iceberg")) - // hive connector tries to read from iceberg table - // TODO: make query fail with nicer message - .hasMessageContaining("Unable to create input format org.apache.hadoop.mapred.FileInputFormat"); assertThat(onTrino().executeQuery("SELECT * FROM iceberg.default.iceberg_view_qualified_hive")).containsOnly(row(1)); assertThat(onTrino().executeQuery("SELECT * FROM iceberg.default.iceberg_view_qualified_iceberg")).containsOnly(row(2)); assertThat(onTrino().executeQuery("SELECT * FROM iceberg.default.iceberg_view_unqualified_iceberg")).containsOnly(row(2));