#include #include #include #include #include #include #include #include #include namespace DB { namespace ErrorCodes { extern const int UNSUPPORTED_METHOD; } namespace { class CollectSetsVisitor : public ConstInDepthQueryTreeVisitor { public: explicit CollectSetsVisitor(PlannerContext & planner_context_) : planner_context(planner_context_) {} void visitImpl(const QueryTreeNodePtr & node) { auto * function_node = node->as(); if (!function_node || !isNameOfInFunction(function_node->getFunctionName())) return; auto in_first_argument = function_node->getArguments().getNodes().at(0); auto in_second_argument = function_node->getArguments().getNodes().at(1); auto in_second_argument_node_type = in_second_argument->getNodeType(); const auto & settings = planner_context.getQueryContext()->getSettingsRef(); String set_key = planner_context.createSetKey(in_second_argument); if (planner_context.hasSet(set_key)) return; /// Tables and table functions are replaced with subquery at Analysis stage, except special Set table. auto * second_argument_table = in_second_argument->as(); StorageSet * storage_set = second_argument_table != nullptr ? dynamic_cast(second_argument_table->getStorage().get()) : nullptr; if (storage_set) { planner_context.registerSet(set_key, PlannerSet(storage_set->getSet())); } else if (const auto * constant_node = in_second_argument->as()) { auto set = makeSetForConstantValue( in_first_argument->getResultType(), constant_node->getValue(), constant_node->getResultType(), settings); planner_context.registerSet(set_key, PlannerSet(std::move(set))); } else if (in_second_argument_node_type == QueryTreeNodeType::QUERY || in_second_argument_node_type == QueryTreeNodeType::UNION) { SizeLimits size_limits_for_set = {settings.max_rows_in_set, settings.max_bytes_in_set, settings.set_overflow_mode}; bool tranform_null_in = settings.transform_null_in; auto set = std::make_shared(size_limits_for_set, false /*fill_set_elements*/, tranform_null_in); planner_context.registerSet(set_key, PlannerSet(std::move(set), in_second_argument)); } else { throw Exception(ErrorCodes::UNSUPPORTED_METHOD, "Function '{}' is supported only if second argument is constant or table expression", function_node->getFunctionName()); } } static bool needChildVisit(const QueryTreeNodePtr & parent_node, const QueryTreeNodePtr & child_node) { if (parent_node->getNodeType() == QueryTreeNodeType::CONSTANT) return false; auto child_node_type = child_node->getNodeType(); return !(child_node_type == QueryTreeNodeType::QUERY || child_node_type == QueryTreeNodeType::UNION); } private: PlannerContext & planner_context; }; } void collectSets(const QueryTreeNodePtr & node, PlannerContext & planner_context) { CollectSetsVisitor visitor(planner_context); visitor.visit(node); } }