1#include "duckdb/optimizer/expression_rewriter.hpp"
2
3#include "duckdb/common/exception.hpp"
4#include "duckdb/planner/expression_iterator.hpp"
5#include "duckdb/planner/operator/logical_filter.hpp"
6
7using namespace duckdb;
8using namespace std;
9
10unique_ptr<Expression> ExpressionRewriter::ApplyRules(LogicalOperator &op, const vector<Rule *> &rules,
11 unique_ptr<Expression> expr, bool &changes_made) {
12 for (auto &rule : rules) {
13 vector<Expression *> bindings;
14 if (rule->root->Match(expr.get(), bindings)) {
15 // the rule matches! try to apply it
16 bool rule_made_change = false;
17 auto result = rule->Apply(op, bindings, rule_made_change);
18 if (result) {
19 changes_made = true;
20 // the base node changed: the rule applied changes
21 // rerun on the new node
22 return ExpressionRewriter::ApplyRules(op, rules, move(result), changes_made);
23 } else if (rule_made_change) {
24 changes_made = true;
25 // the base node didn't change, but changes were made, rerun
26 return expr;
27 }
28 // else nothing changed, continue to the next rule
29 continue;
30 }
31 }
32 // no changes could be made to this node
33 // recursively run on the children of this node
34 ExpressionIterator::EnumerateChildren(*expr, [&](unique_ptr<Expression> child) -> unique_ptr<Expression> {
35 return ExpressionRewriter::ApplyRules(op, rules, move(child), changes_made);
36 });
37 return expr;
38}
39
40void ExpressionRewriter::Apply(LogicalOperator &root) {
41 // first apply the rules to child operators of this node (if any)
42 for (auto &child : root.children) {
43 Apply(*child);
44 }
45 // apply the rules to this node
46 if (root.expressions.size() == 0) {
47 // no expressions to apply rules on: return
48 return;
49 }
50 vector<Rule *> to_apply_rules;
51 for (auto &rule : rules) {
52 if (rule->logical_root && !rule->logical_root->Match(root.type)) {
53 // this rule does not apply to this type of LogicalOperator
54 continue;
55 }
56 to_apply_rules.push_back(rule.get());
57 }
58 if (to_apply_rules.size() == 0) {
59 // no rules to apply on this node
60 return;
61 }
62 for (idx_t i = 0; i < root.expressions.size(); i++) {
63 bool changes_made;
64 do {
65 changes_made = false;
66 root.expressions[i] =
67 ExpressionRewriter::ApplyRules(root, to_apply_rules, move(root.expressions[i]), changes_made);
68 } while (changes_made);
69 }
70
71 // if it is a LogicalFilter, we split up filter conjunctions again
72 if (root.type == LogicalOperatorType::FILTER) {
73 auto &filter = (LogicalFilter &)root;
74 filter.SplitPredicates();
75 }
76}
77