1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements.  See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership.  The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License.  You may obtain a copy of the License at
8 //
9 //   http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing,
12 // software distributed under the License is distributed on an
13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, either express or implied.  See the License for the
15 // specific language governing permissions and limitations
16 // under the License.
17 
18 #include "gandiva/tree_expr_builder.h"
19 
20 #include <iostream>
21 #include <utility>
22 
23 #include "gandiva/decimal_type_util.h"
24 #include "gandiva/gandiva_aliases.h"
25 #include "gandiva/node.h"
26 
27 namespace gandiva {
28 
29 #define MAKE_LITERAL(atype, ctype)                                            \
30   NodePtr TreeExprBuilder::MakeLiteral(ctype value) {                         \
31     return std::make_shared<LiteralNode>(atype, LiteralHolder(value), false); \
32   }
33 
MAKE_LITERAL(arrow::boolean (),bool)34 MAKE_LITERAL(arrow::boolean(), bool)
35 MAKE_LITERAL(arrow::int8(), int8_t)
36 MAKE_LITERAL(arrow::int16(), int16_t)
37 MAKE_LITERAL(arrow::int32(), int32_t)
38 MAKE_LITERAL(arrow::int64(), int64_t)
39 MAKE_LITERAL(arrow::uint8(), uint8_t)
40 MAKE_LITERAL(arrow::uint16(), uint16_t)
41 MAKE_LITERAL(arrow::uint32(), uint32_t)
42 MAKE_LITERAL(arrow::uint64(), uint64_t)
43 MAKE_LITERAL(arrow::float32(), float)
44 MAKE_LITERAL(arrow::float64(), double)
45 
46 NodePtr TreeExprBuilder::MakeStringLiteral(const std::string& value) {
47   return std::make_shared<LiteralNode>(arrow::utf8(), LiteralHolder(value), false);
48 }
49 
MakeBinaryLiteral(const std::string & value)50 NodePtr TreeExprBuilder::MakeBinaryLiteral(const std::string& value) {
51   return std::make_shared<LiteralNode>(arrow::binary(), LiteralHolder(value), false);
52 }
53 
MakeDecimalLiteral(const DecimalScalar128 & value)54 NodePtr TreeExprBuilder::MakeDecimalLiteral(const DecimalScalar128& value) {
55   return std::make_shared<LiteralNode>(arrow::decimal(value.precision(), value.scale()),
56                                        LiteralHolder(value), false);
57 }
58 
MakeNull(DataTypePtr data_type)59 NodePtr TreeExprBuilder::MakeNull(DataTypePtr data_type) {
60   static const std::string empty;
61 
62   if (data_type == nullptr) {
63     return nullptr;
64   }
65 
66   switch (data_type->id()) {
67     case arrow::Type::BOOL:
68       return std::make_shared<LiteralNode>(data_type, LiteralHolder(false), true);
69     case arrow::Type::INT8:
70       return std::make_shared<LiteralNode>(data_type, LiteralHolder((int8_t)0), true);
71     case arrow::Type::INT16:
72       return std::make_shared<LiteralNode>(data_type, LiteralHolder((int16_t)0), true);
73       return std::make_shared<LiteralNode>(data_type, LiteralHolder((int32_t)0), true);
74     case arrow::Type::UINT8:
75       return std::make_shared<LiteralNode>(data_type, LiteralHolder((uint8_t)0), true);
76     case arrow::Type::UINT16:
77       return std::make_shared<LiteralNode>(data_type, LiteralHolder((uint16_t)0), true);
78     case arrow::Type::UINT32:
79       return std::make_shared<LiteralNode>(data_type, LiteralHolder((uint32_t)0), true);
80     case arrow::Type::UINT64:
81       return std::make_shared<LiteralNode>(data_type, LiteralHolder((uint64_t)0), true);
82     case arrow::Type::FLOAT:
83       return std::make_shared<LiteralNode>(data_type,
84                                            LiteralHolder(static_cast<float>(0)), true);
85     case arrow::Type::DOUBLE:
86       return std::make_shared<LiteralNode>(data_type,
87                                            LiteralHolder(static_cast<double>(0)), true);
88     case arrow::Type::STRING:
89     case arrow::Type::BINARY:
90       return std::make_shared<LiteralNode>(data_type, LiteralHolder(empty), true);
91     case arrow::Type::INT32:
92     case arrow::Type::DATE32:
93     case arrow::Type::TIME32:
94     case arrow::Type::INTERVAL_MONTHS:
95       return std::make_shared<LiteralNode>(data_type, LiteralHolder((int32_t)0), true);
96     case arrow::Type::INT64:
97     case arrow::Type::DATE64:
98     case arrow::Type::TIME64:
99     case arrow::Type::TIMESTAMP:
100     case arrow::Type::INTERVAL_DAY_TIME:
101       return std::make_shared<LiteralNode>(data_type, LiteralHolder((int64_t)0), true);
102     case arrow::Type::DECIMAL: {
103       std::shared_ptr<arrow::DecimalType> decimal_type =
104           arrow::internal::checked_pointer_cast<arrow::DecimalType>(data_type);
105       DecimalScalar128 literal(decimal_type->precision(), decimal_type->scale());
106       return std::make_shared<LiteralNode>(data_type, LiteralHolder(literal), true);
107     }
108     default:
109       return nullptr;
110   }
111 }
112 
MakeField(FieldPtr field)113 NodePtr TreeExprBuilder::MakeField(FieldPtr field) {
114   return NodePtr(new FieldNode(field));
115 }
116 
MakeFunction(const std::string & name,const NodeVector & params,DataTypePtr result_type)117 NodePtr TreeExprBuilder::MakeFunction(const std::string& name, const NodeVector& params,
118                                       DataTypePtr result_type) {
119   if (result_type == nullptr) {
120     return nullptr;
121   }
122   return std::make_shared<FunctionNode>(name, params, result_type);
123 }
124 
MakeIf(NodePtr condition,NodePtr then_node,NodePtr else_node,DataTypePtr result_type)125 NodePtr TreeExprBuilder::MakeIf(NodePtr condition, NodePtr then_node, NodePtr else_node,
126                                 DataTypePtr result_type) {
127   if (condition == nullptr || then_node == nullptr || else_node == nullptr ||
128       result_type == nullptr) {
129     return nullptr;
130   }
131   return std::make_shared<IfNode>(condition, then_node, else_node, result_type);
132 }
133 
MakeAnd(const NodeVector & children)134 NodePtr TreeExprBuilder::MakeAnd(const NodeVector& children) {
135   return std::make_shared<BooleanNode>(BooleanNode::AND, children);
136 }
137 
MakeOr(const NodeVector & children)138 NodePtr TreeExprBuilder::MakeOr(const NodeVector& children) {
139   return std::make_shared<BooleanNode>(BooleanNode::OR, children);
140 }
141 
142 // set this to true to print expressions for debugging purposes
143 static bool print_expr = false;
144 
MakeExpression(NodePtr root_node,FieldPtr result_field)145 ExpressionPtr TreeExprBuilder::MakeExpression(NodePtr root_node, FieldPtr result_field) {
146   if (result_field == nullptr) {
147     return nullptr;
148   }
149   if (print_expr) {
150     std::cout << "Expression: " << root_node->ToString() << "\n";
151   }
152   return ExpressionPtr(new Expression(root_node, result_field));
153 }
154 
MakeExpression(const std::string & function,const FieldVector & in_fields,FieldPtr out_field)155 ExpressionPtr TreeExprBuilder::MakeExpression(const std::string& function,
156                                               const FieldVector& in_fields,
157                                               FieldPtr out_field) {
158   if (out_field == nullptr) {
159     return nullptr;
160   }
161   std::vector<NodePtr> field_nodes;
162   for (auto& field : in_fields) {
163     auto node = MakeField(field);
164     field_nodes.push_back(node);
165   }
166   auto func_node = MakeFunction(function, field_nodes, out_field->type());
167   return MakeExpression(func_node, out_field);
168 }
169 
MakeCondition(NodePtr root_node)170 ConditionPtr TreeExprBuilder::MakeCondition(NodePtr root_node) {
171   if (root_node == nullptr) {
172     return nullptr;
173   }
174   if (print_expr) {
175     std::cout << "Condition: " << root_node->ToString() << "\n";
176   }
177 
178   return ConditionPtr(new Condition(root_node));
179 }
180 
MakeCondition(const std::string & function,const FieldVector & in_fields)181 ConditionPtr TreeExprBuilder::MakeCondition(const std::string& function,
182                                             const FieldVector& in_fields) {
183   std::vector<NodePtr> field_nodes;
184   for (auto& field : in_fields) {
185     auto node = MakeField(field);
186     field_nodes.push_back(node);
187   }
188 
189   auto func_node = MakeFunction(function, field_nodes, arrow::boolean());
190   return ConditionPtr(new Condition(func_node));
191 }
192 
MakeInExpressionDecimal(NodePtr node,std::unordered_set<gandiva::DecimalScalar128> & constants)193 NodePtr TreeExprBuilder::MakeInExpressionDecimal(
194     NodePtr node, std::unordered_set<gandiva::DecimalScalar128>& constants) {
195   int32_t precision = 0;
196   int32_t scale = 0;
197   if (!constants.empty()) {
198     precision = constants.begin()->precision();
199     scale = constants.begin()->scale();
200   }
201   return std::make_shared<InExpressionNode<gandiva::DecimalScalar128>>(node, constants,
202                                                                        precision, scale);
203 }
204 
205 #define MAKE_IN(NAME, ctype)                                        \
206   NodePtr TreeExprBuilder::MakeInExpression##NAME(                  \
207       NodePtr node, const std::unordered_set<ctype>& values) {      \
208     return std::make_shared<InExpressionNode<ctype>>(node, values); \
209   }
210 
211 MAKE_IN(Int32, int32_t);
212 MAKE_IN(Int64, int64_t);
213 MAKE_IN(Date32, int32_t);
214 MAKE_IN(Date64, int64_t);
215 MAKE_IN(TimeStamp, int64_t);
216 MAKE_IN(Time32, int32_t);
217 MAKE_IN(Time64, int64_t);
218 MAKE_IN(Float, float);
219 MAKE_IN(Double, double);
220 MAKE_IN(String, std::string);
221 MAKE_IN(Binary, std::string);
222 
223 }  // namespace gandiva
224