diff --git a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestTrinoDatabaseMetaData.java b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestTrinoDatabaseMetaData.java index 6994c5aa2e1b..1da1ce99930f 100644 --- a/client/trino-jdbc/src/test/java/io/trino/jdbc/TestTrinoDatabaseMetaData.java +++ b/client/trino-jdbc/src/test/java/io/trino/jdbc/TestTrinoDatabaseMetaData.java @@ -1339,7 +1339,7 @@ public void testGetColumnsMetadataCalls() .collect(toImmutableList()), new MetadataCallsCount() .withListSchemasCount(5) - .withListTablesCount(5) + .withListTablesCount(4) .withGetTableHandleCount(8) .withGetColumnsCount(2)); diff --git a/core/trino-main/src/main/java/io/trino/metadata/MetadataManager.java b/core/trino-main/src/main/java/io/trino/metadata/MetadataManager.java index 0bf47744f354..7e413f2685d5 100644 --- a/core/trino-main/src/main/java/io/trino/metadata/MetadataManager.java +++ b/core/trino-main/src/main/java/io/trino/metadata/MetadataManager.java @@ -250,6 +250,7 @@ public List listSchemaNames(Session session, String catalogName) ConnectorMetadata metadata = catalogMetadata.getMetadataFor(session, catalogHandle); metadata.listSchemaNames(connectorSession).stream() .map(schema -> schema.toLowerCase(Locale.ENGLISH)) + .filter(schema -> !isExternalInformationSchema(catalogHandle, schema)) .forEach(schemaNames::add); } } @@ -508,8 +509,12 @@ public List listTables(Session session, QualifiedTablePrefi for (CatalogHandle catalogHandle : catalogMetadata.listCatalogHandles()) { ConnectorMetadata metadata = catalogMetadata.getMetadataFor(session, catalogHandle); ConnectorSession connectorSession = session.toConnectorSession(catalogHandle); + if (isExternalInformationSchema(catalogHandle, prefix.getSchemaName())) { + continue; + } metadata.listTables(connectorSession, prefix.getSchemaName()).stream() .map(convertFromSchemaTableName(prefix.getCatalogName())) + .filter(table -> !isExternalInformationSchema(catalogHandle, table.getSchemaName())) .filter(prefix::matches) .forEach(tables::add); } @@ -554,13 +559,21 @@ public List listTableColumns(Session session, QualifiedTab SchemaTablePrefix tablePrefix = prefix.asSchemaTablePrefix(); for (CatalogHandle catalogHandle : catalogMetadata.listCatalogHandles()) { + if (isExternalInformationSchema(catalogHandle, prefix.getSchemaName())) { + continue; + } + ConnectorMetadata metadata = catalogMetadata.getMetadataFor(session, catalogHandle); ConnectorSession connectorSession = session.toConnectorSession(catalogHandle); // Collect column metadata from tables metadata.streamTableColumns(connectorSession, tablePrefix) - .forEachRemaining(columnsMetadata -> tableColumns.put(columnsMetadata.getTable(), columnsMetadata.getColumns())); + .forEachRemaining(columnsMetadata -> { + if (!isExternalInformationSchema(catalogHandle, columnsMetadata.getTable().getSchemaName())) { + tableColumns.put(columnsMetadata.getTable(), columnsMetadata.getColumns()); + } + }); // Collect column metadata from views. if table and view names overlap, the view wins for (Entry entry : getViews(session, prefix).entrySet()) { @@ -1076,10 +1089,14 @@ public List listViews(Session session, QualifiedTablePrefix CatalogMetadata catalogMetadata = catalog.get(); for (CatalogHandle catalogHandle : catalogMetadata.listCatalogHandles()) { + if (isExternalInformationSchema(catalogHandle, prefix.getSchemaName())) { + continue; + } ConnectorMetadata metadata = catalogMetadata.getMetadataFor(session, catalogHandle); ConnectorSession connectorSession = session.toConnectorSession(catalogHandle); metadata.listViews(connectorSession, prefix.getSchemaName()).stream() .map(convertFromSchemaTableName(prefix.getCatalogName())) + .filter(view -> !isExternalInformationSchema(catalogHandle, view.getSchemaName())) .filter(prefix::matches) .forEach(views::add); } @@ -1100,6 +1117,10 @@ public Map getViews(Session session, QualifiedTab SchemaTablePrefix tablePrefix = prefix.asSchemaTablePrefix(); for (CatalogHandle catalogHandle : catalogMetadata.listCatalogHandles()) { + if (isExternalInformationSchema(catalogHandle, tablePrefix.getSchema())) { + continue; + } + ConnectorMetadata metadata = catalogMetadata.getMetadataFor(session, catalogHandle); ConnectorSession connectorSession = session.toConnectorSession(catalogHandle); @@ -1114,6 +1135,9 @@ public Map getViews(Session session, QualifiedTab } for (Entry entry : viewMap.entrySet()) { + if (isExternalInformationSchema(catalogHandle, entry.getKey().getSchemaName())) { + continue; + } QualifiedObjectName viewName = new QualifiedObjectName( prefix.getCatalogName(), entry.getKey().getSchemaName(), @@ -1299,10 +1323,14 @@ public List listMaterializedViews(Session session, Qualifie CatalogMetadata catalogMetadata = catalog.get(); for (CatalogHandle catalogHandle : catalogMetadata.listCatalogHandles()) { + if (isExternalInformationSchema(catalogHandle, prefix.getSchemaName())) { + continue; + } ConnectorMetadata metadata = catalogMetadata.getMetadataFor(session, catalogHandle); ConnectorSession connectorSession = session.toConnectorSession(catalogHandle); metadata.listMaterializedViews(connectorSession, prefix.getSchemaName()).stream() .map(convertFromSchemaTableName(prefix.getCatalogName())) + .filter(materializedView -> !isExternalInformationSchema(catalogHandle, materializedView.getSchemaName())) .filter(prefix::matches) .forEach(materializedViews::add); } @@ -1323,6 +1351,9 @@ public Map getMaterializedViews(Session session, SchemaTablePrefix tablePrefix = prefix.asSchemaTablePrefix(); for (CatalogHandle catalogHandle : catalogMetadata.listCatalogHandles()) { + if (isExternalInformationSchema(catalogHandle, tablePrefix.getSchema())) { + continue; + } ConnectorMetadata metadata = catalogMetadata.getMetadataFor(session, catalogHandle); ConnectorSession connectorSession = session.toConnectorSession(catalogHandle); @@ -1337,6 +1368,9 @@ public Map getMaterializedViews(Session session, } for (Entry entry : materializedViewMap.entrySet()) { + if (isExternalInformationSchema(catalogHandle, entry.getKey().getSchemaName())) { + continue; + } QualifiedObjectName viewName = new QualifiedObjectName( prefix.getCatalogName(), entry.getKey().getSchemaName(), @@ -1431,6 +1465,16 @@ public void setMaterializedViewProperties(Session session, QualifiedObjectName v metadata.setMaterializedViewProperties(session.toConnectorSession(catalogHandle), viewName.asSchemaTableName(), properties); } + private static boolean isExternalInformationSchema(CatalogHandle catalogHandle, Optional schemaName) + { + return schemaName.isPresent() && isExternalInformationSchema(catalogHandle, schemaName.get()); + } + + private static boolean isExternalInformationSchema(CatalogHandle catalogHandle, String schemaName) + { + return !catalogHandle.getType().isInternal() && "information_schema".equalsIgnoreCase(schemaName); + } + @Override public Optional applyTableScanRedirect(Session session, TableHandle tableHandle) { 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 5d83acc082de..78250e3cf15a 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 @@ -121,7 +121,6 @@ public class BigQueryMetadata static final int DEFAULT_NUMERIC_TYPE_PRECISION = 38; static final int DEFAULT_NUMERIC_TYPE_SCALE = 9; - static final String INFORMATION_SCHEMA = "information_schema"; private static final String VIEW_DEFINITION_SYSTEM_TABLE_SUFFIX = "$view_definition"; private final BigQueryClientFactory bigQueryClientFactory; @@ -149,7 +148,6 @@ private List listRemoteSchemaNames(ConnectorSession session) Stream remoteSchemaNames = Streams.stream(client.listDatasets(projectId)) .map(dataset -> dataset.getDatasetId().getDataset()) - .filter(schemaName -> !schemaName.equalsIgnoreCase(INFORMATION_SCHEMA)) .distinct(); // filter out all the ambiguous schemas to prevent failures if anyone tries to access the listed schemas @@ -182,19 +180,12 @@ public List listTables(ConnectorSession session, Optional remoteSchema = schemaName.flatMap(schema -> client.toRemoteDataset(projectId, schema) .filter(dataset -> !dataset.isAmbiguous()) .map(RemoteDatabaseObject::getOnlyRemoteName)); - if (remoteSchema.isPresent() && remoteSchema.get().equalsIgnoreCase(INFORMATION_SCHEMA)) { - return ImmutableList.of(); - } Set remoteSchemaNames = remoteSchema.map(ImmutableSet::of) .orElseGet(() -> ImmutableSet.copyOf(listRemoteSchemaNames(session))); 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 07fcdfc81aff..1bac6824ca04 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 @@ -248,10 +248,8 @@ import static io.trino.spi.type.VarcharType.VARCHAR; import static java.lang.String.format; import static java.time.Instant.EPOCH; -import static java.util.Collections.emptyIterator; import static java.util.Collections.singletonList; import static java.util.Collections.unmodifiableMap; -import static java.util.Locale.ENGLISH; import static java.util.Objects.requireNonNull; import static java.util.UUID.randomUUID; import static java.util.function.Function.identity; @@ -360,10 +358,7 @@ public DeltaLakeMetadata( public List listSchemaNames(ConnectorSession session) { return metastore.getAllDatabases().stream() - .filter(schema -> { - String schemaName = schema.toLowerCase(ENGLISH); - return !(schemaName.equals("information_schema") || schemaName.equals("sys")); - }) + .filter(schema -> !schema.equalsIgnoreCase("sys")) .collect(toImmutableList()); } @@ -485,10 +480,6 @@ public ConnectorTableMetadata getTableMetadata(ConnectorSession session, Connect @Override public List listTables(ConnectorSession session, Optional schemaName) { - if (schemaName.isPresent() && schemaName.get().equals("information_schema")) { - // TODO https://github.com/trinodb/trino/issues/1559 information_schema should be handled by the engine fully - return ImmutableList.of(); - } return schemaName.map(Collections::singletonList) .orElseGet(() -> listSchemaNames(session)) .stream() @@ -556,11 +547,6 @@ public Map> listTableColumns(ConnectorSess @Override public Iterator streamTableColumns(ConnectorSession session, SchemaTablePrefix prefix) { - if (prefix.getSchema().isPresent() && prefix.getSchema().get().equals("information_schema")) { - // TODO https://github.com/trinodb/trino/issues/1559 information_schema should be handled by the engine fully - return emptyIterator(); - } - List tables = prefix.getTable() .map(ignored -> singletonList(prefix.toSchemaTableName())) .orElseGet(() -> listTables(session, prefix.getSchema())); 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 f7fddc7caf41..f0d61d59c141 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 @@ -1099,8 +1099,7 @@ public static String sortingColumnToString(SortingColumn column) public static boolean isHiveSystemSchema(String schemaName) { if ("information_schema".equals(schemaName)) { - // For things like listing columns in information_schema.columns table, we need to explicitly filter out Hive's own information_schema. - // TODO https://github.com/trinodb/trino/issues/1559 this should be filtered out in engine. + // `information_schema` is filtered within engine. This condition exists for internal handling in Hive connector. return true; } if ("sys".equals(schemaName)) { diff --git a/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/catalog/glue/TrinoGlueCatalog.java b/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/catalog/glue/TrinoGlueCatalog.java index ac2b52663b4c..55a9039d816d 100644 --- a/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/catalog/glue/TrinoGlueCatalog.java +++ b/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/catalog/glue/TrinoGlueCatalog.java @@ -199,10 +199,6 @@ public List listNamespaces(ConnectorSession session) private List listNamespaces(ConnectorSession session, Optional namespace) { if (namespace.isPresent()) { - if (isHiveSystemSchema(namespace.get())) { - // TODO https://github.com/trinodb/trino/issues/1559 information_schema should be handled by the engine fully - return ImmutableList.of(); - } return ImmutableList.of(namespace.get()); } return listNamespaces(session); diff --git a/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/catalog/hms/TrinoHiveCatalog.java b/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/catalog/hms/TrinoHiveCatalog.java index c4f56efe1c0f..d7795ced95fe 100644 --- a/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/catalog/hms/TrinoHiveCatalog.java +++ b/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/catalog/hms/TrinoHiveCatalog.java @@ -605,7 +605,6 @@ private List listNamespaces(ConnectorSession session, Optional n { if (namespace.isPresent()) { if (isHiveSystemSchema(namespace.get())) { - // TODO https://github.com/trinodb/trino/issues/1559 information_schema should be handled by the engine fully return ImmutableList.of(); } return ImmutableList.of(namespace.get()); diff --git a/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/catalog/jdbc/TrinoJdbcCatalog.java b/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/catalog/jdbc/TrinoJdbcCatalog.java index 648de291c61d..d61c26a8c8c3 100644 --- a/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/catalog/jdbc/TrinoJdbcCatalog.java +++ b/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/catalog/jdbc/TrinoJdbcCatalog.java @@ -163,10 +163,6 @@ public List listTables(ConnectorSession session, Optional listNamespaces(ConnectorSession session, Optional namespace) { if (namespace.isPresent() && namespaceExists(session, namespace.get())) { - if ("information_schema".equals(namespace.get())) { - // TODO https://github.com/trinodb/trino/issues/1559 this should be filtered out in engine. - return ImmutableList.of(); - } return ImmutableList.of(namespace.get()); } return listNamespaces(session); 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 e76ca3763a5a..49528ff44bbc 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 @@ -176,14 +176,9 @@ protected MockConnectorPlugin buildMockConnectorPlugin() { MockConnectorFactory connectorFactory = MockConnectorFactory.builder() .withListSchemaNames(session -> ImmutableList.copyOf(mockTableListings.keySet())) - .withListTables((session, schemaName) -> { - if (schemaName.equals("information_schema")) { - // TODO (https://github.com/trinodb/trino/issues/1559) connector should not be asked about information_schema - return List.of(); - } - return verifyNotNull(mockTableListings.get(schemaName), "No listing function registered for [%s]", schemaName) - .apply(session); - }) + .withListTables((session, schemaName) -> + verifyNotNull(mockTableListings.get(schemaName), "No listing function registered for [%s]", schemaName) + .apply(session)) .build(); return new MockConnectorPlugin(connectorFactory); } diff --git a/testing/trino-tests/src/test/java/io/trino/tests/TestInformationSchemaConnector.java b/testing/trino-tests/src/test/java/io/trino/tests/TestInformationSchemaConnector.java index 00a96b4bdd20..4672fa027add 100644 --- a/testing/trino-tests/src/test/java/io/trino/tests/TestInformationSchemaConnector.java +++ b/testing/trino-tests/src/test/java/io/trino/tests/TestInformationSchemaConnector.java @@ -153,7 +153,7 @@ public void testMetadataCalls() "VALUES 2", new MetadataCallsCount() .withListSchemasCount(1) - .withListTablesCount(3)); + .withListTablesCount(2)); assertMetadataCalls( "SELECT count(*) from test_catalog.information_schema.tables WHERE table_name LIKE 'test_t_ble1' AND table_name IN ('test_table1', 'test_table2')", "VALUES 2", @@ -188,14 +188,13 @@ public void testMetadataCalls() "VALUES 1", new MetadataCallsCount() .withListSchemasCount(1) - .withListTablesCount(1) .withGetColumnsCount(0)); assertMetadataCalls( "SELECT count(*) FROM (SELECT * from test_catalog.information_schema.columns LIMIT 1000)", "VALUES 1000", new MetadataCallsCount() .withListSchemasCount(1) - .withListTablesCount(2) + .withListTablesCount(1) .withGetColumnsCount(1000)); // Empty table schema and table name