1 | #include "duckdb/parser/expression_util.hpp" |
2 | #include "duckdb/planner/expression.hpp" |
3 | #include "duckdb/parser/parsed_expression.hpp" |
4 | #include "duckdb/parser/expression_map.hpp" |
5 | |
6 | namespace duckdb { |
7 | |
8 | template <class T> |
9 | bool ExpressionUtil::ExpressionListEquals(const vector<unique_ptr<T>> &a, const vector<unique_ptr<T>> &b) { |
10 | if (a.size() != b.size()) { |
11 | return false; |
12 | } |
13 | for (idx_t i = 0; i < a.size(); i++) { |
14 | if (!(*a[i] == *b[i])) { |
15 | return false; |
16 | } |
17 | } |
18 | return true; |
19 | } |
20 | |
21 | template <class T, class EXPRESSION_MAP> |
22 | bool ExpressionUtil::ExpressionSetEquals(const vector<unique_ptr<T>> &a, const vector<unique_ptr<T>> &b) { |
23 | if (a.size() != b.size()) { |
24 | return false; |
25 | } |
26 | // we create a map of expression -> count for the left side |
27 | // we keep the count because the same expression can occur multiple times (e.g. "1 AND 1" is legal) |
28 | // in this case we track the following value: map["Constant(1)"] = 2 |
29 | EXPRESSION_MAP map; |
30 | for (idx_t i = 0; i < a.size(); i++) { |
31 | map[*a[i]]++; |
32 | } |
33 | // now on the right side we reduce the counts again |
34 | // if the conjunctions are identical, all the counts will be 0 after the |
35 | for (auto &expr : b) { |
36 | auto entry = map.find(*expr); |
37 | // first we check if we can find the expression in the map at all |
38 | if (entry == map.end()) { |
39 | return false; |
40 | } |
41 | // if we found it we check the count; if the count is already 0 we return false |
42 | // this happens if e.g. the left side contains "1 AND X", and the right side contains "1 AND 1" |
43 | // "1" is contained in the map, however, the right side contains the expression twice |
44 | // hence we know the children are not identical in this case because the LHS and RHS have a different count for |
45 | // the Constant(1) expression |
46 | if (entry->second == 0) { |
47 | return false; |
48 | } |
49 | entry->second--; |
50 | } |
51 | return true; |
52 | } |
53 | |
54 | bool ExpressionUtil::ListEquals(const vector<unique_ptr<ParsedExpression>> &a, |
55 | const vector<unique_ptr<ParsedExpression>> &b) { |
56 | return ExpressionListEquals<ParsedExpression>(a, b); |
57 | } |
58 | |
59 | bool ExpressionUtil::ListEquals(const vector<unique_ptr<Expression>> &a, const vector<unique_ptr<Expression>> &b) { |
60 | return ExpressionListEquals<Expression>(a, b); |
61 | } |
62 | |
63 | bool ExpressionUtil::SetEquals(const vector<unique_ptr<ParsedExpression>> &a, |
64 | const vector<unique_ptr<ParsedExpression>> &b) { |
65 | return ExpressionSetEquals<ParsedExpression, parsed_expression_map_t<idx_t>>(a, b); |
66 | } |
67 | |
68 | bool ExpressionUtil::SetEquals(const vector<unique_ptr<Expression>> &a, const vector<unique_ptr<Expression>> &b) { |
69 | return ExpressionSetEquals<Expression, expression_map_t<idx_t>>(a, b); |
70 | } |
71 | |
72 | } // namespace duckdb |
73 | |