1#include "duckdb/execution/expression_executor.hpp"
2#include "duckdb/optimizer/rule/in_clause_simplification.hpp"
3#include "duckdb/planner/expression/list.hpp"
4#include "duckdb/planner/expression/bound_operator_expression.hpp"
5
6namespace duckdb {
7
8InClauseSimplificationRule::InClauseSimplificationRule(ExpressionRewriter &rewriter) : Rule(rewriter) {
9 // match on InClauseExpression that has a ConstantExpression as a check
10 auto op = make_uniq<InClauseExpressionMatcher>();
11 op->policy = SetMatcher::Policy::SOME;
12 root = std::move(op);
13}
14
15unique_ptr<Expression> InClauseSimplificationRule::Apply(LogicalOperator &op, vector<reference<Expression>> &bindings,
16 bool &changes_made, bool is_root) {
17 auto &expr = bindings[0].get().Cast<BoundOperatorExpression>();
18 if (expr.children[0]->expression_class != ExpressionClass::BOUND_CAST) {
19 return nullptr;
20 }
21 auto &cast_expression = expr.children[0]->Cast<BoundCastExpression>();
22 if (cast_expression.child->expression_class != ExpressionClass::BOUND_COLUMN_REF) {
23 return nullptr;
24 }
25 //! Here we check if we can apply the expression on the constant side
26 auto target_type = cast_expression.source_type();
27 if (!BoundCastExpression::CastIsInvertible(source_type: cast_expression.return_type, target_type)) {
28 return nullptr;
29 }
30 vector<unique_ptr<BoundConstantExpression>> cast_list;
31 //! First check if we can cast all children
32 for (size_t i = 1; i < expr.children.size(); i++) {
33 if (expr.children[i]->expression_class != ExpressionClass::BOUND_CONSTANT) {
34 return nullptr;
35 }
36 D_ASSERT(expr.children[i]->IsFoldable());
37 auto constant_value = ExpressionExecutor::EvaluateScalar(context&: GetContext(), expr: *expr.children[i]);
38 auto new_constant = constant_value.DefaultTryCastAs(target_type);
39 if (!new_constant) {
40 return nullptr;
41 } else {
42 auto new_constant_expr = make_uniq<BoundConstantExpression>(args&: constant_value);
43 cast_list.push_back(x: std::move(new_constant_expr));
44 }
45 }
46 //! We can cast, so we move the new constant
47 for (size_t i = 1; i < expr.children.size(); i++) {
48 expr.children[i] = std::move(cast_list[i - 1]);
49
50 // expr->children[i] = std::move(new_constant_expr);
51 }
52 //! We can cast the full list, so we move the column
53 expr.children[0] = std::move(cast_expression.child);
54 return nullptr;
55}
56
57} // namespace duckdb
58