| 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 | |
| 8 | using namespace duckdb; | 
| 9 | using namespace std; | 
| 10 | |
| 11 | namespace duckdb { | 
| 12 | |
| 13 | //! The ConstantFoldingExpressionMatcher matches on any scalar expression (i.e. Expression::IsFoldable is true) | 
| 14 | class ConstantFoldingExpressionMatcher : public FoldableConstantMatcher { | 
| 15 | public: | 
| 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 | |
| 26 | ConstantFoldingRule::ConstantFoldingRule(ExpressionRewriter &rewriter) : Rule(rewriter) { | 
| 27 | auto op = make_unique<ConstantFoldingExpressionMatcher>(); | 
| 28 | root = move(op); | 
| 29 | } | 
| 30 | |
| 31 | unique_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 | 
