Project
Loading...
Searching...
No Matches
Expressions.h
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11#ifndef O2_FRAMEWORK_EXPRESSIONS_H_
12#define O2_FRAMEWORK_EXPRESSIONS_H_
13
14#include "Framework/BasicOps.h"
16#include "Framework/Pack.h"
18#include "Framework/Variant.h"
22#include <arrow/type_fwd.h>
23#include <gandiva/gandiva_aliases.h>
24#include <arrow/type.h>
25#include <gandiva/arrow.h>
26#if !defined(__CLING__) && !defined(__ROOTCLING__)
27#include <arrow/table.h>
28#include <gandiva/selection_vector.h>
29#include <gandiva/node.h>
30#include <gandiva/filter.h>
31#include <gandiva/projector.h>
32#else
33namespace gandiva
34{
35class SelectionVector;
36class Filter;
37class Projector;
38} // namespace gandiva
39#endif
40#include <variant>
41#include <string>
42#include <memory>
43#include <set>
44namespace gandiva
45{
46using Selection = std::shared_ptr<gandiva::SelectionVector>;
47using FilterPtr = std::shared_ptr<gandiva::Filter>;
48} // namespace gandiva
49
50using atype = arrow::Type;
52 ExpressionInfo(int ai, size_t hash, std::set<uint32_t>&& hs, gandiva::SchemaPtr sc)
53 : argumentIndex(ai),
54 processHash(hash),
55 hashes(hs),
56 schema(sc)
57 {
58 }
61 std::set<uint32_t> hashes;
62 gandiva::SchemaPtr schema;
63 gandiva::NodePtr tree = nullptr;
66 bool resetSelection = false;
67};
68
70{
71const char* stringType(atype::type t);
72
73template <typename... T>
75 using stored_type = std::variant<T...>;
77};
78
80
81template <typename T>
82constexpr auto selectArrowType()
83{
84 return atype::NA;
85}
86
87#define SELECT_ARROW_TYPE(_Ctype_, _Atype_) \
88 template <typename T> \
89 requires std::same_as<T, _Ctype_> \
90 constexpr auto selectArrowType() \
91 { \
92 return atype::_Atype_; \
93 }
94
96SELECT_ARROW_TYPE(float, FLOAT);
97SELECT_ARROW_TYPE(double, DOUBLE);
98SELECT_ARROW_TYPE(uint8_t, UINT8);
99SELECT_ARROW_TYPE(int8_t, INT8);
100SELECT_ARROW_TYPE(uint16_t, UINT16);
101SELECT_ARROW_TYPE(int16_t, INT16);
102SELECT_ARROW_TYPE(uint32_t, UINT32);
103SELECT_ARROW_TYPE(int32_t, INT32);
104SELECT_ARROW_TYPE(uint64_t, UINT64);
105SELECT_ARROW_TYPE(int64_t, INT64);
106
107std::shared_ptr<arrow::DataType> concreteArrowType(atype::type type);
108std::string upcastTo(atype::type f);
109
112 template <typename T>
114 {
115 }
116
119 atype::type type = atype::NA;
120};
121
124 BindingNode(BindingNode const&) = default;
126 constexpr BindingNode(const char* name_, uint32_t hash_, atype::type type_) : name{name_}, hash{hash_}, type{type_} {}
127 const char* name;
128 uint32_t hash;
129 atype::type type;
130};
131
133struct OpNode {
134 OpNode(BasicOp op_) : op{op_} {}
136};
137
140 template <typename T>
142 {
143 if constexpr (variant_trait_v<typename std::decay<T>::type> != VariantType::Unknown) {
144 retrieve = [](InitContext& context, char const* name) { return LiteralNode::var_t{context.options().get<T>(name)}; };
145 } else {
146 runtime_error("Unknown parameter used in expression.");
147 }
148 }
149
150 void reset(InitContext& context)
151 {
152 value = retrieve(context, name.data());
153 }
154
155 std::string const& name;
157};
158
161};
162
164struct Node {
165 Node(LiteralNode&& v) : self{std::forward<LiteralNode>(v)}, left{nullptr}, right{nullptr}, condition{nullptr}
166 {
167 }
168
169 Node(PlaceholderNode&& v) : self{std::forward<PlaceholderNode>(v)}, left{nullptr}, right{nullptr}, condition{nullptr}
170 {
171 }
172
173 Node(Node&& n) : self{std::forward<self_t>(n.self)}, left{std::forward<std::unique_ptr<Node>>(n.left)}, right{std::forward<std::unique_ptr<Node>>(n.right)}, condition{std::forward<std::unique_ptr<Node>>(n.condition)}
174 {
175 }
176
177 Node(BindingNode const& n) : self{n}, left{nullptr}, right{nullptr}, condition{nullptr}
178 {
179 }
180
181 Node(ConditionalNode op, Node&& then_, Node&& else_, Node&& condition_)
182 : self{op},
183 left{std::make_unique<Node>(std::forward<Node>(then_))},
184 right{std::make_unique<Node>(std::forward<Node>(else_))},
185 condition{std::make_unique<Node>(std::forward<Node>(condition_))} {}
186
188 : self{op},
189 left{std::make_unique<Node>(std::forward<Node>(l))},
190 right{std::make_unique<Node>(std::forward<Node>(r))},
191 condition{nullptr} {}
192
194 : self{op},
195 left{std::make_unique<Node>(std::forward<Node>(l))},
196 right{nullptr},
197 condition{nullptr} {}
198
200 using self_t = std::variant<LiteralNode, BindingNode, OpNode, PlaceholderNode, ConditionalNode>;
202 size_t index = 0;
204 std::unique_ptr<Node> left;
205 std::unique_ptr<Node> right;
206 std::unique_ptr<Node> condition;
207};
208
210
211#define BINARY_OP_NODES(_operator_, _operation_) \
212 inline Node operator _operator_(Node&& left, Node&& right) \
213 { \
214 return Node{OpNode{BasicOp::_operation_}, std::forward<Node>(left), std::forward<Node>(right)}; \
215 } \
216 template <typename T> \
217 inline Node operator _operator_(Node&& left, T right) requires(std::is_arithmetic_v<std::decay_t<T>>) \
218 { \
219 return Node{OpNode{BasicOp::_operation_}, std::forward<Node>(left), LiteralNode{right}}; \
220 } \
221 template <typename T> \
222 inline Node operator _operator_(T left, Node&& right) requires(std::is_arithmetic_v<std::decay_t<T>>) \
223 { \
224 return Node{OpNode{BasicOp::_operation_}, LiteralNode{left}, std::forward<Node>(right)}; \
225 } \
226 template <typename T> \
227 inline Node operator _operator_(Node&& left, Configurable<T> const& right) \
228 { \
229 return Node{OpNode{BasicOp::_operation_}, std::forward<Node>(left), PlaceholderNode{right}}; \
230 } \
231 template <typename T> \
232 inline Node operator _operator_(Configurable<T> const& left, Node&& right) \
233 { \
234 return Node{OpNode{BasicOp::_operation_}, PlaceholderNode{left}, std::forward<Node>(right)}; \
235 } \
236 inline Node operator _operator_(BindingNode const& left, BindingNode const& right) \
237 { \
238 return Node{OpNode{BasicOp::_operation_}, left, right}; \
239 } \
240 inline Node operator _operator_(BindingNode const& left, Node&& right) \
241 { \
242 return Node{OpNode{BasicOp::_operation_}, left, std::forward<Node>(right)}; \
243 } \
244 inline Node operator _operator_(Node&& left, BindingNode const& right) \
245 { \
246 return Node{OpNode{BasicOp::_operation_}, std::forward<Node>(left), right}; \
247 } \
248 template <typename T> \
249 inline Node operator _operator_(Configurable<T> const& left, BindingNode const& right) \
250 { \
251 return Node{OpNode{BasicOp::_operation_}, PlaceholderNode{left}, right}; \
252 } \
253 template <typename T> \
254 inline Node operator _operator_(BindingNode const& left, Configurable<T> const& right) \
255 { \
256 return Node{OpNode{BasicOp::_operation_}, left, PlaceholderNode{right}}; \
257 }
258
274
276template <typename T>
277inline Node npow(Node&& left, T right) requires(std::is_arithmetic_v<T>)
278{
279 return Node{OpNode{BasicOp::Power}, std::forward<Node>(left), LiteralNode{right}};
280}
281
282#define BINARY_FUNC_NODES(_func_, _node_) \
283 template <typename L, typename R> \
284 inline Node _node_(L left, R right) requires(std::is_arithmetic_v<L> && std::is_arithmetic_v<R>) \
285 { \
286 return Node{OpNode{BasicOp::_func_}, LiteralNode{left}, LiteralNode{right}}; \
287 } \
288 \
289 inline Node _node_(Node&& left, Node&& right) \
290 { \
291 return Node{OpNode{BasicOp::_func_}, std::forward<Node>(left), std::forward<Node>(right)}; \
292 } \
293 \
294 inline Node _node_(Node&& left, BindingNode const& right) \
295 { \
296 return Node{OpNode{BasicOp::_func_}, std::forward<Node>(left), right}; \
297 } \
298 \
299 inline Node _node_(BindingNode const& left, BindingNode const& right) \
300 { \
301 return Node{OpNode{BasicOp::_func_}, left, right}; \
302 } \
303 \
304 inline Node _node_(BindingNode const& left, Node&& right) \
305 { \
306 return Node{OpNode{BasicOp::_func_}, left, std::forward<Node>(right)}; \
307 } \
308 \
309 template <typename T> \
310 inline Node _node_(Node&& left, Configurable<T> const& right) \
311 { \
312 return Node{OpNode{BasicOp::_func_}, std::forward<Node>(left), PlaceholderNode{right}}; \
313 } \
314 \
315 template <typename T> \
316 inline Node _node_(Configurable<T> const& left, Node&& right) \
317 { \
318 return Node{OpNode{BasicOp::_func_}, PlaceholderNode{left}, std::forward<Node>(right)}; \
319 } \
320 \
321 template <typename T> \
322 inline Node _node_(BindingNode const& left, Configurable<T> const& right) \
323 { \
324 return Node{OpNode{BasicOp::_func_}, left, PlaceholderNode{right}}; \
325 } \
326 \
327 template <typename T> \
328 inline Node _node_(Configurable<T> const& left, BindingNode const& right) \
329 { \
330 return Node{OpNode{BasicOp::_func_}, PlaceholderNode{left}, right}; \
331 }
332
334#define ncheckbit(_node_, _bit_) ((_node_ & _bit_) == _bit_)
335
337#define UNARY_FUNC_NODES(_func_, _node_) \
338 inline Node _node_(Node&& arg) \
339 { \
340 return Node{OpNode{BasicOp::_func_}, std::forward<Node>(arg)}; \
341 }
342
356
358inline Node ifnode(Node&& condition_, Node&& then_, Node&& else_)
359{
360 return Node{ConditionalNode{}, std::forward<Node>(then_), std::forward<Node>(else_), std::forward<Node>(condition_)};
361}
362
363template <typename L>
364inline Node ifnode(Node&& condition_, Node&& then_, L else_) requires(std::is_arithmetic_v<L>)
365{
366 return Node{ConditionalNode{}, std::forward<Node>(then_), LiteralNode{else_}, std::forward<Node>(condition_)};
367}
368
369template <typename L>
370inline Node ifnode(Node&& condition_, L then_, Node&& else_) requires(std::is_arithmetic_v<L>)
371{
372 return Node{ConditionalNode{}, LiteralNode{then_}, std::forward<Node>(else_), std::forward<Node>(condition_)};
373}
374
375template <typename L1, typename L2>
376inline Node ifnode(Node&& condition_, L1 then_, L2 else_) requires(std::is_arithmetic_v<L1>&& std::is_arithmetic_v<L2>)
377{
378 return Node{ConditionalNode{}, LiteralNode{then_}, LiteralNode{else_}, std::forward<Node>(condition_)};
379}
380
381template <typename T>
382inline Node ifnode(Configurable<T> const& condition_, Node&& then_, Node&& else_)
383{
384 return Node{ConditionalNode{}, std::forward<Node>(then_), std::forward<Node>(else_), PlaceholderNode{condition_}};
385}
386
387template <typename L>
388inline Node ifnode(Node&& condition_, Node&& then_, Configurable<L> const& else_)
389{
390 return Node{ConditionalNode{}, std::forward<Node>(then_), PlaceholderNode{else_}, std::forward<Node>(condition_)};
391}
392
393template <typename L>
394inline Node ifnode(Node&& condition_, Configurable<L> const& then_, Node&& else_)
395{
396 return Node{ConditionalNode{}, PlaceholderNode{then_}, std::forward<Node>(else_), std::forward<Node>(condition_)};
397}
398
399template <typename L1, typename L2>
400inline Node ifnode(Node&& condition_, Configurable<L1> const& then_, Configurable<L2> const& else_)
401{
402 return Node{ConditionalNode{}, PlaceholderNode{then_}, PlaceholderNode{else_}, std::forward<Node>(condition_)};
403}
404
406struct Filter {
407 Filter(Node&& node_) : node{std::make_unique<Node>(std::forward<Node>(node_))}
408 {
410 }
411
412 Filter(Filter&& other) : node{std::forward<std::unique_ptr<Node>>(other.node)}
413 {
415 }
416 std::unique_ptr<Node> node;
417
418 size_t designateSubtrees(Node* node, size_t index = 0);
419};
420
421template <typename T>
422concept is_filter = std::same_as<T, Filter>;
423
425
427gandiva::Selection createSelection(std::shared_ptr<arrow::Table> const& table, Filter const& expression);
429gandiva::Selection createSelection(std::shared_ptr<arrow::Table> const& table, std::shared_ptr<gandiva::Filter> const& gfilter);
430
432using Operations = std::vector<ColumnOperationSpec>;
433
435Operations createOperations(Filter const& expression);
436
438bool isTableCompatible(std::set<uint32_t> const& hashes, Operations const& specs);
440gandiva::NodePtr createExpressionTree(Operations const& opSpecs,
441 gandiva::SchemaPtr const& Schema);
443std::shared_ptr<gandiva::Filter> createFilter(gandiva::SchemaPtr const& Schema,
444 gandiva::ConditionPtr condition);
446std::shared_ptr<gandiva::Filter> createFilter(gandiva::SchemaPtr const& Schema,
447 Operations const& opSpecs);
449std::shared_ptr<gandiva::Projector> createProjector(gandiva::SchemaPtr const& Schema,
450 Operations const& opSpecs,
451 gandiva::FieldPtr result);
453std::shared_ptr<gandiva::Projector> createProjector(gandiva::SchemaPtr const& Schema,
454 Projector&& p,
455 gandiva::FieldPtr result);
457void updateExpressionInfos(expressions::Filter const& filter, std::vector<ExpressionInfo>& eInfos);
459gandiva::ConditionPtr makeCondition(gandiva::NodePtr node);
461gandiva::ExpressionPtr makeExpression(gandiva::NodePtr node, gandiva::FieldPtr result);
464
465template <typename... C>
466std::vector<expressions::Projector> makeProjectors(framework::pack<C...>)
467{
468 return {C::Projector()...};
469}
470
471std::shared_ptr<gandiva::Projector> createProjectorHelper(size_t nColumns, expressions::Projector* projectors,
472 std::shared_ptr<arrow::Schema> schema,
473 std::vector<std::shared_ptr<arrow::Field>> const& fields);
474
475template <typename... C>
476std::shared_ptr<gandiva::Projector> createProjectors(framework::pack<C...>, std::vector<std::shared_ptr<arrow::Field>> const& fields, gandiva::SchemaPtr schema)
477{
478 std::array<expressions::Projector, sizeof...(C)> projectors{{std::move(C::Projector())...}};
479
480 return createProjectorHelper(sizeof...(C), projectors.data(), schema, fields);
481}
482
483void updateFilterInfo(ExpressionInfo& info, std::shared_ptr<arrow::Table>& table);
484} // namespace o2::framework::expressions
485
486#endif // O2_FRAMEWORK_EXPRESSIONS_H_
#define SELECT_ARROW_TYPE(_Ctype_, _Atype_)
Definition Expressions.h:87
#define BINARY_FUNC_NODES(_func_, _node_)
arrow::Type atype
Definition Expressions.h:50
#define UNARY_FUNC_NODES(_func_, _node_)
unary functions on nodes
uint32_t op
uint32_t gfilter
Definition RawData.h:6
ConfigParamRegistry const & options()
Definition InitContext.h:33
GLdouble n
Definition glcorearb.h:1982
GLuint64EXT * result
Definition glcorearb.h:5662
const GLdouble * v
Definition glcorearb.h:832
GLuint index
Definition glcorearb.h:781
GLuint const GLchar * name
Definition glcorearb.h:781
GLdouble GLdouble right
Definition glcorearb.h:4077
GLdouble f
Definition glcorearb.h:310
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition glcorearb.h:1308
GLboolean r
Definition glcorearb.h:1233
std::shared_ptr< gandiva::Filter > FilterPtr
Definition Expressions.h:47
std::shared_ptr< gandiva::SelectionVector > Selection
Definition Expressions.h:46
std::shared_ptr< arrow::DataType > concreteArrowType(atype::type type)
std::shared_ptr< gandiva::Filter > createFilter(gandiva::SchemaPtr const &Schema, gandiva::ConditionPtr condition)
Function to create gandiva filter from gandiva condition.
gandiva::ExpressionPtr makeExpression(gandiva::NodePtr node, gandiva::FieldPtr result)
Function to create gandiva projecting expression from generic gandiva expression tree.
BINARY_OP_NODES && LogicalAnd
BINARY_OP_NODES & BitwiseAnd
std::shared_ptr< gandiva::Projector > createProjectorHelper(size_t nColumns, expressions::Projector *projectors, std::shared_ptr< arrow::Schema > schema, std::vector< std::shared_ptr< arrow::Field > > const &fields)
gandiva::Selection createSelection(std::shared_ptr< arrow::Table > const &table, Filter const &expression)
Function for creating gandiva selection from our internal filter tree.
const char * stringType(atype::type t)
std::vector< ColumnOperationSpec > Operations
void updateExpressionInfos(expressions::Filter const &filter, std::vector< ExpressionInfo > &eInfos)
Function for attaching gandiva filters to to compatible task inputs.
constexpr auto selectArrowType()
Definition Expressions.h:82
Operations createOperations(Filter const &expression)
Function to create an internal operation sequence from a filter tree.
gandiva::ConditionPtr makeCondition(gandiva::NodePtr node)
Function to create gandiva condition expression from generic gandiva expression tree.
bool isTableCompatible(std::set< uint32_t > const &hashes, Operations const &specs)
Function to check compatibility of a given arrow schema with operation sequence.
Node ifnode(Node &&condition_, Node &&then_, Node &&else_)
conditionals
gandiva::NodePtr createExpressionTree(Operations const &opSpecs, gandiva::SchemaPtr const &Schema)
Function to create gandiva expression tree from operation sequence.
void updatePlaceholders(Filter &filter, InitContext &context)
Update placeholder nodes from context.
BINARY_OP_NODES^ BitwiseXor
BINARY_OP_NODES * Multiplication
Node npow(Node &&left, T right)
functions
std::string upcastTo(atype::type f)
std::shared_ptr< gandiva::Projector > createProjector(gandiva::SchemaPtr const &Schema, Operations const &opSpecs, gandiva::FieldPtr result)
Function to create gandiva projector from operation sequence.
std::vector< expressions::Projector > makeProjectors(framework::pack< C... >)
std::shared_ptr< gandiva::Projector > createProjectors(framework::pack< C... >, std::vector< std::shared_ptr< arrow::Field > > const &fields, gandiva::SchemaPtr schema)
void updateFilterInfo(ExpressionInfo &info, std::shared_ptr< arrow::Table > &table)
RuntimeErrorRef runtime_error(const char *)
@ GreaterThanOrEqual
Definition BasicOps.h:29
std::vector< int64_t > SelectionVector
Definition ASoA.h:406
Defining DataPointCompositeObject explicitly as copiable.
gandiva::Selection selection
Definition Expressions.h:65
gandiva::SchemaPtr schema
Definition Expressions.h:62
ExpressionInfo(int ai, size_t hash, std::set< uint32_t > &&hs, gandiva::SchemaPtr sc)
Definition Expressions.h:52
std::set< uint32_t > hashes
Definition Expressions.h:61
gandiva::NodePtr tree
Definition Expressions.h:63
size_t processHash
Definition Expressions.h:60
An expression tree node corresponding to a column binding.
constexpr BindingNode(const char *name_, uint32_t hash_, atype::type type_)
BindingNode(BindingNode const &)=default
A struct, containing the root of the expression tree.
size_t designateSubtrees(Node *node, size_t index=0)
std::unique_ptr< Node > node
An expression tree node corresponding to a literal value.
LiteralValue::stored_type var_t
std::unique_ptr< Node > condition
std::variant< LiteralNode, BindingNode, OpNode, PlaceholderNode, ConditionalNode > self_t
variant with possible nodes
std::unique_ptr< Node > right
Node(BindingNode const &n)
Node(OpNode op, Node &&l, Node &&r)
Node(ConditionalNode op, Node &&then_, Node &&else_, Node &&condition_)
std::unique_ptr< Node > left
pointers to children
An expression tree node corresponding to binary or unary operation.
A placeholder node for simple type configurable.
LiteralNode::var_t(* retrieve)(InitContext &, char const *)
PlaceholderNode(Configurable< T > const &v)
VectorOfTObjectPtrs other