1 | #include "duckdb/optimizer/matcher/expression_matcher.hpp" |
2 | |
3 | #include "duckdb/planner/expression/list.hpp" |
4 | |
5 | namespace duckdb { |
6 | |
7 | bool ExpressionMatcher::Match(Expression &expr, vector<reference<Expression>> &bindings) { |
8 | if (type && !type->Match(type: expr.return_type)) { |
9 | return false; |
10 | } |
11 | if (expr_type && !expr_type->Match(type: expr.type)) { |
12 | return false; |
13 | } |
14 | if (expr_class != ExpressionClass::INVALID && expr_class != expr.GetExpressionClass()) { |
15 | return false; |
16 | } |
17 | bindings.push_back(x: expr); |
18 | return true; |
19 | } |
20 | |
21 | bool ExpressionEqualityMatcher::Match(Expression &expr, vector<reference<Expression>> &bindings) { |
22 | if (!expr.Equals(other: expression)) { |
23 | return false; |
24 | } |
25 | bindings.push_back(x: expr); |
26 | return true; |
27 | } |
28 | |
29 | bool CaseExpressionMatcher::Match(Expression &expr_p, vector<reference<Expression>> &bindings) { |
30 | if (!ExpressionMatcher::Match(expr&: expr_p, bindings)) { |
31 | return false; |
32 | } |
33 | return true; |
34 | } |
35 | |
36 | bool ComparisonExpressionMatcher::Match(Expression &expr_p, vector<reference<Expression>> &bindings) { |
37 | if (!ExpressionMatcher::Match(expr&: expr_p, bindings)) { |
38 | return false; |
39 | } |
40 | auto &expr = expr_p.Cast<BoundComparisonExpression>(); |
41 | vector<reference<Expression>> expressions; |
42 | expressions.push_back(x: *expr.left); |
43 | expressions.push_back(x: *expr.right); |
44 | return SetMatcher::Match(matchers, entries&: expressions, bindings, policy); |
45 | } |
46 | |
47 | bool CastExpressionMatcher::Match(Expression &expr_p, vector<reference<Expression>> &bindings) { |
48 | if (!ExpressionMatcher::Match(expr&: expr_p, bindings)) { |
49 | return false; |
50 | } |
51 | if (!matcher) { |
52 | return true; |
53 | } |
54 | auto &expr = expr_p.Cast<BoundCastExpression>(); |
55 | return matcher->Match(expr&: *expr.child, bindings); |
56 | } |
57 | |
58 | bool InClauseExpressionMatcher::Match(Expression &expr_p, vector<reference<Expression>> &bindings) { |
59 | if (!ExpressionMatcher::Match(expr&: expr_p, bindings)) { |
60 | return false; |
61 | } |
62 | auto &expr = expr_p.Cast<BoundOperatorExpression>(); |
63 | if (expr.type != ExpressionType::COMPARE_IN || expr.type == ExpressionType::COMPARE_NOT_IN) { |
64 | return false; |
65 | } |
66 | return SetMatcher::Match(matchers, entries&: expr.children, bindings, policy); |
67 | } |
68 | |
69 | bool ConjunctionExpressionMatcher::Match(Expression &expr_p, vector<reference<Expression>> &bindings) { |
70 | if (!ExpressionMatcher::Match(expr&: expr_p, bindings)) { |
71 | return false; |
72 | } |
73 | auto &expr = expr_p.Cast<BoundConjunctionExpression>(); |
74 | if (!SetMatcher::Match(matchers, entries&: expr.children, bindings, policy)) { |
75 | return false; |
76 | } |
77 | return true; |
78 | } |
79 | |
80 | bool FunctionExpressionMatcher::Match(Expression &expr_p, vector<reference<Expression>> &bindings) { |
81 | if (!ExpressionMatcher::Match(expr&: expr_p, bindings)) { |
82 | return false; |
83 | } |
84 | auto &expr = expr_p.Cast<BoundFunctionExpression>(); |
85 | if (!FunctionMatcher::Match(matcher&: function, name&: expr.function.name)) { |
86 | return false; |
87 | } |
88 | if (!SetMatcher::Match(matchers, entries&: expr.children, bindings, policy)) { |
89 | return false; |
90 | } |
91 | return true; |
92 | } |
93 | |
94 | bool FoldableConstantMatcher::Match(Expression &expr, vector<reference<Expression>> &bindings) { |
95 | // we match on ANY expression that is a scalar expression |
96 | if (!expr.IsFoldable()) { |
97 | return false; |
98 | } |
99 | bindings.push_back(x: expr); |
100 | return true; |
101 | } |
102 | |
103 | } // namespace duckdb |
104 | |