1 | #include "catch.hpp" |
2 | #include "duckdb/common/helper.hpp" |
3 | #include "duckdb/planner/expression/bound_operator_expression.hpp" |
4 | #include "duckdb/optimizer/rule/empty_needle_removal.hpp" |
5 | #include "duckdb/optimizer/rule/constant_folding.hpp" |
6 | #include "duckdb/execution/expression_executor.hpp" |
7 | #include "expression_helper.hpp" |
8 | |
9 | using namespace duckdb; |
10 | using namespace std; |
11 | |
12 | static void require_case(ExpressionHelper &helper, string input) { |
13 | auto root = helper.ParseExpression(input); |
14 | auto result = helper.ApplyExpressionRule(move(root)); |
15 | REQUIRE(result->type == ExpressionType::CASE_EXPR); |
16 | } |
17 | |
18 | static void require_constant(ExpressionHelper &helper, string input, Value constant) { |
19 | auto root = helper.ParseExpression(input); |
20 | auto result = helper.ApplyExpressionRule(move(root)); |
21 | REQUIRE(result->IsFoldable()); |
22 | auto result_value = ExpressionExecutor::EvaluateScalar(*result); |
23 | REQUIRE(((constant.is_null && result_value.is_null) || constant == result_value)); |
24 | } |
25 | |
26 | TEST_CASE("Test Empty Needle Optimization Rules" , "[needle-optimizer]" ) { |
27 | ExpressionHelper helper; |
28 | |
29 | REQUIRE(helper.AddColumns("S VARCHAR" ).empty()); |
30 | |
31 | helper.AddRule<EmptyNeedleRemovalRule>(); |
32 | helper.AddRule<ConstantFoldingRule>(); |
33 | |
34 | string input, expected_output; |
35 | |
36 | require_case(helper, "PREFIX(S, '')" ); |
37 | require_case(helper, "CONTAINS(S, '')" ); |
38 | require_case(helper, "SUFFIX(S, '')" ); |
39 | |
40 | require_constant(helper, "PREFIX(S, NULL)" , Value()); |
41 | require_constant(helper, "PREFIX('', NULL)" , Value()); |
42 | require_constant(helper, "PREFIX(NULL, NULL)" , Value()); |
43 | require_constant(helper, "PREFIX(NULL, '')" , Value()); |
44 | |
45 | require_constant(helper, "PREFIX('asdf', '')" , Value::BOOLEAN(true)); |
46 | require_constant(helper, "PREFIX('', '')" , Value::BOOLEAN(true)); |
47 | |
48 | require_constant(helper, "CONTAINS(S, NULL)" , Value()); |
49 | require_constant(helper, "CONTAINS('', NULL)" , Value()); |
50 | require_constant(helper, "CONTAINS(NULL, NULL)" , Value()); |
51 | require_constant(helper, "CONTAINS(NULL, '')" , Value()); |
52 | |
53 | require_constant(helper, "CONTAINS('asdf', '')" , Value::BOOLEAN(true)); |
54 | require_constant(helper, "CONTAINS('', '')" , Value::BOOLEAN(true)); |
55 | |
56 | require_constant(helper, "SUFFIX(S, NULL)" , Value()); |
57 | require_constant(helper, "SUFFIX('', NULL)" , Value()); |
58 | require_constant(helper, "SUFFIX(NULL, NULL)" , Value()); |
59 | require_constant(helper, "SUFFIX(NULL, '')" , Value()); |
60 | |
61 | require_constant(helper, "SUFFIX('asdf', '')" , Value::BOOLEAN(true)); |
62 | require_constant(helper, "SUFFIX('', '')" , Value::BOOLEAN(true)); |
63 | |
64 | // REQUIRE_FAIL ---------------- |
65 | input = "PREFIX(S, ' ')" ; |
66 | REQUIRE(helper.VerifyRewrite(input, input)); |
67 | |
68 | input = "PREFIX(S, 'a')" ; |
69 | REQUIRE(helper.VerifyRewrite(input, input)); |
70 | |
71 | input = "CONTAINS(S, ' ')" ; |
72 | REQUIRE(helper.VerifyRewrite(input, input)); |
73 | |
74 | input = "CONTAINS(S, 'a')" ; |
75 | REQUIRE(helper.VerifyRewrite(input, input)); |
76 | |
77 | input = "SUFFIX(S, ' ')" ; |
78 | REQUIRE(helper.VerifyRewrite(input, input)); |
79 | |
80 | input = "SUFFIX(S, 'a')" ; |
81 | REQUIRE(helper.VerifyRewrite(input, input)); |
82 | } |
83 | |