]> git.proxmox.com Git - ceph.git/blame - ceph/src/arrow/cpp/src/gandiva/expr_decomposer_test.cc
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / cpp / src / gandiva / expr_decomposer_test.cc
CommitLineData
1d09f67e
TL
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/expr_decomposer.h"
19
20#include <gtest/gtest.h>
21
22#include "gandiva/annotator.h"
23#include "gandiva/dex.h"
24#include "gandiva/function_registry.h"
25#include "gandiva/gandiva_aliases.h"
26#include "gandiva/node.h"
27#include "gandiva/tree_expr_builder.h"
28
29namespace gandiva {
30
31using arrow::int32;
32
33class TestExprDecomposer : public ::testing::Test {
34 protected:
35 FunctionRegistry registry_;
36};
37
38TEST_F(TestExprDecomposer, TestStackSimple) {
39 Annotator annotator;
40 ExprDecomposer decomposer(registry_, annotator);
41
42 // if (a) _
43 // else _
44 IfNode node_a(nullptr, nullptr, nullptr, int32());
45
46 decomposer.PushConditionEntry(node_a);
47 decomposer.PopConditionEntry(node_a);
48
49 int idx_a = decomposer.PushThenEntry(node_a, false);
50 EXPECT_EQ(idx_a, 0);
51 decomposer.PopThenEntry(node_a);
52
53 decomposer.PushElseEntry(node_a, idx_a);
54 bool is_terminal_a = decomposer.PopElseEntry(node_a);
55 EXPECT_EQ(is_terminal_a, true);
56 EXPECT_EQ(decomposer.if_entries_stack_.empty(), true);
57}
58
59TEST_F(TestExprDecomposer, TestNested) {
60 Annotator annotator;
61 ExprDecomposer decomposer(registry_, annotator);
62
63 // if (a) _
64 // else _
65 // if (b) _
66 // else _
67 IfNode node_a(nullptr, nullptr, nullptr, int32());
68 IfNode node_b(nullptr, nullptr, nullptr, int32());
69
70 decomposer.PushConditionEntry(node_a);
71 decomposer.PopConditionEntry(node_a);
72
73 int idx_a = decomposer.PushThenEntry(node_a, false);
74 EXPECT_EQ(idx_a, 0);
75 decomposer.PopThenEntry(node_a);
76
77 decomposer.PushElseEntry(node_a, idx_a);
78
79 { // start b
80 decomposer.PushConditionEntry(node_b);
81 decomposer.PopConditionEntry(node_b);
82
83 int idx_b = decomposer.PushThenEntry(node_b, true);
84 EXPECT_EQ(idx_b, 0); // must reuse bitmap.
85 decomposer.PopThenEntry(node_b);
86
87 decomposer.PushElseEntry(node_b, idx_b);
88 bool is_terminal_b = decomposer.PopElseEntry(node_b);
89 EXPECT_EQ(is_terminal_b, true);
90 } // end b
91
92 bool is_terminal_a = decomposer.PopElseEntry(node_a);
93 EXPECT_EQ(is_terminal_a, false); // there was a nested if.
94
95 EXPECT_EQ(decomposer.if_entries_stack_.empty(), true);
96}
97
98TEST_F(TestExprDecomposer, TestInternalIf) {
99 Annotator annotator;
100 ExprDecomposer decomposer(registry_, annotator);
101
102 // if (a) _
103 // if (b) _
104 // else _
105 // else _
106 IfNode node_a(nullptr, nullptr, nullptr, int32());
107 IfNode node_b(nullptr, nullptr, nullptr, int32());
108
109 decomposer.PushConditionEntry(node_a);
110 decomposer.PopConditionEntry(node_a);
111
112 int idx_a = decomposer.PushThenEntry(node_a, false);
113 EXPECT_EQ(idx_a, 0);
114
115 { // start b
116 decomposer.PushConditionEntry(node_b);
117 decomposer.PopConditionEntry(node_b);
118
119 int idx_b = decomposer.PushThenEntry(node_b, false);
120 EXPECT_EQ(idx_b, 1); // must not reuse bitmap.
121 decomposer.PopThenEntry(node_b);
122
123 decomposer.PushElseEntry(node_b, idx_b);
124 bool is_terminal_b = decomposer.PopElseEntry(node_b);
125 EXPECT_EQ(is_terminal_b, true);
126 } // end b
127
128 decomposer.PopThenEntry(node_a);
129 decomposer.PushElseEntry(node_a, idx_a);
130
131 bool is_terminal_a = decomposer.PopElseEntry(node_a);
132 EXPECT_EQ(is_terminal_a, true); // there was no nested if.
133
134 EXPECT_EQ(decomposer.if_entries_stack_.empty(), true);
135}
136
137TEST_F(TestExprDecomposer, TestParallelIf) {
138 Annotator annotator;
139 ExprDecomposer decomposer(registry_, annotator);
140
141 // if (a) _
142 // else _
143 // if (b) _
144 // else _
145 IfNode node_a(nullptr, nullptr, nullptr, int32());
146 IfNode node_b(nullptr, nullptr, nullptr, int32());
147
148 decomposer.PushConditionEntry(node_a);
149 decomposer.PopConditionEntry(node_a);
150
151 int idx_a = decomposer.PushThenEntry(node_a, false);
152 EXPECT_EQ(idx_a, 0);
153
154 decomposer.PopThenEntry(node_a);
155 decomposer.PushElseEntry(node_a, idx_a);
156
157 bool is_terminal_a = decomposer.PopElseEntry(node_a);
158 EXPECT_EQ(is_terminal_a, true); // there was no nested if.
159
160 // start b
161 decomposer.PushConditionEntry(node_b);
162 decomposer.PopConditionEntry(node_b);
163
164 int idx_b = decomposer.PushThenEntry(node_b, false);
165 EXPECT_EQ(idx_b, 1); // must not reuse bitmap.
166 decomposer.PopThenEntry(node_b);
167
168 decomposer.PushElseEntry(node_b, idx_b);
169 bool is_terminal_b = decomposer.PopElseEntry(node_b);
170 EXPECT_EQ(is_terminal_b, true);
171
172 EXPECT_EQ(decomposer.if_entries_stack_.empty(), true);
173}
174
175TEST_F(TestExprDecomposer, TestIfInCondition) {
176 Annotator annotator;
177 ExprDecomposer decomposer(registry_, annotator);
178
179 // if (if _ else _) : a
180 // -
181 // else
182 // if (if _ else _) : b
183 // -
184 // else
185 // -
186 IfNode node_a(nullptr, nullptr, nullptr, int32());
187 IfNode node_b(nullptr, nullptr, nullptr, int32());
188 IfNode cond_node_a(nullptr, nullptr, nullptr, int32());
189 IfNode cond_node_b(nullptr, nullptr, nullptr, int32());
190
191 // start a
192 decomposer.PushConditionEntry(node_a);
193 {
194 // start cond_node_a
195 decomposer.PushConditionEntry(cond_node_a);
196 decomposer.PopConditionEntry(cond_node_a);
197
198 int idx_cond_a = decomposer.PushThenEntry(cond_node_a, false);
199 EXPECT_EQ(idx_cond_a, 0);
200 decomposer.PopThenEntry(cond_node_a);
201
202 decomposer.PushElseEntry(cond_node_a, idx_cond_a);
203 bool is_terminal = decomposer.PopElseEntry(cond_node_a);
204 EXPECT_EQ(is_terminal, true); // there was no nested if.
205 }
206 decomposer.PopConditionEntry(node_a);
207
208 int idx_a = decomposer.PushThenEntry(node_a, false);
209 EXPECT_EQ(idx_a, 1); // no re-use
210 decomposer.PopThenEntry(node_a);
211
212 decomposer.PushElseEntry(node_a, idx_a);
213
214 { // start b
215 decomposer.PushConditionEntry(node_b);
216 {
217 // start cond_node_b
218 decomposer.PushConditionEntry(cond_node_b);
219 decomposer.PopConditionEntry(cond_node_b);
220
221 int idx_cond_b = decomposer.PushThenEntry(cond_node_b, false);
222 EXPECT_EQ(idx_cond_b, 2); // no re-use
223 decomposer.PopThenEntry(cond_node_b);
224
225 decomposer.PushElseEntry(cond_node_b, idx_cond_b);
226 bool is_terminal = decomposer.PopElseEntry(cond_node_b);
227 EXPECT_EQ(is_terminal, true); // there was no nested if.
228 }
229 decomposer.PopConditionEntry(node_b);
230
231 int idx_b = decomposer.PushThenEntry(node_b, true);
232 EXPECT_EQ(idx_b, 1); // must reuse bitmap.
233 decomposer.PopThenEntry(node_b);
234
235 decomposer.PushElseEntry(node_b, idx_b);
236 bool is_terminal = decomposer.PopElseEntry(node_b);
237 EXPECT_EQ(is_terminal, true);
238 } // end b
239
240 bool is_terminal_a = decomposer.PopElseEntry(node_a);
241 EXPECT_EQ(is_terminal_a, false); // there was a nested if.
242
243 EXPECT_EQ(decomposer.if_entries_stack_.empty(), true);
244}
245
246TEST_F(TestExprDecomposer, TestFunctionBetweenNestedIf) {
247 Annotator annotator;
248 ExprDecomposer decomposer(registry_, annotator);
249
250 // if (a) _
251 // else
252 // function(
253 // if (b) _
254 // else _
255 // )
256
257 IfNode node_a(nullptr, nullptr, nullptr, int32());
258 IfNode node_b(nullptr, nullptr, nullptr, int32());
259
260 // start outer if
261 decomposer.PushConditionEntry(node_a);
262 decomposer.PopConditionEntry(node_a);
263
264 int idx_a = decomposer.PushThenEntry(node_a, false);
265 EXPECT_EQ(idx_a, 0);
266 decomposer.PopThenEntry(node_a);
267
268 decomposer.PushElseEntry(node_a, idx_a);
269 { // start b
270 decomposer.PushConditionEntry(node_b);
271 decomposer.PopConditionEntry(node_b);
272
273 int idx_b = decomposer.PushThenEntry(node_b, false); // not else node of parent if
274 EXPECT_EQ(idx_b, 1); // can't reuse bitmap.
275 decomposer.PopThenEntry(node_b);
276
277 decomposer.PushElseEntry(node_b, idx_b);
278 bool is_terminal_b = decomposer.PopElseEntry(node_b);
279 EXPECT_EQ(is_terminal_b, true);
280 }
281 bool is_terminal_a = decomposer.PopElseEntry(node_a);
282 EXPECT_EQ(is_terminal_a, true); // a else is also terminal
283
284 EXPECT_TRUE(decomposer.if_entries_stack_.empty());
285}
286
287TEST_F(TestExprDecomposer, TestComplexIfCondition) {
288 Annotator annotator;
289 ExprDecomposer decomposer(registry_, annotator);
290
291 // if (if _
292 // else
293 // if _
294 // else _
295 // )
296 // then
297 // if _
298 // else
299 // if _
300 // else _
301 //
302 // else
303 // if _
304 // else
305 // if _
306 // else _
307
308 IfNode node_a(nullptr, nullptr, nullptr, int32());
309
310 IfNode cond_node_a(nullptr, nullptr, nullptr, int32());
311 IfNode cond_node_a_inner_if(nullptr, nullptr, nullptr, int32());
312
313 IfNode then_node_a(nullptr, nullptr, nullptr, int32());
314 IfNode then_node_a_inner_if(nullptr, nullptr, nullptr, int32());
315
316 IfNode else_node_a(nullptr, nullptr, nullptr, int32());
317 IfNode else_node_a_inner_if(nullptr, nullptr, nullptr, int32());
318
319 // start outer if
320 decomposer.PushConditionEntry(node_a);
321 {
322 // start the nested if inside the condition of a
323 decomposer.PushConditionEntry(cond_node_a);
324 decomposer.PopConditionEntry(cond_node_a);
325
326 int idx_cond_a = decomposer.PushThenEntry(cond_node_a, false);
327 EXPECT_EQ(idx_cond_a, 0);
328 decomposer.PopThenEntry(cond_node_a);
329
330 decomposer.PushElseEntry(cond_node_a, idx_cond_a);
331 {
332 decomposer.PushConditionEntry(cond_node_a_inner_if);
333 decomposer.PopConditionEntry(cond_node_a_inner_if);
334
335 int idx_cond_a_inner_if = decomposer.PushThenEntry(cond_node_a_inner_if, true);
336 EXPECT_EQ(idx_cond_a_inner_if,
337 0); // expect bitmap to be resused since nested if else
338 decomposer.PopThenEntry(cond_node_a_inner_if);
339
340 decomposer.PushElseEntry(cond_node_a_inner_if, idx_cond_a_inner_if);
341 bool is_terminal = decomposer.PopElseEntry(cond_node_a_inner_if);
342 EXPECT_TRUE(is_terminal);
343 }
344 EXPECT_FALSE(decomposer.PopElseEntry(cond_node_a));
345 }
346 decomposer.PopConditionEntry(node_a);
347
348 int idx_a = decomposer.PushThenEntry(node_a, false);
349 EXPECT_EQ(idx_a, 1);
350
351 {
352 // start the nested if inside the then node of a
353 decomposer.PushConditionEntry(then_node_a);
354 decomposer.PopConditionEntry(then_node_a);
355
356 int idx_then_a = decomposer.PushThenEntry(then_node_a, false);
357 EXPECT_EQ(idx_then_a, 2);
358 decomposer.PopThenEntry(then_node_a);
359
360 decomposer.PushElseEntry(then_node_a, idx_then_a);
361 {
362 decomposer.PushConditionEntry(then_node_a_inner_if);
363 decomposer.PopConditionEntry(then_node_a_inner_if);
364
365 int idx_then_a_inner_if = decomposer.PushThenEntry(then_node_a_inner_if, true);
366 EXPECT_EQ(idx_then_a_inner_if,
367 2); // expect bitmap to be resused since nested if else
368 decomposer.PopThenEntry(then_node_a_inner_if);
369
370 decomposer.PushElseEntry(then_node_a_inner_if, idx_then_a_inner_if);
371 bool is_terminal = decomposer.PopElseEntry(then_node_a_inner_if);
372 EXPECT_TRUE(is_terminal);
373 }
374 EXPECT_FALSE(decomposer.PopElseEntry(then_node_a));
375 }
376 decomposer.PopThenEntry(node_a);
377
378 decomposer.PushElseEntry(node_a, idx_a);
379 {
380 // start the nested if inside the else node of a
381 decomposer.PushConditionEntry(else_node_a);
382 decomposer.PopConditionEntry(else_node_a);
383
384 int idx_else_a =
385 decomposer.PushThenEntry(else_node_a, true); // else node is another if-node
386 EXPECT_EQ(idx_else_a, 1); // reuse the outer if node bitmap since nested if-else
387 decomposer.PopThenEntry(else_node_a);
388
389 decomposer.PushElseEntry(else_node_a, idx_else_a);
390 {
391 decomposer.PushConditionEntry(else_node_a_inner_if);
392 decomposer.PopConditionEntry(else_node_a_inner_if);
393
394 int idx_else_a_inner_if = decomposer.PushThenEntry(else_node_a_inner_if, true);
395 EXPECT_EQ(idx_else_a_inner_if,
396 1); // expect bitmap to be resused since nested if else
397 decomposer.PopThenEntry(else_node_a_inner_if);
398
399 decomposer.PushElseEntry(else_node_a_inner_if, idx_else_a_inner_if);
400 bool is_terminal = decomposer.PopElseEntry(else_node_a_inner_if);
401 EXPECT_TRUE(is_terminal);
402 }
403 EXPECT_FALSE(decomposer.PopElseEntry(else_node_a));
404 }
405 EXPECT_FALSE(decomposer.PopElseEntry(node_a));
406 EXPECT_TRUE(decomposer.if_entries_stack_.empty());
407}
408
409} // namespace gandiva