Repository: ClickHouse/ClickHouse
File: src/Storages/StorageMaterializedView.cpp (C++)

Code before:
        throw Exception(ErrorCodes::QUERY_IS_NOT_SUPPORTED_IN_MATERIALIZED_VIEW, "SQL SECURITY INVOKER can't be specified for MATERIALIZED VIEW");

    if (storage_metadata.sql_security_type == SQLSecurityType::DEFINER)
        ViewDefinerDependencies::instance().addViewDependency(*storage_metadata.definer, table_id_);

    if (!query.select)
        throw Exception(ErrorCodes::INCORRECT_QUERY, "SELECT query is not specified for {}", getName());

    /// If the destination table is not set, use inner table
    auto to_table_id = query.getTargetTableID(ViewTarget::To);
    has_inner_table = to_table_id.empty();
    auto to_inner_uuid = query.getTargetInnerUUID(ViewTarget::To);
    auto to_table_engine = query.getTargetInnerEngine(ViewTarget::To);

    if (has_inner_table && !to_table_engine)
        throw Exception(ErrorCodes::INCORRECT_QUERY,
                        "You must specify where to save results of a MaterializedView query: "
                        "either ENGINE or an existing table in a TO clause");

    if (to_table_engine && to_table_engine->primary_key)
        storage_metadata.primary_key = KeyDescription::getKeyFromAST(to_table_engine->primary_key->ptr(),
                                                                     storage_metadata.columns,
                                                                     local_context->getGlobalContext());
    /// Use the database where the materialized view is created to resolve nested views
    ContextMutablePtr mv_db_context = Context::createCopy(local_context);
    mv_db_context->setCurrentDatabase(table_id_.database_name);

    auto select = SelectQueryDescription::getSelectQueryFromASTForMatView(query.select->clone(), query.refresh_strategy != nullptr, mv_db_context);
    if (select.select_table_id)
    {
        auto select_table_dependent_views = DatabaseCatalog::instance().getDependentViews(select.select_table_id);

        auto max_materialized_views_count_for_table = getContext()->getServerSettings()[ServerSetting::max_materialized_views_count_for_table];
        if (max_materialized_views_count_for_table && select_table_dependent_views.size() >= max_materialized_views_count_for_table)
            throw Exception(ErrorCodes::TOO_MANY_MATERIALIZED_VIEWS,
                            "Too many materialized views, maximum: {}", max_materialized_views_count_for_table.value);
    }

    storage_metadata.setSelectQuery(select);
    if (!comment.empty())
        storage_metadata.setComment(comment);
    if (query.refresh_strategy)
        storage_metadata.setRefresh(query.refresh_strategy->clone());

    setInMemoryMetadata(storage_metadata);

    bool point_to_itself_by_uuid = has_inner_table && to_inner_uuid != UUIDHelpers::Nil
                                                   && to_inner_uuid == table_id_.uuid;
    bool point_to_itself_by_name = !has_inner_table && to_table_id.database_name == table_id_.database_name
                                                    && to_table_id.table_name == table_id_.table_name;
    if (point_to_itself_by_uuid || point_to_itself_by_name)

Review comment (refactor):
The pattern of creating a context copy and setting the current database is duplicated three times in this file (lines 146-147, 542-543, and 670-671). Consider extracting this into a helper method like `createMaterializedViewContext(const ContextPtr& context, const String& database_name)` to reduce duplication and ensure consistency.

Code after:
        throw Exception(ErrorCodes::QUERY_IS_NOT_SUPPORTED_IN_MATERIALIZED_VIEW, "SQL SECURITY INVOKER can't be specified for MATERIALIZED VIEW");

    if (storage_metadata.sql_security_type == SQLSecurityType::DEFINER)
        ViewDefinerDependencies::instance().addViewDependency(*storage_metadata.definer, table_id_);

    if (!query.select)
        throw Exception(ErrorCodes::INCORRECT_QUERY, "SELECT query is not specified for {}", getName());

    /// If the destination table is not set, use inner table
    auto to_table_id = query.getTargetTableID(ViewTarget::To);
    has_inner_table = to_table_id.empty();
    auto to_inner_uuid = query.getTargetInnerUUID(ViewTarget::To);
    auto * to_table_engine = query.getTargetInnerEngine(ViewTarget::To);

    if (has_inner_table && !to_table_engine)
        throw Exception(ErrorCodes::INCORRECT_QUERY,
                        "You must specify where to save results of a MaterializedView query: "
                        "either ENGINE or an existing table in a TO clause");

    if (to_table_engine && to_table_engine->primary_key)
        storage_metadata.primary_key = KeyDescription::getKeyFromAST(to_table_engine->primary_key->ptr(),
                                                                     storage_metadata.columns,
                                                                     local_context->getGlobalContext());
    /// Use the database where the materialized view is created to resolve nested views
    ContextMutablePtr mv_db_context = Context::createCopy(local_context);
    mv_db_context->setCurrentDatabase(table_id_.database_name);

    auto select = SelectQueryDescription::getSelectQueryFromASTForMatView(query.select->clone(), query.refresh_strategy != nullptr, mv_db_context);
    if (select.select_table_id)
    {
        auto select_table_dependent_views = DatabaseCatalog::instance().getDependentViews(select.select_table_id);

        auto max_materialized_views_count_for_table = getContext()->getServerSettings()[ServerSetting::max_materialized_views_count_for_table];
        if (max_materialized_views_count_for_table && select_table_dependent_views.size() >= max_materialized_views_count_for_table)
            throw Exception(ErrorCodes::TOO_MANY_MATERIALIZED_VIEWS,
                            "Too many materialized views, maximum: {}", max_materialized_views_count_for_table.value);
    }

    storage_metadata.setSelectQuery(select);
    if (!comment.empty())
        storage_metadata.setComment(comment);
    if (query.refresh_strategy)
        storage_metadata.setRefresh(query.refresh_strategy->clone());

    setInMemoryMetadata(storage_metadata);

    bool point_to_itself_by_uuid = has_inner_table && to_inner_uuid != UUIDHelpers::Nil
                                                   && to_inner_uuid == table_id_.uuid;
    bool point_to_itself_by_name = !has_inner_table && to_table_id.database_name == table_id_.database_name
                                                    && to_table_id.table_name == table_id_.table_name;
    if (point_to_itself_by_uuid || point_to_itself_by_name)