1#include "duckdb/optimizer/rule/constant_folding.hpp"
2
3#include "duckdb/common/exception.hpp"
4#include "duckdb/execution/expression_executor.hpp"
5#include "duckdb/optimizer/expression_rewriter.hpp"
6#include "duckdb/planner/expression/bound_constant_expression.hpp"
7
8using namespace duckdb;
9using namespace std;
10
11namespace duckdb {
12
13//! The ConstantFoldingExpressionMatcher matches on any scalar expression (i.e. Expression::IsFoldable is true)
14class ConstantFoldingExpressionMatcher : public FoldableConstantMatcher {
15public:
16 bool Match(Expression *expr, vector<Expression *> &bindings) override {
17 // we also do not match on ConstantExpressions, because we cannot fold those any further
18 if (expr->type == ExpressionType::VALUE_CONSTANT) {
19 return false;
20 }
21 return FoldableConstantMatcher::Match(expr, bindings);
22 }
23};
24} // namespace duckdb
25
26ConstantFoldingRule::ConstantFoldingRule(ExpressionRewriter &rewriter) : Rule(rewriter) {
27 auto op = make_unique<ConstantFoldingExpressionMatcher>();
28 root = move(op);
29}
30
31unique_ptr<Expression> ConstantFoldingRule::Apply(LogicalOperator &op, vector<Expression *> &bindings,
32 bool &changes_made) {
33 auto root = bindings[0];
34 // the root is a scalar expression that we have to fold
35 assert(root->IsFoldable() && root->type != ExpressionType::VALUE_CONSTANT);
36
37 // use an ExpressionExecutor to execute the expression
38 auto result_value = ExpressionExecutor::EvaluateScalar(*root);
39 assert(result_value.type == root->return_type);
40 // now get the value from the result vector and insert it back into the plan as a constant expression
41 return make_unique<BoundConstantExpression>(result_value);
42}
43