#include #include #include #include #include #include #include namespace DB { namespace ErrorCodes { extern const int QUERY_IS_NOT_SUPPORTED_IN_MATERIALIZED_VIEW; } SelectQueryDescription::SelectQueryDescription(const SelectQueryDescription & other) : select_table_id(other.select_table_id) , select_query(other.select_query ? other.select_query->clone() : nullptr) , inner_query(other.inner_query ? other.inner_query->clone() : nullptr) { } SelectQueryDescription & SelectQueryDescription::SelectQueryDescription::operator=(const SelectQueryDescription & other) { if (&other == this) return *this; select_table_id = other.select_table_id; if (other.select_query) select_query = other.select_query->clone(); else select_query.reset(); if (other.inner_query) inner_query = other.inner_query->clone(); else inner_query.reset(); return *this; } namespace { StorageID extractDependentTableFromSelectQuery(ASTSelectQuery & query, ContextPtr context, bool add_default_db = true) { if (add_default_db) { AddDefaultDatabaseVisitor visitor(context, context->getCurrentDatabase()); visitor.visit(query); } if (auto db_and_table = getDatabaseAndTable(query, 0)) { return StorageID(db_and_table->database, db_and_table->table/*, db_and_table->uuid*/); } else if (auto subquery = extractTableExpression(query, 0)) { auto * ast_select = subquery->as(); if (!ast_select) throw Exception(ErrorCodes::QUERY_IS_NOT_SUPPORTED_IN_MATERIALIZED_VIEW, "StorageMaterializedView cannot be created from table functions ({})", serializeAST(*subquery)); if (ast_select->list_of_selects->children.size() != 1) throw Exception("UNION is not supported for MATERIALIZED VIEW", ErrorCodes::QUERY_IS_NOT_SUPPORTED_IN_MATERIALIZED_VIEW); auto & inner_query = ast_select->list_of_selects->children.at(0); return extractDependentTableFromSelectQuery(inner_query->as(), context, false); } else return StorageID::createEmpty(); } void checkAllowedQueries(const ASTSelectQuery & query) { if (query.prewhere() || query.final() || query.sampleSize()) throw Exception("MATERIALIZED VIEW cannot have PREWHERE, SAMPLE or FINAL.", DB::ErrorCodes::QUERY_IS_NOT_SUPPORTED_IN_MATERIALIZED_VIEW); ASTPtr subquery = extractTableExpression(query, 0); if (!subquery) return; if (const auto * ast_select = subquery->as()) { if (ast_select->list_of_selects->children.size() != 1) throw Exception("UNION is not supported for MATERIALIZED VIEW", ErrorCodes::QUERY_IS_NOT_SUPPORTED_IN_MATERIALIZED_VIEW); const auto & inner_query = ast_select->list_of_selects->children.at(0); checkAllowedQueries(inner_query->as()); } } } /// check if only one single select query in SelectWithUnionQuery static bool isSingleSelect(const ASTPtr & select, ASTPtr & res) { auto new_select = select->as(); if (new_select.list_of_selects->children.size() != 1) return false; auto & new_inner_query = new_select.list_of_selects->children.at(0); if (new_inner_query->as()) { res = new_inner_query; return true; } else return isSingleSelect(new_inner_query, res); } SelectQueryDescription SelectQueryDescription::getSelectQueryFromASTForMatView(const ASTPtr & select, ContextPtr context) { ASTPtr new_inner_query; if (!isSingleSelect(select, new_inner_query)) throw Exception("UNION is not supported for MATERIALIZED VIEW", ErrorCodes::QUERY_IS_NOT_SUPPORTED_IN_MATERIALIZED_VIEW); auto & select_query = new_inner_query->as(); checkAllowedQueries(select_query); SelectQueryDescription result; result.select_table_id = extractDependentTableFromSelectQuery(select_query, context); result.select_query = select->as().clone(); result.inner_query = new_inner_query->clone(); return result; } }