diff --git a/src/Interpreters/Cache/QueryCache.cpp b/src/Interpreters/Cache/QueryCache.cpp index 8a76378f14c..67fcdb8159c 100644 --- a/src/Interpreters/Cache/QueryCache.cpp +++ b/src/Interpreters/Cache/QueryCache.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -14,6 +15,7 @@ #include #include #include +#include #include #include /// chassert @@ -69,20 +71,31 @@ struct HasSystemTablesMatcher if (data.has_system_tables) return; - if (const auto * identifier = node->as()) + String database_table; /// or whatever else we get, e.g. just a table + + /// SELECT [...] FROM + if (const auto * table_identifier = node->as()) { - StorageID storage_id = identifier->getTableId(); - if (!storage_id.hasDatabase()) - /// The common case that a database name was not explicitly specified in the SQL. However, isPredefinedTable() is AST-based - /// and assumes that a database name was specified. This bites us in this edge situation: - /// USE SYSTEM; - /// SELECT * FROM PROCESSES; -- instead of SYSTEM.PROCESSES - /// In this case, don't call isPredefinedTable() (to avoid exceptions) and accept that the behavior is not 100% kosher. - return; - bool is_predefined_table = DatabaseCatalog::instance().isPredefinedTable(storage_id); - if (is_predefined_table) - data.has_system_tables = true; + database_table = table_identifier->name(); } + /// SELECT [...] FROM clusterAllReplicas(,
) + else if (const auto * identifier = node->as()) + { + database_table = identifier->name(); + } + /// Handle SELECT [...] FROM clusterAllReplicas(, '
') + else if (const auto * literal = node->as()) + { + const auto & value = literal->value; /// (*) + database_table = applyVisitor(FieldVisitorDump(), value); + } + + /// (*) returns table in quotes, so we can't use .starts_with() for matching + static const re2::RE2 is_system_table(String(DatabaseCatalog::TEMPORARY_DATABASE) + + "|" + DatabaseCatalog::SYSTEM_DATABASE + + "|" + DatabaseCatalog::INFORMATION_SCHEMA + + "|" + DatabaseCatalog::INFORMATION_SCHEMA_UPPERCASE); + data.has_system_tables = re2::RE2::PartialMatch(database_table, is_system_table); } }; diff --git a/tests/queries/0_stateless/02494_query_cache_system_tables.sql b/tests/queries/0_stateless/02494_query_cache_system_tables.sql index 89ea9d2b6b7..935011a6bb0 100644 --- a/tests/queries/0_stateless/02494_query_cache_system_tables.sql +++ b/tests/queries/0_stateless/02494_query_cache_system_tables.sql @@ -44,5 +44,8 @@ SELECT * SETTINGS use_query_cache = 1; SELECT * FROM information_schema.tables SETTINGS use_query_cache = 1; -- { serverError QUERY_CACHE_USED_WITH_SYSTEM_TABLE } SELECT * FROM INFORMATION_SCHEMA.TABLES SETTINGS use_query_cache = 1; -- { serverError QUERY_CACHE_USED_WITH_SYSTEM_TABLE } +SELECT * FROM clusterAllReplicas('test_shard_localhost', system.one) SETTINGS use_query_cache = 1; -- {serverError QUERY_CACHE_USED_WITH_SYSTEM_TABLE } +SELECT * FROM clusterAllReplicas('test_shard_localhost', 'system.one') SETTINGS use_query_cache = 1; -- {serverError QUERY_CACHE_USED_WITH_SYSTEM_TABLE } + -- Cleanup SYSTEM DROP QUERY CACHE;