1#include "duckdb/common/vector_operations/vector_operations.hpp"
2#include "duckdb/execution/expression_executor.hpp"
3#include "duckdb/planner/expression/bound_between_expression.hpp"
4#include "duckdb/common/operator/comparison_operators.hpp"
5#include "duckdb/common/vector_operations/ternary_executor.hpp"
6
7namespace duckdb {
8
9struct BothInclusiveBetweenOperator {
10 template <class T>
11 static inline bool Operation(T input, T lower, T upper) {
12 return GreaterThanEquals::Operation<T>(input, lower) && LessThanEquals::Operation<T>(input, upper);
13 }
14};
15
16struct LowerInclusiveBetweenOperator {
17 template <class T>
18 static inline bool Operation(T input, T lower, T upper) {
19 return GreaterThanEquals::Operation<T>(input, lower) && LessThan::Operation<T>(input, upper);
20 }
21};
22
23struct UpperInclusiveBetweenOperator {
24 template <class T>
25 static inline bool Operation(T input, T lower, T upper) {
26 return GreaterThan::Operation<T>(input, lower) && LessThanEquals::Operation<T>(input, upper);
27 }
28};
29
30struct ExclusiveBetweenOperator {
31 template <class T>
32 static inline bool Operation(T input, T lower, T upper) {
33 return GreaterThan::Operation<T>(input, lower) && LessThan::Operation<T>(input, upper);
34 }
35};
36
37template <class OP>
38static idx_t BetweenLoopTypeSwitch(Vector &input, Vector &lower, Vector &upper, const SelectionVector *sel, idx_t count,
39 SelectionVector *true_sel, SelectionVector *false_sel) {
40 switch (input.GetType().InternalType()) {
41 case PhysicalType::BOOL:
42 case PhysicalType::INT8:
43 return TernaryExecutor::Select<int8_t, int8_t, int8_t, OP>(input, lower, upper, sel, count, true_sel,
44 false_sel);
45 case PhysicalType::INT16:
46 return TernaryExecutor::Select<int16_t, int16_t, int16_t, OP>(input, lower, upper, sel, count, true_sel,
47 false_sel);
48 case PhysicalType::INT32:
49 return TernaryExecutor::Select<int32_t, int32_t, int32_t, OP>(input, lower, upper, sel, count, true_sel,
50 false_sel);
51 case PhysicalType::INT64:
52 return TernaryExecutor::Select<int64_t, int64_t, int64_t, OP>(input, lower, upper, sel, count, true_sel,
53 false_sel);
54 case PhysicalType::INT128:
55 return TernaryExecutor::Select<hugeint_t, hugeint_t, hugeint_t, OP>(input, lower, upper, sel, count, true_sel,
56 false_sel);
57 case PhysicalType::UINT8:
58 return TernaryExecutor::Select<uint8_t, uint8_t, uint8_t, OP>(input, lower, upper, sel, count, true_sel,
59 false_sel);
60 case PhysicalType::UINT16:
61 return TernaryExecutor::Select<uint16_t, uint16_t, uint16_t, OP>(input, lower, upper, sel, count, true_sel,
62 false_sel);
63 case PhysicalType::UINT32:
64 return TernaryExecutor::Select<uint32_t, uint32_t, uint32_t, OP>(input, lower, upper, sel, count, true_sel,
65 false_sel);
66 case PhysicalType::UINT64:
67 return TernaryExecutor::Select<uint64_t, uint64_t, uint64_t, OP>(input, lower, upper, sel, count, true_sel,
68 false_sel);
69 case PhysicalType::FLOAT:
70 return TernaryExecutor::Select<float, float, float, OP>(input, lower, upper, sel, count, true_sel, false_sel);
71 case PhysicalType::DOUBLE:
72 return TernaryExecutor::Select<double, double, double, OP>(input, lower, upper, sel, count, true_sel,
73 false_sel);
74 case PhysicalType::VARCHAR:
75 return TernaryExecutor::Select<string_t, string_t, string_t, OP>(input, lower, upper, sel, count, true_sel,
76 false_sel);
77 case PhysicalType::INTERVAL:
78 return TernaryExecutor::Select<interval_t, interval_t, interval_t, OP>(input, lower, upper, sel, count,
79 true_sel, false_sel);
80 default:
81 throw InvalidTypeException(input.GetType(), "Invalid type for BETWEEN");
82 }
83}
84
85unique_ptr<ExpressionState> ExpressionExecutor::InitializeState(const BoundBetweenExpression &expr,
86 ExpressionExecutorState &root) {
87 auto result = make_uniq<ExpressionState>(args: expr, args&: root);
88 result->AddChild(expr: expr.input.get());
89 result->AddChild(expr: expr.lower.get());
90 result->AddChild(expr: expr.upper.get());
91 result->Finalize();
92 return result;
93}
94
95void ExpressionExecutor::Execute(const BoundBetweenExpression &expr, ExpressionState *state, const SelectionVector *sel,
96 idx_t count, Vector &result) {
97 // resolve the children
98 state->intermediate_chunk.Reset();
99
100 auto &input = state->intermediate_chunk.data[0];
101 auto &lower = state->intermediate_chunk.data[1];
102 auto &upper = state->intermediate_chunk.data[2];
103
104 Execute(expr: *expr.input, state: state->child_states[0].get(), sel, count, result&: input);
105 Execute(expr: *expr.lower, state: state->child_states[1].get(), sel, count, result&: lower);
106 Execute(expr: *expr.upper, state: state->child_states[2].get(), sel, count, result&: upper);
107
108 Vector intermediate1(LogicalType::BOOLEAN);
109 Vector intermediate2(LogicalType::BOOLEAN);
110
111 if (expr.upper_inclusive && expr.lower_inclusive) {
112 VectorOperations::GreaterThanEquals(left&: input, right&: lower, result&: intermediate1, count);
113 VectorOperations::LessThanEquals(left&: input, right&: upper, result&: intermediate2, count);
114 } else if (expr.lower_inclusive) {
115 VectorOperations::GreaterThanEquals(left&: input, right&: lower, result&: intermediate1, count);
116 VectorOperations::LessThan(left&: input, right&: upper, result&: intermediate2, count);
117 } else if (expr.upper_inclusive) {
118 VectorOperations::GreaterThan(left&: input, right&: lower, result&: intermediate1, count);
119 VectorOperations::LessThanEquals(left&: input, right&: upper, result&: intermediate2, count);
120 } else {
121 VectorOperations::GreaterThan(left&: input, right&: lower, result&: intermediate1, count);
122 VectorOperations::LessThan(left&: input, right&: upper, result&: intermediate2, count);
123 }
124 VectorOperations::And(left&: intermediate1, right&: intermediate2, result, count);
125}
126
127idx_t ExpressionExecutor::Select(const BoundBetweenExpression &expr, ExpressionState *state, const SelectionVector *sel,
128 idx_t count, SelectionVector *true_sel, SelectionVector *false_sel) {
129 // resolve the children
130 Vector input(state->intermediate_chunk.data[0]);
131 Vector lower(state->intermediate_chunk.data[1]);
132 Vector upper(state->intermediate_chunk.data[2]);
133
134 Execute(expr: *expr.input, state: state->child_states[0].get(), sel, count, result&: input);
135 Execute(expr: *expr.lower, state: state->child_states[1].get(), sel, count, result&: lower);
136 Execute(expr: *expr.upper, state: state->child_states[2].get(), sel, count, result&: upper);
137
138 if (expr.upper_inclusive && expr.lower_inclusive) {
139 return BetweenLoopTypeSwitch<BothInclusiveBetweenOperator>(input, lower, upper, sel, count, true_sel,
140 false_sel);
141 } else if (expr.lower_inclusive) {
142 return BetweenLoopTypeSwitch<LowerInclusiveBetweenOperator>(input, lower, upper, sel, count, true_sel,
143 false_sel);
144 } else if (expr.upper_inclusive) {
145 return BetweenLoopTypeSwitch<UpperInclusiveBetweenOperator>(input, lower, upper, sel, count, true_sel,
146 false_sel);
147 } else {
148 return BetweenLoopTypeSwitch<ExclusiveBetweenOperator>(input, lower, upper, sel, count, true_sel, false_sel);
149 }
150}
151
152} // namespace duckdb
153