From 4b7a7e00f8e8420016ad63b6b5f19faa3602b748 Mon Sep 17 00:00:00 2001 From: "Mateusz \"Serafin\" Gajewski" Date: Fri, 30 Aug 2024 16:10:55 +0200 Subject: [PATCH] Throw CATALOG/SCHEMA_NOT_FOUND for missing SHOW CREATE relations --- .../trino/sql/rewrite/ShowQueriesRewrite.java | 21 ++++++++++++ .../io/trino/sql/query/TestShowQueries.java | 32 +++++++++++++++++++ 2 files changed, 53 insertions(+) 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() {