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