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 <gtest/gtest.h>
21 #include "gandiva/annotator.h"
22 #include "gandiva/dex.h"
23 #include "gandiva/expr_decomposer.h"
24 #include "gandiva/function_registry.h"
25 #include "gandiva/function_signature.h"
26 #include "gandiva/gandiva_aliases.h"
27 #include "gandiva/node.h"
28
29 namespace gandiva {
30
31 using arrow::boolean;
32 using arrow::int32;
33
34 class TestExprTree : public ::testing::Test {
35 public:
SetUp()36 void SetUp() {
37 i0_ = field("i0", int32());
38 i1_ = field("i1", int32());
39
40 b0_ = field("b0", boolean());
41 }
42
43 protected:
44 FieldPtr i0_; // int32
45 FieldPtr i1_; // int32
46
47 FieldPtr b0_; // bool
48 FunctionRegistry registry_;
49 };
50
TEST_F(TestExprTree,TestField)51 TEST_F(TestExprTree, TestField) {
52 Annotator annotator;
53
54 auto n0 = TreeExprBuilder::MakeField(i0_);
55 EXPECT_EQ(n0->return_type(), int32());
56
57 auto n1 = TreeExprBuilder::MakeField(b0_);
58 EXPECT_EQ(n1->return_type(), boolean());
59
60 ExprDecomposer decomposer(registry_, annotator);
61 ValueValidityPairPtr pair;
62 auto status = decomposer.Decompose(*n1, &pair);
63 DCHECK_EQ(status.ok(), true) << status.message();
64
65 auto value = pair->value_expr();
66 auto value_dex = std::dynamic_pointer_cast<VectorReadFixedLenValueDex>(value);
67 EXPECT_EQ(value_dex->FieldType(), boolean());
68
69 EXPECT_EQ(pair->validity_exprs().size(), 1);
70 auto validity = pair->validity_exprs().at(0);
71 auto validity_dex = std::dynamic_pointer_cast<VectorReadValidityDex>(validity);
72 EXPECT_NE(validity_dex->ValidityIdx(), value_dex->DataIdx());
73 }
74
TEST_F(TestExprTree,TestBinary)75 TEST_F(TestExprTree, TestBinary) {
76 Annotator annotator;
77
78 auto left = TreeExprBuilder::MakeField(i0_);
79 auto right = TreeExprBuilder::MakeField(i1_);
80
81 auto n = TreeExprBuilder::MakeFunction("add", {left, right}, int32());
82 auto add = std::dynamic_pointer_cast<FunctionNode>(n);
83
84 auto func_desc = add->descriptor();
85 FunctionSignature sign(func_desc->name(), func_desc->params(),
86 func_desc->return_type());
87
88 EXPECT_EQ(add->return_type(), int32());
89 EXPECT_TRUE(sign == FunctionSignature("add", {int32(), int32()}, int32()));
90
91 ExprDecomposer decomposer(registry_, annotator);
92 ValueValidityPairPtr pair;
93 auto status = decomposer.Decompose(*n, &pair);
94 DCHECK_EQ(status.ok(), true) << status.message();
95
96 auto value = pair->value_expr();
97 auto null_if_null = std::dynamic_pointer_cast<NonNullableFuncDex>(value);
98
99 FunctionSignature signature("add", {int32(), int32()}, int32());
100 const NativeFunction* fn = registry_.LookupSignature(signature);
101 EXPECT_EQ(null_if_null->native_function(), fn);
102 }
103
TEST_F(TestExprTree,TestUnary)104 TEST_F(TestExprTree, TestUnary) {
105 Annotator annotator;
106
107 auto arg = TreeExprBuilder::MakeField(i0_);
108 auto n = TreeExprBuilder::MakeFunction("isnumeric", {arg}, boolean());
109
110 auto unaryFn = std::dynamic_pointer_cast<FunctionNode>(n);
111 auto func_desc = unaryFn->descriptor();
112 FunctionSignature sign(func_desc->name(), func_desc->params(),
113 func_desc->return_type());
114 EXPECT_EQ(unaryFn->return_type(), boolean());
115 EXPECT_TRUE(sign == FunctionSignature("isnumeric", {int32()}, boolean()));
116
117 ExprDecomposer decomposer(registry_, annotator);
118 ValueValidityPairPtr pair;
119 auto status = decomposer.Decompose(*n, &pair);
120 DCHECK_EQ(status.ok(), true) << status.message();
121
122 auto value = pair->value_expr();
123 auto never_null = std::dynamic_pointer_cast<NullableNeverFuncDex>(value);
124
125 FunctionSignature signature("isnumeric", {int32()}, boolean());
126 const NativeFunction* fn = registry_.LookupSignature(signature);
127 EXPECT_EQ(never_null->native_function(), fn);
128 }
129
TEST_F(TestExprTree,TestExpression)130 TEST_F(TestExprTree, TestExpression) {
131 Annotator annotator;
132 auto left = TreeExprBuilder::MakeField(i0_);
133 auto right = TreeExprBuilder::MakeField(i1_);
134
135 auto n = TreeExprBuilder::MakeFunction("add", {left, right}, int32());
136 auto e = TreeExprBuilder::MakeExpression(n, field("r", int32()));
137 auto root_node = e->root();
138 EXPECT_EQ(root_node->return_type(), int32());
139
140 auto add_node = std::dynamic_pointer_cast<FunctionNode>(root_node);
141 auto func_desc = add_node->descriptor();
142 FunctionSignature sign(func_desc->name(), func_desc->params(),
143 func_desc->return_type());
144 EXPECT_TRUE(sign == FunctionSignature("add", {int32(), int32()}, int32()));
145
146 ExprDecomposer decomposer(registry_, annotator);
147 ValueValidityPairPtr pair;
148 auto status = decomposer.Decompose(*root_node, &pair);
149 DCHECK_EQ(status.ok(), true) << status.message();
150
151 auto value = pair->value_expr();
152 auto null_if_null = std::dynamic_pointer_cast<NonNullableFuncDex>(value);
153
154 FunctionSignature signature("add", {int32(), int32()}, int32());
155 const NativeFunction* fn = registry_.LookupSignature(signature);
156 EXPECT_EQ(null_if_null->native_function(), fn);
157 }
158
159 } // namespace gandiva
160