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
6namespace duckdb {
7
8template <class T>
9bool 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
21template <class T, class EXPRESSION_MAP>
22bool 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
54bool ExpressionUtil::ListEquals(const vector<unique_ptr<ParsedExpression>> &a,
55 const vector<unique_ptr<ParsedExpression>> &b) {
56 return ExpressionListEquals<ParsedExpression>(a, b);
57}
58
59bool ExpressionUtil::ListEquals(const vector<unique_ptr<Expression>> &a, const vector<unique_ptr<Expression>> &b) {
60 return ExpressionListEquals<Expression>(a, b);
61}
62
63bool 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
68bool 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