diff --git a/core/trino-main/src/main/java/io/trino/sql/rewrite/ShowQueriesRewrite.java b/core/trino-main/src/main/java/io/trino/sql/rewrite/ShowQueriesRewrite.java index b5c856335956c..2a27e9ddf9564 100644 --- a/core/trino-main/src/main/java/io/trino/sql/rewrite/ShowQueriesRewrite.java +++ b/core/trino-main/src/main/java/io/trino/sql/rewrite/ShowQueriesRewrite.java @@ -397,6 +397,10 @@ protected Node visitShowSchemas(ShowSchemas node, Void context) } String catalog = node.getCatalog().map(Identifier::getValue).orElseGet(() -> session.getCatalog().orElseThrow()); + if (!metadata.catalogExists(session, catalog)) { + throw semanticException(CATALOG_NOT_FOUND, node, "Catalog '%s' does not exist", catalog); + } + accessControl.checkCanShowSchemas(session.toSecurityContext(), catalog); Optional predicate = Optional.empty(); @@ -525,6 +529,8 @@ protected Node visitShowCreate(ShowCreate node, Void context) private Query showCreateMaterializedView(ShowCreate node) { QualifiedObjectName objectName = createQualifiedObjectName(session, node, node.getName()); + verifySchemaCatalogExists(node, objectName); + Optional viewDefinition = metadata.getMaterializedView(session, objectName); if (viewDefinition.isEmpty()) { @@ -567,6 +573,7 @@ private Query showCreateMaterializedView(ShowCreate node) private Query showCreateView(ShowCreate node) { QualifiedObjectName objectName = createQualifiedObjectName(session, node, node.getName()); + verifySchemaCatalogExists(node, objectName); if (metadata.isMaterializedView(session, objectName)) { throw semanticException(NOT_SUPPORTED, node, "Relation '%s' is a materialized view, not a view", objectName); @@ -605,9 +612,22 @@ private Query showCreateView(ShowCreate node) return singleValueQuery("Create View", sql); } + private void verifySchemaCatalogExists(Node node, QualifiedObjectName objectName) + { + if (!metadata.catalogExists(session, objectName.catalogName())) { + throw semanticException(CATALOG_NOT_FOUND, node, "Catalog '%s' does not exist", objectName.catalogName()); + } + + CatalogSchemaName catalogSchemaName = new CatalogSchemaName(objectName.catalogName(), objectName.schemaName()); + if (!metadata.schemaExists(session, catalogSchemaName)) { + throw semanticException(SCHEMA_NOT_FOUND, node, "Schema '%s' does not exist", catalogSchemaName); + } + } + private Query showCreateTable(ShowCreate node) { QualifiedObjectName objectName = createQualifiedObjectName(session, node, node.getName()); + verifySchemaCatalogExists(node, objectName); if (metadata.isMaterializedView(session, objectName)) { throw semanticException(NOT_SUPPORTED, node, "Relation '%s' is a materialized view, not a table", objectName); @@ -686,6 +706,7 @@ private Query showCreateSchema(ShowCreate node) private Node showCreateFunction(ShowCreate node) { QualifiedObjectName functionName = qualifiedFunctionName(functionSchema, node, node.getName()); + verifySchemaCatalogExists(node, functionName); accessControl.checkCanShowCreateFunction(session.toSecurityContext(), functionName); diff --git a/core/trino-main/src/test/java/io/trino/sql/query/TestShowQueries.java b/core/trino-main/src/test/java/io/trino/sql/query/TestShowQueries.java index 21b0dc94508e6..258d41b1694c1 100644 --- a/core/trino-main/src/test/java/io/trino/sql/query/TestShowQueries.java +++ b/core/trino-main/src/test/java/io/trino/sql/query/TestShowQueries.java @@ -31,6 +31,9 @@ import java.util.Optional; +import static io.trino.spi.StandardErrorCode.CATALOG_NOT_FOUND; +import static io.trino.spi.StandardErrorCode.SCHEMA_NOT_FOUND; +import static io.trino.spi.StandardErrorCode.TABLE_NOT_FOUND; import static io.trino.spi.type.BigintType.BIGINT; import static io.trino.testing.TestingSession.testSessionBuilder; import static org.assertj.core.api.Assertions.assertThat; @@ -66,6 +69,9 @@ public TestShowQueries() .withListSchemaNames(session -> ImmutableList.of("mockschema")) .withListTables((session, schemaName) -> ImmutableList.of("mockTable")) .withGetTableHandle((session, schemaTableName) -> { + if (schemaTableName.getTableName().equals("nonexistingtable")) { + return null; + } if (schemaTableName.getTableName().equals("mockview")) { return null; } @@ -205,6 +211,32 @@ public void testShowColumnsWithLikeWithEscape() .matches("VALUES (VARCHAR 'cola_', VARCHAR 'bigint' , VARCHAR '', VARCHAR '')"); } + @Test + public void testNonExistingRelations() + { + testNonExistingRelations("TABLE", "Table"); + testNonExistingRelations("VIEW", "View"); + testNonExistingRelations("MATERIALIZED VIEW", "Materialized view"); + } + + private void testNonExistingRelations(String relationType, String relationName) + { + assertThat(assertions.query("SHOW CREATE " + relationType + " missing.mockSchema.nonExistingTable")) + .failure() + .hasErrorCode(CATALOG_NOT_FOUND) + .hasMessage("line 1:1: Catalog 'missing' does not exist"); + + assertThat(assertions.query("SHOW CREATE " + relationType + " mock.missingschema.nonExistingTable")) + .failure() + .hasErrorCode(SCHEMA_NOT_FOUND) + .hasMessage("line 1:1: Schema 'mock.missingschema' does not exist"); + + assertThat(assertions.query("SHOW CREATE " + relationType + " mock.mockSchema.nonExistingTable")) + .failure() + .hasErrorCode(TABLE_NOT_FOUND) + .hasMessage("line 1:1: " + relationName + " 'mock.mockschema.nonexistingtable' does not exist"); + } + @Test public void testShowCreateViewWithProperties() { diff --git a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/BaseHiveConnectorTest.java b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/BaseHiveConnectorTest.java index c3f44cd4ae147..41acc43ac2eda 100644 --- a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/BaseHiveConnectorTest.java +++ b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/BaseHiveConnectorTest.java @@ -243,6 +243,9 @@ protected static QueryRunner createHiveQueryRunner(HiveQueryRunner.Builder bu "hive_timestamp_nanos", "hive", ImmutableMap.of("hive.timestamp-precision", "NANOSECONDS")); + + queryRunner.execute("CREATE SCHEMA hive.functions"); + return queryRunner; } 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 bea34b658d7f8..4ea7441c962cc 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 @@ -55,7 +55,7 @@ public class TestMemoryConnectorTest protected QueryRunner createQueryRunner() throws Exception { - return MemoryQueryRunner.builder() + QueryRunner runner = MemoryQueryRunner.builder() .addExtraProperties(ImmutableMap.builder() // Adjust DF limits to test edge cases .put("dynamic-filtering.small.max-distinct-values-per-driver", "100") @@ -80,6 +80,9 @@ protected QueryRunner createQueryRunner() .add(TpchTable.LINE_ITEM) .build()) .build(); + + runner.execute("CREATE SCHEMA memory.functions"); + return runner; } @Override