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
6using namespace duckdb;
7using namespace std;
8
9template <class T>
10bool 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
22template <class T>
23bool 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
55bool ExpressionUtil::ListEquals(const vector<unique_ptr<ParsedExpression>> &a,
56 const vector<unique_ptr<ParsedExpression>> &b) {
57 return ExpressionListEquals<ParsedExpression>(a, b);
58}
59
60bool ExpressionUtil::ListEquals(const vector<unique_ptr<Expression>> &a, const vector<unique_ptr<Expression>> &b) {
61 return ExpressionListEquals<Expression>(a, b);
62}
63
64bool ExpressionUtil::SetEquals(const vector<unique_ptr<ParsedExpression>> &a,
65 const vector<unique_ptr<ParsedExpression>> &b) {
66 return ExpressionSetEquals<ParsedExpression>(a, b);
67}
68
69bool ExpressionUtil::SetEquals(const vector<unique_ptr<Expression>> &a, const vector<unique_ptr<Expression>> &b) {
70 return ExpressionSetEquals<Expression>(a, b);
71}
72