@@ -128,7 +128,7 @@ struct OpNode {
128128// / A placeholder node for simple type configurable
129129struct PlaceholderNode : LiteralNode {
130130 template <typename T>
131- PlaceholderNode (Configurable<T> v) : LiteralNode{v.value }, name{v.name }
131+ PlaceholderNode (Configurable<T> const & v) : LiteralNode{v.value }, name{v.name }
132132 {
133133 if constexpr (variant_trait_v<typename std::decay<T>::type> != VariantType::Unknown) {
134134 retrieve = [](InitContext& context, std::string const & name) { return LiteralNode::var_t {context.options ().get <T>(name.c_str ())}; };
@@ -146,40 +146,54 @@ struct PlaceholderNode : LiteralNode {
146146 LiteralNode::var_t (*retrieve)(InitContext&, std::string const & name);
147147};
148148
149+ // / A conditional node
150+ struct ConditionalNode {
151+ };
152+
149153// / A generic tree node
150154struct Node {
151- Node (LiteralNode v) : self{v}, left{nullptr }, right{nullptr }
155+ Node (LiteralNode v) : self{v}, left{nullptr }, right{nullptr }, condition{ nullptr }
152156 {
153157 }
154158
155- Node (PlaceholderNode v) : self{v}, left{nullptr }, right{nullptr }
159+ Node (PlaceholderNode v) : self{v}, left{nullptr }, right{nullptr }, condition{ nullptr }
156160 {
157161 }
158162
159- Node (Node&& n) : self{n.self }, left{std::move (n.left )}, right{std::move (n.right )}
163+ Node (Node&& n) : self{n.self }, left{std::move (n.left )}, right{std::move (n.right )}, condition{ std::move (n. condition )}
160164 {
161165 }
162166
163- Node (BindingNode n) : self{n}, left{nullptr }, right{nullptr }
167+ Node (BindingNode n) : self{n}, left{nullptr }, right{nullptr }, condition{ nullptr }
164168 {
165169 }
166170
171+ Node (ConditionalNode op, Node&& then_, Node&& else_, Node&& condition_)
172+ : self{op},
173+ left{std::make_unique<Node>(std::move (then_))},
174+ right{std::make_unique<Node>(std::move (else_))},
175+ condition{std::make_unique<Node>(std::move (condition_))} {}
176+
167177 Node (OpNode op, Node&& l, Node&& r)
168178 : self{op},
169179 left{std::make_unique<Node>(std::move (l))},
170- right{std::make_unique<Node>(std::move (r))} {}
180+ right{std::make_unique<Node>(std::move (r))},
181+ condition{nullptr } {}
171182
172183 Node (OpNode op, Node&& l)
173184 : self{op},
174185 left{std::make_unique<Node>(std::move (l))},
175- right{nullptr } {}
186+ right{nullptr },
187+ condition{nullptr } {}
176188
177189 // / variant with possible nodes
178- using self_t = std::variant<LiteralNode, BindingNode, OpNode, PlaceholderNode>;
190+ using self_t = std::variant<LiteralNode, BindingNode, OpNode, PlaceholderNode, ConditionalNode >;
179191 self_t self;
192+ size_t index = 0 ;
180193 // / pointers to children
181194 std::unique_ptr<Node> left;
182195 std::unique_ptr<Node> right;
196+ std::unique_ptr<Node> condition;
183197};
184198
185199// / overloaded operators to build the tree from an expression
@@ -319,20 +333,84 @@ inline Node nbitwise_not(Node left)
319333 return Node{OpNode{BasicOp::BitwiseNot}, std::move (left)};
320334}
321335
336+ // / conditionals
337+ template <typename C, typename T, typename E>
338+ inline Node ifnode (C condition_, T then_, E else_)
339+ {
340+ return Node{ConditionalNode{}, std::move (then_), std::move (else_), std::move (condition_)};
341+ }
342+
343+ template <>
344+ inline Node ifnode (Node condition_, Node then_, Node else_)
345+ {
346+ return Node{ConditionalNode{}, std::move (then_), std::move (else_), std::move (condition_)};
347+ }
348+
349+ template <typename L, std::enable_if_t <std::is_integral<L>::value || std::is_floating_point<L>::value, bool > = true >
350+ inline Node ifnode (Node condition_, Node then_, L else_)
351+ {
352+ return Node{ConditionalNode{}, std::move (then_), LiteralNode{else_}, std::move (condition_)};
353+ }
354+
355+ template <typename L, std::enable_if_t <std::is_integral<L>::value || std::is_floating_point<L>::value, bool > = true >
356+ inline Node ifnode (Node condition_, L then_, Node else_)
357+ {
358+ return Node{ConditionalNode{}, LiteralNode{then_}, std::move (else_), std::move (condition_)};
359+ }
360+
361+ template <typename L1 , typename L2 , std::enable_if_t <(std::is_integral<L1 >::value || std::is_floating_point<L1 >::value) && (std::is_integral<L2 >::value || std::is_floating_point<L2 >::value), bool > = true >
362+ inline Node ifnode (Node condition_, L1 then_, L2 else_)
363+ {
364+ return Node{ConditionalNode{}, LiteralNode{then_}, LiteralNode{else_}, std::move (condition_)};
365+ }
366+
367+ template <typename T>
368+ inline Node ifnode (Configurable<T> condition_, Node then_, Node else_)
369+ {
370+ return Node{ConditionalNode{}, std::move (then_), std::move (else_), PlaceholderNode{condition_}};
371+ }
372+
373+ template <typename L>
374+ inline Node ifnode (Node condition_, Node then_, Configurable<L> else_)
375+ {
376+ return Node{ConditionalNode{}, std::move (then_), PlaceholderNode{else_}, std::move (condition_)};
377+ }
378+
379+ template <typename L>
380+ inline Node ifnode (Node condition_, Configurable<L> then_, Node else_)
381+ {
382+ return Node{ConditionalNode{}, PlaceholderNode{then_}, std::move (else_), std::move (condition_)};
383+ }
384+
385+ template <typename L1 , typename L2 >
386+ inline Node ifnode (Node condition_, Configurable<L1 > then_, Configurable<L2 > else_)
387+ {
388+ return Node{ConditionalNode{}, PlaceholderNode{then_}, PlaceholderNode{else_}, std::move (condition_)};
389+ }
390+
322391// / A struct, containing the root of the expression tree
323392struct Filter {
324- Filter (Node&& node_) : node{std::make_unique<Node>(std::move (node_))} {}
325- Filter (Filter&& other) : node{std::move (other.node )} {}
393+ Filter (Node&& node_) : node{std::make_unique<Node>(std::move (node_))}
394+ {
395+ (void )designateSubtrees (node.get ());
396+ }
397+
398+ Filter (Filter&& other) : node{std::move (other.node )}
399+ {
400+ (void )designateSubtrees (node.get ());
401+ }
326402 std::unique_ptr<Node> node;
403+
404+ size_t designateSubtrees (Node* node, size_t index = 0 );
327405};
328406
329407using Projector = Filter;
330408
331409using Selection = std::shared_ptr<gandiva::SelectionVector>;
332410// / Function for creating gandiva selection from our internal filter tree
333- Selection createSelection (std::shared_ptr<arrow::Table> table, Filter const & expression);
411+ Selection createSelection (std::shared_ptr<arrow::Table> const & table, Filter const & expression);
334412// / Function for creating gandiva selection from prepared gandiva expressions tree
335- Selection createSelection (std::shared_ptr<arrow::Table> table, std::shared_ptr<gandiva::Filter> gfilter);
413+ Selection createSelection (std::shared_ptr<arrow::Table> const & table, std::shared_ptr<gandiva::Filter> gfilter);
336414
337415struct ColumnOperationSpec ;
338416using Operations = std::vector<ColumnOperationSpec>;
0 commit comments