forked from oceanbase/oceanbase
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathob_batch_eval_util.h
More file actions
296 lines (269 loc) · 10.6 KB
/
Copy pathob_batch_eval_util.h
File metadata and controls
296 lines (269 loc) · 10.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#ifndef OCEANBASE_EXPR_OB_BATCH_EVAL_UTIL_H_
#define OCEANBASE_EXPR_OB_BATCH_EVAL_UTIL_H_
#include <type_traits>
#include "sql/engine/expr/ob_expr.h"
namespace oceanbase
{
namespace sql
{
using common::OB_SUCCESS;
// Batch evaluate operand of binary operator
int binary_operand_batch_eval(const ObExpr &expr,
ObEvalCtx &ctx,
const ObBitVector &skip,
const int64_t size,
const bool null_short_circuit);
// Iterate datums of batch result argument
struct ObArgBatchDatumIter
{
explicit ObArgBatchDatumIter(const ObDatum *datums) : datums_(datums) {}
const ObDatum &datum(const int64_t idx) const { return datums_[idx]; }
const ObDatum *datums_;
};
// Iterate datum of scalar result argument
struct ObArgScalarDatumIter
{
explicit ObArgScalarDatumIter(const ObDatum *datum) : datum_(datum) {}
const ObDatum &datum(const int64_t) const { return *datum_; }
const ObDatum *datum_;
};
// Iterate datums of result
struct ObResBatchDatumIter
{
explicit ObResBatchDatumIter(ObDatum *datums) : datums_(datums) {}
ObDatum &datum(const int64_t idx) const { return datums_[idx]; }
ObDatum *datums_;
};
// Iterate raw data of batch result argument
template <typename RawType>
struct ObArgBatchRawIter : public ObArgBatchDatumIter
{
explicit ObArgBatchRawIter(const ObDatum *datums, const char *rev_buf)
: ObArgBatchDatumIter(datums), rev_(reinterpret_cast<const RawType *>(rev_buf)) {}
const RawType &raw(const int64_t i) const { return rev_[i]; }
const RawType *rev_;
};
// Iterate raw data of scalar result argument
template <typename RawType>
struct ObArgScalarRawIter : public ObArgScalarDatumIter
{
using ObArgScalarDatumIter::ObArgScalarDatumIter;
const RawType &raw(const int64_t) const
{
return *reinterpret_cast<const RawType *>(datum_->ptr_);
}
};
// Iterate raw data of result
template <typename RawType>
struct ObResBatchRawIter : public ObResBatchDatumIter
{
explicit ObResBatchRawIter(ObDatum *datums, char *rev_buf)
: ObResBatchDatumIter(datums), rev_(reinterpret_cast<RawType *>(rev_buf)) {}
RawType &raw(int64_t i) const { return rev_[i]; }
RawType *rev_;
};
template <typename ArithOp>
struct ObDoArithBatchEval
{
template <typename ResIter, typename LeftIter, typename RightIter, typename... Args>
inline int operator()(const ObExpr &expr,
ObEvalCtx &ctx,
const ObBitVector &skip,
const int64_t size,
const ResIter &iter,
const LeftIter &l_it,
const RightIter &r_it,
const bool in_frame_notnull,
Args &...args) const
{
int ret = OB_SUCCESS;
ObBitVector &eval_flags = expr.get_evaluated_flags(ctx);
const int64_t step_size = sizeof(uint16_t) * CHAR_BIT;
common::ObDatumDesc desc;
for (int64_t i = 0; i < size && OB_SUCC(ret);) {
const int64_t bit_vec_off = i / step_size;
const uint16_t skip_v = skip.reinterpret_data<uint16_t>()[bit_vec_off];
uint16_t &eval_v = eval_flags.reinterpret_data<uint16_t>()[bit_vec_off];
if (i + step_size < size && (0 == (skip_v | eval_v))) {
if (ArithOp::is_raw_op_supported() && in_frame_notnull) {
for (int64_t j = 0; j < step_size; i++, j++) {
ArithOp::raw_op(iter.raw(i), l_it.raw(i), r_it.raw(i), args...);
}
i -= step_size;
for (int64_t j = 0; OB_SUCC(ret) && j < step_size; i++, j++) {
iter.datum(i).pack_ = sizeof(typename ArithOp::RES_RAW_TYPE);
ret = ArithOp::raw_check(iter.raw(i), l_it.raw(i), r_it.raw(i));
}
} else {
for (int64_t j = 0; OB_SUCC(ret) && j < step_size; i++, j++) {
ret = ArithOp::datum_op(iter.datum(i), l_it.datum(i), r_it.datum(i), args...);
desc.pack_ |= iter.datum(i).pack_;
}
}
if (OB_SUCC(ret)) {
eval_v = 0xFFFF;
}
} else if (i + step_size < size && (0xFFFF == (skip_v | eval_v))) {
i += step_size;
} else {
const int64_t new_size = std::min(size, i + step_size);
for (; i < new_size && OB_SUCC(ret); i++) {
if (!(skip.at(i) || eval_flags.at(i))) {
ret = ArithOp::datum_op(iter.datum(i), l_it.datum(i), r_it.datum(i), args...);
eval_flags.bit_or_assign(i, OB_SUCCESS == ret);
desc.pack_ |= iter.datum(i).pack_;
}
}
}
}
if (OB_SUCC(ret) && desc.is_null()) {
expr.get_eval_info(ctx).notnull_ = false;
}
return ret;
}
};
template <typename ArithOp, template <class> class Functor, typename... Args>
inline int call_functor_with_arg_iter(const ObExpr &expr,
ObEvalCtx &ctx,
const ObBitVector &skip,
const int64_t size,
Args &...args)
{
int ret = OB_SUCCESS;
const ObExpr &left = *expr.args_[0];
const ObExpr &right = *expr.args_[1];
ObResBatchRawIter<typename ArithOp::RES_RAW_TYPE> res(
expr.locate_batch_datums(ctx), expr.get_rev_buf(ctx));
if (left.is_batch_result() && !right.is_batch_result()) {
ObArgBatchRawIter<typename ArithOp::L_RAW_TYPE> l(
left.locate_batch_datums(ctx), left.get_rev_buf(ctx));
ObArgScalarRawIter<typename ArithOp::R_RAW_TYPE> r(&right.locate_expr_datum(ctx));
ret = Functor<ArithOp>()(expr, ctx, skip, size, res, l, r,
(left.get_eval_info(ctx).in_frame_notnull()
&& !right.locate_expr_datum(ctx).is_null()),
args...);
} else if (!left.is_batch_result() && right.is_batch_result()) {
ObArgScalarRawIter<typename ArithOp::L_RAW_TYPE> l(&left.locate_expr_datum(ctx));
ObArgBatchRawIter<typename ArithOp::R_RAW_TYPE> r(
right.locate_batch_datums(ctx), right.get_rev_buf(ctx));
ret = Functor<ArithOp>()(expr, ctx, skip, size, res, l, r,
(right.get_eval_info(ctx).in_frame_notnull()
&& !left.locate_expr_datum(ctx).is_null()),
args...);
} else if (left.is_batch_result() && right.is_batch_result()) {
ObArgBatchRawIter<typename ArithOp::L_RAW_TYPE> l(
left.locate_batch_datums(ctx), left.get_rev_buf(ctx));
ObArgBatchRawIter<typename ArithOp::R_RAW_TYPE> r(
right.locate_batch_datums(ctx), right.get_rev_buf(ctx));
ret = Functor<ArithOp>()(expr, ctx, skip, size, res, l, r,
(left.get_eval_info(ctx).in_frame_notnull()
&& right.get_eval_info(ctx).in_frame_notnull()),
args...);
} else {
ret = common::OB_ERR_UNEXPECTED;
SQL_LOG(WARN, "one argument must be batch result in arith batch evaluate",
K(ret), K(expr), K(left), K(right));
}
return ret;
};
// define arith evaluate batch function.
// see example in ObExprAdd
template <typename ArithOp, typename... Args>
int def_batch_arith_op(const ObExpr &expr,
ObEvalCtx &ctx,
const ObBitVector &skip,
const int64_t size,
Args &...args)
{
int ret = OB_SUCCESS;
if (OB_FAIL(binary_operand_batch_eval(expr, ctx, skip, size, lib::is_oracle_mode()))) {
SQL_LOG(WARN, "bianry operand batch evaluate failed", K(ret), K(expr));
} else {
ret = call_functor_with_arg_iter<ArithOp, ObDoArithBatchEval>(expr, ctx, skip, size, args...);
}
return ret;
}
template <typename Res, typename Left, typename Righ>
struct ObArithOpRawType
{
typedef Res RES_RAW_TYPE;
typedef Left L_RAW_TYPE;
typedef Righ R_RAW_TYPE;
};
struct ObArithOpBase : public ObArithOpRawType<char, char, char>
{
constexpr static bool is_raw_op_supported() { return false; }
template <typename... Args>
static void raw_op(RES_RAW_TYPE &, const L_RAW_TYPE &, const R_RAW_TYPE, Args &...args) {}
static int raw_check(const RES_RAW_TYPE &, const L_RAW_TYPE &, const R_RAW_TYPE &)
{
return common::OB_ERR_UNEXPECTED;
}
};
// Wrap arith operate with null check.
template <typename DatumFunctor>
struct ObWrapArithOpNullCheck: public ObArithOpBase
{
template <typename... Args>
static int datum_op(ObDatum &res, const ObDatum &l, const ObDatum &r, Args &...args)
{
int ret = OB_SUCCESS;
if (l.is_null() || r.is_null()) {
res.set_null();
} else {
ret = DatumFunctor()(res, l, r, args...);
}
return ret;
}
};
template <typename DatumFunctor, typename... Args>
int def_batch_arith_op_by_datum_func(BATCH_EVAL_FUNC_ARG_DECL, Args &...args)
{
return def_batch_arith_op<ObWrapArithOpNullCheck<DatumFunctor>, Args...>(
BATCH_EVAL_FUNC_ARG_LIST, args...);
}
// Wrap arith datum operate from raw operate.
template <typename Base>
struct ObArithOpWrap : public Base
{
constexpr static bool is_raw_op_supported() { return true; }
template <typename... Args>
int operator()(ObDatum &res, const ObDatum &l, const ObDatum &r, Args &...args) const
{
Base::raw_op(
*const_cast<typename Base::RES_RAW_TYPE *>(
reinterpret_cast<const typename Base::RES_RAW_TYPE *>(res.ptr_)),
*reinterpret_cast<const typename Base::L_RAW_TYPE *>(l.ptr_),
*reinterpret_cast<const typename Base::R_RAW_TYPE *>(r.ptr_),
args...);
res.pack_ = sizeof(typename Base::RES_RAW_TYPE);
return Base::raw_check(*reinterpret_cast<const typename Base::RES_RAW_TYPE *>(res.ptr_),
*reinterpret_cast<const typename Base::L_RAW_TYPE *>(l.ptr_),
*reinterpret_cast<const typename Base::R_RAW_TYPE *>(r.ptr_));
}
template <typename... Args>
static int datum_op(ObDatum &res, const ObDatum &l, const ObDatum &r, Args &...args)
{
int ret = OB_SUCCESS;
if (l.is_null() || r.is_null()) {
res.set_null();
} else {
ret = ObArithOpWrap()(res, l, r, args...);
}
return ret;
}
};
} // end namespace sql
} // end namespace oceanbase
#endif // OCEANBASE_EXPR_OB_BATCH_EVAL_UTIL_H_