11#include < Storages/MergeTree/RPNBuilder.h>
22
33#include < Common/FieldVisitorToString.h>
4+ #include < Storages/MergeTree/KeyCondition.h>
45#include < Core/Settings.h>
56
67#include < Parsers/ASTLiteral.h>
1819#include < Functions/indexHint.h>
1920#include < Functions/IFunction.h>
2021#include < Functions/IFunctionAdaptors.h>
22+ #include < Functions/FunctionsMiscellaneous.h>
2123
2224#include < Interpreters/Context.h>
2325
@@ -41,7 +43,7 @@ namespace ErrorCodes
4143namespace
4244{
4345
44- void appendColumnNameWithoutAlias (const ActionsDAG::Node & node, WriteBuffer & out, bool allow_experimental_analyzer , bool legacy = false )
46+ void appendColumnNameWithoutAlias (const ActionsDAG::Node & node, WriteBuffer & out, const ContextPtr & context, bool use_analyzer , bool legacy = false )
4547{
4648 switch (node.type )
4749 {
@@ -53,37 +55,72 @@ void appendColumnNameWithoutAlias(const ActionsDAG::Node & node, WriteBuffer & o
5355 // / If it was created from ASTLiteral, then result_name can be an alias.
5456 // / We need to convert value back to string here.
5557 const auto * column_const = typeid_cast<const ColumnConst *>(node.column .get ());
56- if (column_const && !allow_experimental_analyzer )
58+ if (column_const && !use_analyzer )
5759 writeString (applyVisitor (FieldVisitorToString (), column_const->getField ()), out);
5860 else
5961 writeString (node.result_name , out);
6062 break ;
6163 }
6264 case ActionsDAG::ActionType::ALIAS:
63- appendColumnNameWithoutAlias (*node.children .front (), out, allow_experimental_analyzer , legacy);
65+ appendColumnNameWithoutAlias (*node.children .front (), out, context, use_analyzer , legacy);
6466 break ;
6567 case ActionsDAG::ActionType::ARRAY_JOIN:
6668 writeCString (" arrayJoin(" , out);
67- appendColumnNameWithoutAlias (*node.children .front (), out, allow_experimental_analyzer , legacy);
69+ appendColumnNameWithoutAlias (*node.children .front (), out, context, use_analyzer , legacy);
6870 writeChar (' )' , out);
6971 break ;
7072 case ActionsDAG::ActionType::FUNCTION:
7173 {
72- auto name = node.function_base ->getName ();
73- if (legacy && name == " modulo" )
74- writeCString (" moduloLegacy" , out);
74+ if (const auto * func_capture = typeid_cast<const ExecutableFunctionCapture *>(node.function .get ()))
75+ {
76+ const auto & capture = func_capture->getCapture ();
77+ auto capture_dag = func_capture->getActions ()->getActionsDAG ().clone ();
78+ if (!node.children .empty ())
79+ {
80+ auto captured_columns_dag = ActionsDAG::cloneSubDAG (node.children , false );
81+ auto & outputs = captured_columns_dag.getOutputs ();
82+ for (size_t i = 0 ; i < capture->captured_names .size (); ++i)
83+ outputs[i] = &captured_columns_dag.addAlias (*outputs[i], capture->captured_names [i]);
84+
85+ capture_dag = ActionsDAG::merge (std::move (captured_columns_dag), std::move (capture_dag));
86+ }
87+
88+ writeString (" lambda(tuple(" , out);
89+ bool first = true ;
90+ for (const auto & arg : capture->lambda_arguments )
91+ {
92+ if (!first)
93+ writeCString (" , " , out);
94+ first = false ;
95+
96+ writeString (arg.name , out);
97+ }
98+ writeString (" ), " , out);
99+
100+ ActionsDAGWithInversionPushDown inverted_capture_dag (capture_dag.getOutputs ().at (0 ), context);
101+ appendColumnNameWithoutAlias (*inverted_capture_dag.predicate , out, context, use_analyzer, legacy);
102+ writeChar (' )' , out);
103+ break ;
104+ }
75105 else
76- writeString (name, out);
106+ {
107+ auto name = node.function_base ->getName ();
108+ if (legacy && name == " modulo" )
109+ writeCString (" moduloLegacy" , out);
110+ else
111+ writeString (name, out);
112+
113+ writeChar (' (' , out);
114+ }
77115
78- writeChar (' (' , out);
79116 bool first = true ;
80117 for (const auto * arg : node.children )
81118 {
82119 if (!first)
83120 writeCString (" , " , out);
84121 first = false ;
85122
86- appendColumnNameWithoutAlias (*arg, out, allow_experimental_analyzer , legacy);
123+ appendColumnNameWithoutAlias (*arg, out, context, use_analyzer , legacy);
87124 }
88125 writeChar (' )' , out);
89126 break ;
@@ -94,10 +131,10 @@ void appendColumnNameWithoutAlias(const ActionsDAG::Node & node, WriteBuffer & o
94131 }
95132}
96133
97- String getColumnNameWithoutAlias (const ActionsDAG::Node & node, bool allow_experimental_analyzer , bool legacy = false )
134+ String getColumnNameWithoutAlias (const ActionsDAG::Node & node, const ContextPtr & context, bool use_analyzer , bool legacy = false )
98135{
99136 WriteBufferFromOwnString out;
100- appendColumnNameWithoutAlias (node, out, allow_experimental_analyzer , legacy);
137+ appendColumnNameWithoutAlias (node, out, context, use_analyzer , legacy);
101138
102139 return std::move (out.str ());
103140}
@@ -148,7 +185,7 @@ std::string RPNBuilderTreeNode::getColumnName() const
148185 if (ast_node)
149186 return ast_node->getColumnNameWithoutAlias ();
150187
151- return getColumnNameWithoutAlias (*dag_node, getTreeContext ().getSettings ()[Setting::allow_experimental_analyzer]);
188+ return getColumnNameWithoutAlias (*dag_node, getTreeContext ().getQueryContext (), getTreeContext (). getSettings ()[Setting::allow_experimental_analyzer]);
152189}
153190
154191std::string RPNBuilderTreeNode::getColumnNameWithModuloLegacy () const
@@ -160,7 +197,7 @@ std::string RPNBuilderTreeNode::getColumnNameWithModuloLegacy() const
160197 return adjusted_ast->getColumnNameWithoutAlias ();
161198 }
162199
163- return getColumnNameWithoutAlias (*dag_node, getTreeContext ().getSettings ()[Setting::allow_experimental_analyzer], true /* legacy*/ );
200+ return getColumnNameWithoutAlias (*dag_node, getTreeContext ().getQueryContext (), getTreeContext (). getSettings ()[Setting::allow_experimental_analyzer], true /* legacy*/ );
164201}
165202
166203bool RPNBuilderTreeNode::isFunction () const
0 commit comments