From 1c5e5eb0d3949ff5d6f6bfd42a72428b4a2d5668 Mon Sep 17 00:00:00 2001 From: Piotr Findeisen Date: Wed, 29 Nov 2023 10:08:42 +0100 Subject: [PATCH] Allow differentiating materialized views from tables efficiently Tools often need to list tables/relations and know whether they are regular tables, views, or materialized views. For example, on a table one can `SHOW CREATE TABLE` or `DROP TABLE`, but syntax for views and materialized views is different. Before this change, to differentiate different relations types, tools need to join `information_schema.tables` with `system.metadata.materialized_views`. This is effective, but not efficient: `system.metadata.materialized_views` contains much more information. To address the inefficiency, this commit introduces a new column to `information_schema.tables`. To guarantee SQL spec future-compatibility, the column is hidden and prefixed with `trino_` --- .../InformationSchemaPageSource.java | 31 ++++++++++++------- .../InformationSchemaTable.java | 1 + .../io/trino/testing/BaseConnectorTest.java | 8 ++--- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/core/trino-main/src/main/java/io/trino/connector/informationschema/InformationSchemaPageSource.java b/core/trino-main/src/main/java/io/trino/connector/informationschema/InformationSchemaPageSource.java index 143cc6493c63..b7a7f6ee4186 100644 --- a/core/trino-main/src/main/java/io/trino/connector/informationschema/InformationSchemaPageSource.java +++ b/core/trino-main/src/main/java/io/trino/connector/informationschema/InformationSchemaPageSource.java @@ -277,34 +277,43 @@ private void addColumnsRecords(QualifiedTablePrefix prefix) private void addTablesRecords(QualifiedTablePrefix prefix) { - boolean needsTableType = requiredColumns.contains("table_type"); + boolean needsTableType = requiredColumns.contains("table_type") || requiredColumns.contains("trino_relation_type"); Set relations; - Set views; + Map relationTypes; if (needsTableType) { - Map relationTypes = getRelationTypes(session, metadata, accessControl, prefix); + relationTypes = getRelationTypes(session, metadata, accessControl, prefix); relations = relationTypes.keySet(); - views = relationTypes.entrySet().stream() - .filter(entry -> entry.getValue() == RelationType.VIEW) - .map(Entry::getKey) - .collect(toImmutableSet()); } else { relations = listTables(session, metadata, accessControl, prefix); - views = Set.of(); + relationTypes = null; } - // TODO (https://github.com/trinodb/trino/issues/8207) define a type for materialized views for (SchemaTableName name : relations) { String type = null; + String trinoRelationType = null; if (needsTableType) { - // if table and view names overlap, the view wins - type = views.contains(name) ? "VIEW" : "BASE TABLE"; + switch (relationTypes.get(name)) { + case TABLE -> { + type = "BASE TABLE"; + trinoRelationType = type; + } + case VIEW -> { + type = "VIEW"; + trinoRelationType = type; + } + case MATERIALIZED_VIEW -> { + type = "BASE TABLE"; + trinoRelationType = "MATERIALIZED VIEW"; + } + } } addRecord( prefix.getCatalogName(), name.getSchemaName(), name.getTableName(), type, + trinoRelationType, null); if (isLimitExhausted()) { return; diff --git a/core/trino-main/src/main/java/io/trino/connector/informationschema/InformationSchemaTable.java b/core/trino-main/src/main/java/io/trino/connector/informationschema/InformationSchemaTable.java index 605076aa3841..e45bb8594d74 100644 --- a/core/trino-main/src/main/java/io/trino/connector/informationschema/InformationSchemaTable.java +++ b/core/trino-main/src/main/java/io/trino/connector/informationschema/InformationSchemaTable.java @@ -47,6 +47,7 @@ public enum InformationSchemaTable .column("table_schema", createUnboundedVarcharType()) .column("table_name", createUnboundedVarcharType()) .column("table_type", createUnboundedVarcharType()) + .hiddenColumn("trino_relation_type", createUnboundedVarcharType()) .hiddenColumn("table_comment", createUnboundedVarcharType()) // MySQL compatible .build()), VIEWS(table("views") 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 dd00a554460a..214130af3770 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 @@ -1052,15 +1052,15 @@ public void testMaterializedView() .containsAll("VALUES '" + view.getObjectName() + "'"); // information_schema.tables without table_name filter so that ConnectorMetadata.listViews is exercised assertThat(query( - "SELECT table_name, table_type FROM information_schema.tables " + + "SELECT table_name, table_type, trino_relation_type FROM information_schema.tables " + "WHERE table_schema = '" + view.getSchemaName() + "'")) .skippingTypesCheck() - .containsAll("VALUES ('" + view.getObjectName() + "', 'BASE TABLE')"); + .containsAll("VALUES ('" + view.getObjectName() + "', 'BASE TABLE', 'MATERIALIZED VIEW')"); // information_schema.tables with table_name filter assertQuery( - "SELECT table_name, table_type FROM information_schema.tables " + + "SELECT table_name, table_type, trino_relation_type FROM information_schema.tables " + "WHERE table_schema = '" + view.getSchemaName() + "' and table_name = '" + view.getObjectName() + "'", - "VALUES ('" + view.getObjectName() + "', 'BASE TABLE')"); + "VALUES ('" + view.getObjectName() + "', 'BASE TABLE', 'MATERIALIZED VIEW')"); // system.jdbc.tables without filter assertThat(query("SELECT table_schem, table_name, table_type FROM system.jdbc.tables"))