MCPcopy Create free account
hub / github.com/ClickHouse/ClickHouse / addBuildSubqueriesForSetsStepIfNeeded

Function addBuildSubqueriesForSetsStepIfNeeded

src/Planner/Planner.cpp:1597–1662  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1595}
1596
1597void addBuildSubqueriesForSetsStepIfNeeded(
1598 QueryPlan & query_plan,
1599 const SelectQueryOptions & select_query_options,
1600 const PlannerContextPtr & planner_context,
1601 const UsefulSets & useful_sets)
1602{
1603 auto subqueries = planner_context->getPreparedSets().getSubqueries();
1604
1605 auto predicate = [&useful_sets](const auto & set) { return !useful_sets.contains(set); };
1606 auto it = std::remove_if(subqueries.begin(), subqueries.end(), std::move(predicate));
1607 subqueries.erase(it, subqueries.end());
1608
1609 for (auto & subquery : subqueries)
1610 {
1611 auto query_tree = subquery->detachQueryTree();
1612 auto subquery_options = select_query_options.subquery();
1613 /// Sets may use Materialized CTEs, so we need to materialize them in order to correctly build set from subquery.
1614 /// Normally CTEs are materialized before building sets and running the main query, but in case when
1615 /// set is built for primary key analysis, CTEs are not materialized yet.
1616 ///
1617 /// To build the set correctly, we need to add a DelayedMaterializingCTEsStep for CTEs in the set subquery plan.
1618 /// This is done by forceMaterializeCTE() method, which would lead collectMaterializedCTEs() to return non-empty result.
1619 ///
1620 /// As a result:
1621 /// 1. If set is built during primary key analysis FutureSetFromSubquery::buildSetInplace(), we will build plans for used CTEs materialization.
1622 /// Later, when the main query plan is optimized, DelayedMaterializingCTEsStep for these CTEs will not add materialization plans again.
1623 /// 2. If set is built during main query execution, we will build plans for used CTEs materialization to be run before the set is built
1624 /// and before the main query is executed.
1625 subquery_options.forceMaterializeCTE();
1626 /// I don't know if this is a good decision,
1627 /// but for now it is done in the same way as in old analyzer.
1628 /// This would not ignore limits for subqueries (affects mutations only).
1629 /// See test_build_sets_from_multiple_threads-analyzer.
1630 subquery_options.ignore_limits = false;
1631 Planner subquery_planner(
1632 query_tree,
1633 subquery_options,
1634 std::make_shared<GlobalPlannerContext>(
1635 nullptr, nullptr, nullptr, collectFiltersForAnalysis(query_tree, subquery_options, nullptr)));
1636 subquery_planner.buildQueryPlanIfNeeded();
1637
1638 auto subquery_plan = std::move(subquery_planner).extractQueryPlan();
1639 /// Contexts should be copied into the root query plan, because some functions may
1640 /// be created using them while this subquery plan will be destroyed after
1641 /// FutureSetFromSubquery::buildSetInplace(). Otherwise, function execution may fail
1642 /// with a "Context has expired" exception.
1643 for (const auto & context : subquery_plan.getInterpretersContexts())
1644 query_plan.addInterpreterContext(context);
1645 subquery->setQueryPlan(std::make_unique<QueryPlan>(std::move(subquery_plan)));
1646 }
1647
1648 if (!subqueries.empty())
1649 {
1650 const auto & settings = planner_context->getQueryContext()->getSettingsRef();
1651 SizeLimits network_transfer_limits(settings[Setting::max_rows_to_transfer], settings[Setting::max_bytes_to_transfer], settings[Setting::transfer_overflow_mode]);
1652 auto prepared_sets_cache = planner_context->getQueryContext()->getPreparedSetsCache();
1653
1654 auto step = std::make_unique<DelayedCreatingSetsStep>(

Callers 1

buildPlanForQueryNodeMethod · 0.85

Calls 15

detachQueryTreeMethod · 0.80
subqueryMethod · 0.80
extractQueryPlanMethod · 0.80
setQueryPlanMethod · 0.80
getSubqueriesMethod · 0.45
containsMethod · 0.45
beginMethod · 0.45
endMethod · 0.45
eraseMethod · 0.45

Tested by

no test coverage detected