From 5585d4c91c1c06c9e77a9ea244bbd1ccab344276 Mon Sep 17 00:00:00 2001 From: obdev Date: Wed, 27 Dec 2023 04:13:17 +0000 Subject: [PATCH] Refactor vec2.0 between expr --- src/share/vector/expr_cmp_func.cpp | 174 +--------- src/share/vector/expr_cmp_func.h | 9 - src/sql/engine/expr/ob_expr_between.cpp | 360 +++++++++++++++------ src/sql/engine/expr/ob_expr_between.h | 25 +- src/sql/engine/expr/ob_expr_func_round.cpp | 52 +-- src/sql/engine/ob_serializable_function.h | 2 +- 6 files changed, 309 insertions(+), 313 deletions(-) diff --git a/src/share/vector/expr_cmp_func.cpp b/src/share/vector/expr_cmp_func.cpp index 012f512ed7..6c9ea4611e 100644 --- a/src/share/vector/expr_cmp_func.cpp +++ b/src/share/vector/expr_cmp_func.cpp @@ -239,94 +239,6 @@ template <> int get_cmp_ret (const int ret) { return ret; } } \ } while (false) -#define DO_VECTOR_BETWEEN_CMP(LVec, RVec, ResVec) \ - do { \ - LVec *l_vector = static_cast(left.get_vector(ctx)); \ - RVec *r_vector = static_cast(right.get_vector(ctx)); \ - ResVec *res_vec = static_cast(expr.get_vector(ctx)); \ - ObBitVector &eval_flags = expr.get_evaluated_flags(ctx); \ - const char *l_payload = nullptr, *r_payload = nullptr; \ - ObLength l_len = 0, r_len = 0; \ - int cmp_ret = 0; \ - if (!l_vector->has_null() && !r_vector->has_null()) { \ - if (OB_LIKELY(bound.get_all_rows_active() \ - && eval_flags.accumulate_bit_cnt(bound) == 0)) { \ - for (int i = bound.start(); OB_SUCC(ret) && i < bound.end(); i++) { \ - l_vector->get_payload(i, l_payload, l_len); \ - r_vector->get_payload(i, r_payload, r_len); \ - ret = VecTCCmpCalc::cmp(left.obj_meta_, right.obj_meta_, \ - (const void *)l_payload, l_len, \ - (const void *)r_payload, r_len, cmp_ret); \ - /* Result priority: false > null > true */ \ - if (OB_FAIL(ret)) { \ - } else if (Stage == ObExprBetween::BETWEEN_LEFT) { \ - /* If the current calculation is left<=val, any result is directly filled in. \ - If the result is false, the subsequent calculation results are meaningless, \ - and skip is set to true. */ \ - res_vec->set_int(i, (cmp_ret <= 0)); \ - if (cmp_ret > 0) { \ - skip.set(i); \ - } \ - } else if (cmp_ret > 0) { /*BETWEEN_RIGHT*/ \ - /* If currently calculating val<=right, \ - only when the result is false will it be filled in. \ - Note that set_null may have been called before, \ - so unset_null should be called here. */ \ - res_vec->unset_null(i); \ - res_vec->set_int(i, 0); \ - } \ - } \ - } else { \ - for (int i = bound.start(); OB_SUCC(ret) && i < bound.end(); i++) { \ - if (skip.at(i) || eval_flags.at(i)) { continue; } \ - l_vector->get_payload(i, l_payload, l_len); \ - r_vector->get_payload(i, r_payload, r_len); \ - ret = VecTCCmpCalc::cmp(left.obj_meta_, right.obj_meta_, \ - (const void *)l_payload, l_len, \ - (const void *)r_payload, r_len, cmp_ret); \ - if (OB_FAIL(ret)) { \ - } else if (Stage == ObExprBetween::BETWEEN_LEFT) { \ - res_vec->set_int(i, (cmp_ret <= 0)); \ - if (cmp_ret > 0) { \ - skip.set(i); \ - } \ - } else if (cmp_ret > 0) { /*BETWEEN_RIGHT*/ \ - res_vec->unset_null(i); \ - res_vec->set_int(i, 0); \ - } \ - } \ - } \ - } else { \ - for (int i = bound.start(); OB_SUCC(ret) && i < bound.end(); i++) { \ - if (skip.at(i) || eval_flags.at(i)) { continue; } \ - if (l_vector->is_null(i) || r_vector->is_null(i)) { \ - res_vec->set_null(i); \ - /* Cannot set skip here. \ - Because the priority of the "between" results \ - is consistent with the "and" expression: false > null > true. \ - If the result of the right branch is false, \ - it should override the null in the left branch. */ \ - } else { \ - l_vector->get_payload(i, l_payload, l_len); \ - r_vector->get_payload(i, r_payload, r_len); \ - ret = VecTCCmpCalc::cmp(left.obj_meta_, right.obj_meta_, \ - (const void *)l_payload, l_len, \ - (const void *)r_payload, r_len, cmp_ret); \ - if (OB_FAIL(ret)) { \ - } else if (Stage == ObExprBetween::BETWEEN_LEFT) { \ - res_vec->set_int(i, (cmp_ret <= 0)); \ - if (cmp_ret > 0) { \ - skip.set(i); \ - } \ - } else if (cmp_ret > 0) { /*BETWEEN_RIGHT*/ \ - res_vec->unset_null(i); \ - res_vec->set_int(i, 0); \ - } \ - } \ - } \ - } \ - } while (false) - #define CALC_FORMAT(l, r, res) \ ((int32_t)l + (((int32_t)r) << VEC_MAX_FORMAT) + (((int32_t)res) << (VEC_MAX_FORMAT * 2))) template @@ -451,57 +363,9 @@ struct EvalVectorCmp: public EvalVectorCmpWithNull {} template struct EvalVectorCmp: public EvalVectorCmpWithNull {}; -template -struct EvalVectorBetweenCmp -{ - #define VECTOR_BETWEEN_CMP_CASE(l_fmt, r_fmt, res_fmt) \ - case CALC_FORMAT(l_fmt, r_fmt, res_fmt): { \ - DO_VECTOR_BETWEEN_CMP(L_##l_fmt##_FMT, R_##r_fmt##_FMT, RES_##res_fmt##_FMT); \ - } break - static int eval_between_vector(const ObExpr &expr, const ObExpr &left, const ObExpr &right, - ObEvalCtx &ctx, ObBitVector &skip, const EvalBound &bound) - { - using L_VEC_FIXED_FMT = ObFixedLengthFormat>; - using R_VEC_FIXED_FMT = ObFixedLengthFormat>; - using RES_VEC_FIXED_FMT = ObFixedLengthFormat; - using L_VEC_DISCRETE_FMT = ObDiscreteFormat; - using R_VEC_DISCRETE_FMT = ObDiscreteFormat; - using L_VEC_UNIFORM_FMT = ObUniformFormat; - using R_VEC_UNIFORM_FMT = ObUniformFormat; - - int ret = OB_SUCCESS; - VectorFormat left_format = left.get_format(ctx); - VectorFormat right_format = right.get_format(ctx); - VectorFormat res_format = expr.get_format(ctx); - LOG_DEBUG("eval vector cmp", K(expr), K(l_tc), K(r_tc), K(bound), - K(left_format), K(right_format), K(res_format)); - if (is_valid_format(left_format) && is_valid_format(right_format) - && is_valid_format(res_format)) { - switch (CALC_FORMAT(left_format, right_format, res_format)) { - VECTOR_BETWEEN_CMP_CASE(VEC_FIXED, VEC_FIXED, VEC_FIXED); - VECTOR_BETWEEN_CMP_CASE(VEC_FIXED, VEC_UNIFORM, VEC_FIXED); - VECTOR_BETWEEN_CMP_CASE(VEC_DISCRETE, VEC_DISCRETE, VEC_FIXED); - VECTOR_BETWEEN_CMP_CASE(VEC_DISCRETE, VEC_UNIFORM, VEC_FIXED); - VECTOR_BETWEEN_CMP_CASE(VEC_UNIFORM, VEC_FIXED, VEC_FIXED); - VECTOR_BETWEEN_CMP_CASE(VEC_UNIFORM, VEC_DISCRETE, VEC_FIXED); - VECTOR_BETWEEN_CMP_CASE(VEC_UNIFORM, VEC_UNIFORM, VEC_FIXED); - default: { - DO_VECTOR_BETWEEN_CMP(ObVectorBase, ObVectorBase, ObVectorBase); - break; - } - } - } else { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid format", K(left_format), K(right_format), K(res_format)); - } - return ret; - } -#undef VECTOR_BETWEEN_CMP_CASE -}; #undef CALC_FORMAT static sql::ObExpr::EvalVectorFunc EVAL_VECTOR_EXPR_CMP_FUNCS[MAX_VEC_TC][MAX_VEC_TC][CO_MAX]; -static sql::ObExprBetween::EvalVectorBetweenFunc EVAL_VECTOR_BETWEEN_EXPR_CMP_FUNCS[MAX_VEC_TC][MAX_VEC_TC][ObExprBetween::EvalBetweenStage::BETWEEN_MAX]; template struct VectorExprCmpFuncIniter @@ -518,9 +382,6 @@ struct VectorExprCmpFuncIniter template using EvalFunc = EvalVectorCmp(X), static_cast(Y), cmp_op>; - template - using EvalBetweenFunc = - EvalVectorBetweenCmp(X), static_cast(Y), stage>; static void init_array() { auto &funcs = EVAL_VECTOR_EXPR_CMP_FUNCS; @@ -531,12 +392,6 @@ struct VectorExprCmpFuncIniter funcs[X][Y][CO_NE] = &EvalFunc::eval_vector; funcs[X][Y][CO_EQ] = &EvalFunc::eval_vector; funcs[X][Y][CO_CMP] = &EvalFunc::eval_vector; - - auto &between_funcs = EVAL_VECTOR_BETWEEN_EXPR_CMP_FUNCS; - between_funcs[X][Y][ObExprBetween::EvalBetweenStage::BETWEEN_LEFT] = - &EvalBetweenFunc::eval_between_vector; - between_funcs[X][Y][ObExprBetween::EvalBetweenStage::BETWEEN_RIGHT] = - &EvalBetweenFunc::eval_between_vector; } }; @@ -557,48 +412,35 @@ sql::ObExpr::EvalVectorFunc VectorCmpExprFuncsHelper::get_eval_vector_expr_cmp_f return EVAL_VECTOR_EXPR_CMP_FUNCS[l_tc][r_tc][cmp_op]; } -sql::ObExprBetween::EvalVectorBetweenFunc VectorCmpExprFuncsHelper::get_eval_vector_between_expr_cmp_func( - const sql::ObDatumMeta &l_meta, const sql::ObDatumMeta &r_meta, - sql::ObExprBetween::EvalBetweenStage stage) -{ - LOG_DEBUG("eval vector between_expr_cmp_func", K(l_meta), K(r_meta), K(stage)); - VecValueTypeClass l_tc = get_vec_value_tc(l_meta.type_, l_meta.scale_, l_meta.precision_); - VecValueTypeClass r_tc = get_vec_value_tc(r_meta.type_, r_meta.scale_, r_meta.precision_); - return EVAL_VECTOR_BETWEEN_EXPR_CMP_FUNCS[l_tc][r_tc][stage]; -} - } // end namespace common namespace sql { void *g_ser_eval_vector_expr_cmp_funcs[MAX_VEC_TC * MAX_VEC_TC * 7]; -void *g_ser_eval_vector_between_expr_cmp_funcs[MAX_VEC_TC * MAX_VEC_TC * 2]; void *g_ser_nullsafe_rowcmp_funcs[MAX_VEC_TC * MAX_VEC_TC * 2]; +void *g_ser_rowcmp_funcs[MAX_VEC_TC * MAX_VEC_TC]; static_assert(sizeof(g_ser_eval_vector_expr_cmp_funcs) == sizeof(EVAL_VECTOR_EXPR_CMP_FUNCS), "unexpected size"); -static_assert(sizeof(g_ser_eval_vector_between_expr_cmp_funcs) == sizeof(EVAL_VECTOR_BETWEEN_EXPR_CMP_FUNCS), - "unexpected size"); static_assert(sizeof(g_ser_nullsafe_rowcmp_funcs) == sizeof(NULLSAFE_ROW_CMP_FUNCS), "unexpected size"); +static_assert(sizeof(g_ser_rowcmp_funcs) == sizeof(ROW_CMP_FUNCS), + "unexpected size"); bool g_ser_eval_vector_expr_cmp_funcs_init = ObFuncSerialization::convert_NxN_array( g_ser_eval_vector_expr_cmp_funcs, reinterpret_cast(EVAL_VECTOR_EXPR_CMP_FUNCS), MAX_VEC_TC, 7, 0, 7); -bool g_ser_eval_vector_between_expr_cmp_funcs_init = ObFuncSerialization::convert_NxN_array( - g_ser_eval_vector_between_expr_cmp_funcs, reinterpret_cast(EVAL_VECTOR_BETWEEN_EXPR_CMP_FUNCS), - MAX_VEC_TC, 2, 0, 2); - bool g_ser_nullsafe_rowcmp_funcs_init = ObFuncSerialization::convert_NxN_array( g_ser_nullsafe_rowcmp_funcs, reinterpret_cast(NULLSAFE_ROW_CMP_FUNCS), MAX_VEC_TC, 2, 0, 2); - +bool g_ser_rowcmp_funcs_init = ObFuncSerialization::convert_NxN_array( + g_ser_rowcmp_funcs, reinterpret_cast(ROW_CMP_FUNCS), + MAX_VEC_TC, 1, 0, 1); REG_SER_FUNC_ARRAY(OB_SFA_CMP_EXPR_EVAL_VECTOR, g_ser_eval_vector_expr_cmp_funcs, sizeof(g_ser_eval_vector_expr_cmp_funcs) / sizeof(void *)); -REG_SER_FUNC_ARRAY(OB_SFA_CMP_BETWEEN_EXPR_EVAL_VECTOR, g_ser_eval_vector_between_expr_cmp_funcs, - sizeof(g_ser_eval_vector_between_expr_cmp_funcs) / sizeof(void *)); - REG_SER_FUNC_ARRAY(OB_SFA_VECTOR_NULLSAFE_CMP, g_ser_nullsafe_rowcmp_funcs, sizeof(g_ser_nullsafe_rowcmp_funcs) / sizeof(void *)); +REG_SER_FUNC_ARRAY(OB_SFA_VECTOR_CMP, g_ser_rowcmp_funcs, + sizeof(g_ser_rowcmp_funcs) / sizeof(void *)); } // end namespace sql } // end namespace oceanabse diff --git a/src/share/vector/expr_cmp_func.h b/src/share/vector/expr_cmp_func.h index 7cb07f21b8..e5abbb1872 100644 --- a/src/share/vector/expr_cmp_func.h +++ b/src/share/vector/expr_cmp_func.h @@ -39,15 +39,6 @@ struct VectorCmpExprFuncsHelper static sql::ObExpr::EvalVectorFunc get_eval_vector_expr_cmp_func(const sql::ObDatumMeta &l_meta, const sql::ObDatumMeta &r_meta, const common::ObCmpOp cmp_op); - // Compared to get_eval_vector_expr_cmp_func, - // the obtained function has two additional expr arguments: left and right. - // Among the EvalVectorFunc functions, - // they directly use the first two arguments of the expr as left and right. - // However, in some scenarios, this may not be the case, - // so the following functions have been added. - static sql::ObExprBetween::EvalVectorBetweenFunc get_eval_vector_between_expr_cmp_func(const sql::ObDatumMeta &l_meta, - const sql::ObDatumMeta &r_meta, - sql::ObExprBetween::EvalBetweenStage stage); }; } // end namespace common diff --git a/src/sql/engine/expr/ob_expr_between.cpp b/src/sql/engine/expr/ob_expr_between.cpp index 5f0ca969ed..a407ab9744 100644 --- a/src/sql/engine/expr/ob_expr_between.cpp +++ b/src/sql/engine/expr/ob_expr_between.cpp @@ -78,92 +78,99 @@ int calc_between_expr(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res_datum) return ret; } -// eval_left_and_right_operand -template -static int eval_lr_operand(const ObExpr &expr, ObEvalCtx &ctx, - ObBitVector &skip, const EvalBound &bound) -{ - int ret = OB_SUCCESS; - const ObExpr &val_expr = *expr.args_[0]; - const ObExpr &left_expr = *expr.args_[1]; - const ObExpr &right_expr = *expr.args_[2]; - ValVec *val_vec = static_cast(val_expr.get_vector(ctx)); - ResVec *res_vec = static_cast(expr.get_vector(ctx)); - if (val_vec->has_null()) { - for (int i = bound.start(); i < bound.end(); ++i) { - if (!skip.at(i) && val_vec->is_null(i)) { - res_vec->set_null(i); - skip.set(i); - } - } - } - // if skip is all true, `eval_vector` still needs to be called, for that expr format may not be inited. - if (OB_FAIL(left_expr.eval_vector(ctx, skip, bound))) { - LOG_WARN("eval left operand failed", K(ret)); - } else if (OB_FAIL(right_expr.eval_vector(ctx, skip, bound))) { - LOG_WARN("eval right operand failed", K(ret)); - } - return ret; +#define BETWEEN_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT( \ + func_name, stage, l_format, right_vec, res_vec) \ +switch (l_format) { \ + case VEC_FIXED: { \ + ret = func_name( \ + expr, ctx, my_skip, bound); \ + break; \ + } \ + case VEC_DISCRETE: { \ + ret = func_name( \ + expr, ctx, my_skip, bound); \ + break; \ + } \ + case VEC_CONTINUOUS: { \ + ret = func_name( \ + expr, ctx, my_skip, bound); \ + break; \ + } \ + case VEC_UNIFORM: { \ + ret = func_name, right_vec, res_vec, stage>( \ + expr, ctx, my_skip, bound); \ + break; \ + } \ + case VEC_UNIFORM_CONST: { \ + ret = func_name, right_vec, res_vec, stage>( \ + expr, ctx, my_skip, bound); \ + break; \ + } \ + default: { \ + ret = func_name( \ + expr, ctx, my_skip, bound); \ + } \ } -template -static int dispatch_eval_between_operands(const ObExpr &expr, ObEvalCtx &ctx, - ObBitVector &skip, const EvalBound &bound) -{ - int ret = OB_SUCCESS; - VectorFormat res_format = expr.get_format(ctx); - switch (res_format) { - case VEC_FIXED: { - ret = eval_lr_operand(expr, ctx, skip, bound); - break; - } - case VEC_UNIFORM: { - ret = eval_lr_operand>(expr, ctx, skip, bound); - break; - } - case VEC_UNIFORM_CONST: { - ret = eval_lr_operand>(expr, ctx, skip, bound); - break; - } - default: { - ret = eval_lr_operand(expr, ctx, skip, bound); - } - } - return ret; +#define BETWEEN_DISPATCH_VECTOR_IN_RIGHT_ARG_FORMAT( \ + func_name, stage, l_format, r_format, res_vec) \ +switch (r_format) { \ + case VEC_FIXED: { \ + BETWEEN_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT( \ + func_name, stage, l_format, ObFixedLengthBase, res_vec); \ + break; \ + } \ + case VEC_DISCRETE: { \ + BETWEEN_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT( \ + func_name, stage, l_format, ObDiscreteFormat, res_vec); \ + break; \ + } \ + case VEC_CONTINUOUS: { \ + BETWEEN_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT( \ + func_name, stage, l_format, ObContinuousFormat, res_vec); \ + break; \ + } \ + case VEC_UNIFORM: { \ + BETWEEN_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT( \ + func_name, stage, l_format, ObUniformFormat, res_vec); \ + break; \ + } \ + case VEC_UNIFORM_CONST: { \ + BETWEEN_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT( \ + func_name, stage, l_format, ObUniformFormat, res_vec); \ + break; \ + } \ + default: { \ + BETWEEN_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT( \ + func_name, stage, l_format, ObVectorBase, res_vec); \ + } \ } -static int eval_between_operands(const ObExpr &expr, ObEvalCtx &ctx, - ObBitVector &skip, const EvalBound &bound) -{ - int ret = OB_SUCCESS; - const ObExpr &val_expr = *expr.args_[0]; - if (OB_FAIL(val_expr.eval_vector(ctx, skip, bound))) { - LOG_WARN("eval left operand failed", K(ret)); - } else { - VectorFormat val_format = val_expr.get_format(ctx); - switch (val_format) { - case VEC_DISCRETE: - case VEC_CONTINUOUS: - case VEC_FIXED: { - ret = dispatch_eval_between_operands(expr, ctx, skip, bound); - break; - } - case VEC_UNIFORM: { - ret = dispatch_eval_between_operands>(expr, ctx, skip, bound); - break; - } - case VEC_UNIFORM_CONST: { - ret = dispatch_eval_between_operands>(expr, ctx, skip, bound); - break; - } - default: { - ret = dispatch_eval_between_operands(expr, ctx, skip, bound); - } - } - } - return ret; +#define BETWEEN_DISPATCH_VECTOR_IN_RES_ARG_FORMAT( \ + func_name, stage, l_format, r_format) \ +switch (res_format) { \ + case VEC_FIXED: { \ + BETWEEN_DISPATCH_VECTOR_IN_RIGHT_ARG_FORMAT( \ + func_name, stage, l_format, r_format, IntegerFixedVec); \ + break; \ + } \ + case VEC_UNIFORM: { \ + BETWEEN_DISPATCH_VECTOR_IN_RIGHT_ARG_FORMAT( \ + func_name, stage, l_format, r_format, IntegerUniVec); \ + break; \ + } \ + case VEC_UNIFORM_CONST: { \ + BETWEEN_DISPATCH_VECTOR_IN_RIGHT_ARG_FORMAT( \ + func_name, stage, l_format, r_format, IntegerUniCVec); \ + break; \ + } \ + default: { \ + BETWEEN_DISPATCH_VECTOR_IN_RIGHT_ARG_FORMAT( \ + func_name, stage, l_format, r_format, ObVectorBase); \ + } \ } + int ObExprBetween::eval_between_vector(const ObExpr &expr, ObEvalCtx &ctx, const ObBitVector &skip, @@ -176,17 +183,33 @@ int ObExprBetween::eval_between_vector(const ObExpr &expr, const ObExpr &right_expr = *expr.args_[2]; ObBitVector &my_skip = expr.get_pvt_skip(ctx); my_skip.deep_copy(skip, bound.start(), bound.end()); - if (OB_FAIL(eval_between_operands(expr, ctx, my_skip, bound))) { - LOG_WARN("eval between operands failed", K(ret)); - } else if (OB_FAIL((reinterpret_cast(expr.inner_functions_[2]))( - expr, left_expr, val_expr, ctx, my_skip, bound))) { // eval left <= val - LOG_WARN("compare left and val failed", K(ret)); - } else if (OB_FAIL((reinterpret_cast(expr.inner_functions_[3]))( - expr, val_expr, right_expr, ctx, my_skip, bound))) { // eval val <= right - LOG_WARN("compare val and right failed", K(ret)); + if (OB_FAIL(val_expr.eval_vector(ctx, my_skip, bound))) { + LOG_WARN("eval left operand failed", K(ret)); + } else if (OB_FAIL(left_expr.eval_vector(ctx, my_skip, bound))) { + LOG_WARN("eval left operand failed", K(ret)); + } else if (OB_FAIL(right_expr.eval_vector(ctx, my_skip, bound))) { + LOG_WARN("eval left operand failed", K(ret)); } else { - ObBitVector &eval_flags = expr.get_evaluated_flags(ctx); - eval_flags.bit_not(skip, bound); + VectorFormat val_format = val_expr.get_format(ctx); + VectorFormat left_format = left_expr.get_format(ctx); + VectorFormat right_format = right_expr.get_format(ctx); + VectorFormat res_format = expr.get_format(ctx); + BETWEEN_DISPATCH_VECTOR_IN_RES_ARG_FORMAT( + inner_eval_between_vector, BETWEEN_LEFT, + left_format, val_format); + if (OB_FAIL(ret)) { + LOG_WARN("compare left and val failed", K(ret)); + } else { + BETWEEN_DISPATCH_VECTOR_IN_RES_ARG_FORMAT( + inner_eval_between_vector, BETWEEN_RIGHT, + val_format, right_format); + if (OB_FAIL(ret)) { + LOG_WARN("compare val and right failed", K(ret)); + } else { + ObBitVector &eval_flags = expr.get_evaluated_flags(ctx); + eval_flags.bit_not(skip, bound); + } + } } return ret; } @@ -206,8 +229,8 @@ int ObExprBetween::cg_expr(ObExprCGCtx &expr_cg_ctx, } else { DatumCmpFunc cmp_func_1 = NULL; // left <= val DatumCmpFunc cmp_func_2 = NULL; // val <= right - EvalVectorBetweenFunc vec_cmp_func_1 = NULL; // left <= val - EvalVectorBetweenFunc vec_cmp_func_2 = NULL; // val <= right + RowCmpFunc vec_cmp_func_1 = NULL; // left <= val + RowCmpFunc vec_cmp_func_2 = NULL; // val <= right const ObDatumMeta &val_meta = rt_expr.args_[0]->datum_meta_; const ObDatumMeta &left_meta = rt_expr.args_[1]->datum_meta_; const ObDatumMeta &right_meta = rt_expr.args_[2]->datum_meta_; @@ -237,23 +260,22 @@ int ObExprBetween::cg_expr(ObExprCGCtx &expr_cg_ctx, ret = OB_ERR_UNEXPECTED; LOG_WARN("get_datum_expr_cmp_func failed", K(ret), K(val_meta), K(right_meta), K(is_oracle_mode()), K(rt_expr)); - } else if (OB_ISNULL(vec_cmp_func_1 = VectorCmpExprFuncsHelper::get_eval_vector_between_expr_cmp_func( - left_meta, val_meta, EvalBetweenStage::BETWEEN_LEFT))) { + } else if (OB_ISNULL(vec_cmp_func_1 = VectorCmpExprFuncsHelper::get_row_cmp_func( + left_meta, val_meta))) { ret = OB_ERR_UNEXPECTED; VecValueTypeClass value_tc = get_vec_value_tc(val_meta.type_, val_meta.scale_, val_meta.precision_); VecValueTypeClass left_tc = get_vec_value_tc(left_meta.type_, left_meta.scale_, left_meta.precision_); LOG_WARN("The result of get_eval_vector_between_expr_cmp_func(left) is null.", K(ret), K(left_meta), K(val_meta), K(right_meta), K(value_tc), K(left_tc), K(rt_expr)); - } else if (OB_ISNULL(vec_cmp_func_2 = VectorCmpExprFuncsHelper::get_eval_vector_between_expr_cmp_func( - val_meta, right_meta, EvalBetweenStage::BETWEEN_RIGHT))) { + } else if (OB_ISNULL(vec_cmp_func_2 = VectorCmpExprFuncsHelper::get_row_cmp_func( + val_meta, right_meta))) { ret = OB_ERR_UNEXPECTED; VecValueTypeClass value_tc = get_vec_value_tc(val_meta.type_, val_meta.scale_, val_meta.precision_); VecValueTypeClass right_tc = get_vec_value_tc(right_meta.type_, right_meta.scale_, right_meta.precision_); LOG_WARN("The result of get_eval_vector_between_expr_cmp_func(right) is null.", K(ret), K(left_meta), K(val_meta), K(right_meta), K(value_tc), K(right_tc), K(rt_expr)); } else if (OB_ISNULL(rt_expr.inner_functions_ = reinterpret_cast( - expr_cg_ctx.allocator_->alloc(sizeof(DatumCmpFunc) * 2 + - sizeof(EvalVectorBetweenFunc) * 2)))) { + expr_cg_ctx.allocator_->alloc(sizeof(DatumCmpFunc) * 2 + sizeof(RowCmpFunc) * 2)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("alloc memory for inner_functions_ failed", K(ret)); } else { @@ -269,5 +291,147 @@ int ObExprBetween::cg_expr(ObExprCGCtx &expr_cg_ctx, return ret; } +#define DO_VECTOR_BETWEEN_ROW_CMP() \ + if (std::is_same::value) { \ + l_payload = fixed_base_l_payload + l_len * i; \ + } else if (!std::is_same>::value){ \ + l_vector->get_payload(i, l_payload, l_len); \ + } \ + if (std::is_same::value) { \ + r_payload = fixed_base_r_payload + r_len * i; \ + } else if (!std::is_same>::value){ \ + r_vector->get_payload(i, r_payload, r_len); \ + } \ + if (Stage == EvalBetweenStage::BETWEEN_LEFT) { \ + ret = (reinterpret_cast(expr.inner_functions_[2])) \ + (left->obj_meta_, right->obj_meta_, \ + (const void *)l_payload, l_len, \ + (const void *)r_payload, r_len, cmp_ret); \ + } else { /*BETWEEN_RIGHT*/ \ + ret = (reinterpret_cast(expr.inner_functions_[3])) \ + (left->obj_meta_, right->obj_meta_, \ + (const void *)l_payload, l_len, \ + (const void *)r_payload, r_len, cmp_ret); \ + } + +#define DO_VECTOR_BETWEEN_SET_RES() \ + /* Result priority: false > null > true */ \ + if (OB_FAIL(ret)) { \ + } else if (Stage == EvalBetweenStage::BETWEEN_LEFT) { \ + /* If the current calculation is left<=val, any result is directly filled in. \ + If the result is false, the subsequent calculation results are meaningless, \ + and skip is set to true. */ \ + res_vec->set_int(i, (cmp_ret <= 0)); \ + if (cmp_ret > 0) { \ + skip.set(i); \ + } \ + } else if (cmp_ret > 0) { /*BETWEEN_RIGHT*/ \ + /* If currently calculating val<=right, \ + only when the result is false will it be filled in. */ \ + res_vec->set_int(i, 0); \ + } + + +template +int ObExprBetween::inner_eval_between_vector(const ObExpr &expr, + ObEvalCtx &ctx, + ObBitVector &skip, + const EvalBound &bound) +{ + int ret = OB_SUCCESS; + ObExpr *left = nullptr; + ObExpr *right = nullptr; + if (Stage == EvalBetweenStage::BETWEEN_LEFT) { + left = expr.args_[1]; + right = expr.args_[0]; + } else { + left = expr.args_[0]; + right = expr.args_[2]; + } + LVec *l_vector = static_cast(left->get_vector(ctx)); + RVec *r_vector = static_cast(right->get_vector(ctx)); + ResVec *res_vec = static_cast(expr.get_vector(ctx)); + ObBitVector &eval_flags = expr.get_evaluated_flags(ctx); + const char *l_payload = nullptr, *r_payload = nullptr; + const char *fixed_base_l_payload = nullptr, *fixed_base_r_payload = nullptr; + ObLength l_len = 0, r_len = 0; + int cmp_ret = 0; + bool l_has_null = l_vector->has_null(); + bool r_has_null = r_vector->has_null(); + // If a constant value exists and that constant value is null, + // then set the entire res_vec to null. + if (std::is_same>::value && l_has_null) { + // If at this point the computation is val < right, and val is null, + // then the result must have already been set to null previously, + // and can be skipped directly. + if (Stage == EvalBetweenStage::BETWEEN_LEFT) { + for (int i = bound.start(); i < bound.end(); ++i) { + if (skip.at(i) || eval_flags.at(i)) { continue; } + res_vec->set_null(i); + } + } + } else if (std::is_same>::value && r_has_null) { + for (int i = bound.start(); i < bound.end(); ++i) { + if (skip.at(i) || eval_flags.at(i)) { continue; } + res_vec->set_null(i); + } + // For the case where both sides are constants, calculate only once, + // then fill the values in a loop; + // there is no need to consider the null situation, + // as it has already been assessed previously. + } else if (std::is_same>::value && + std::is_same>::value) { + l_vector->get_payload(0, l_payload, l_len); + r_vector->get_payload(0, r_payload, r_len); + if (Stage == EvalBetweenStage::BETWEEN_LEFT) { + ret = (reinterpret_cast(expr.inner_functions_[2])) + (left->obj_meta_, right->obj_meta_, + (const void *)l_payload, l_len, + (const void *)r_payload, r_len, cmp_ret); + } else { /*BETWEEN_RIGHT*/ + ret = (reinterpret_cast(expr.inner_functions_[3])) + (left->obj_meta_, right->obj_meta_, + (const void *)l_payload, l_len, + (const void *)r_payload, r_len, cmp_ret); + } + for (int i = bound.start(); OB_SUCC(ret) && i < bound.end(); ++i) { + if (skip.at(i) || eval_flags.at(i)) { continue; } + DO_VECTOR_BETWEEN_SET_RES(); + } + } else { + if (std::is_same::value) { + fixed_base_l_payload = (reinterpret_cast(l_vector))->get_data(); + l_len = (reinterpret_cast(l_vector))->get_length(); + } else if (std::is_same>::value) { + l_vector->get_payload(0, l_payload, l_len); + } + if (std::is_same::value) { + fixed_base_r_payload = (reinterpret_cast(r_vector))->get_data(); + r_len = (reinterpret_cast(r_vector))->get_length(); + } else if (std::is_same>::value) { + r_vector->get_payload(0, r_payload, r_len); + } + if (!(l_has_null || r_has_null)) { + for (int i = bound.start(); OB_SUCC(ret) && i < bound.end(); ++i) { + if (skip.at(i) || eval_flags.at(i)) { continue; } + DO_VECTOR_BETWEEN_ROW_CMP(); + DO_VECTOR_BETWEEN_SET_RES(); + } + } else { + for (int i = bound.start(); OB_SUCC(ret) && i < bound.end(); ++i) { + if (skip.at(i) || eval_flags.at(i)) { continue; } + if (l_vector->is_null(i) || r_vector->is_null(i)) { + res_vec->set_null(i); + } else { + DO_VECTOR_BETWEEN_ROW_CMP(); + DO_VECTOR_BETWEEN_SET_RES(); + } + } + } + } + return ret; +} + } } diff --git a/src/sql/engine/expr/ob_expr_between.h b/src/sql/engine/expr/ob_expr_between.h index ca1d95fa4c..1db8eb0b9e 100644 --- a/src/sql/engine/expr/ob_expr_between.h +++ b/src/sql/engine/expr/ob_expr_between.h @@ -30,6 +30,12 @@ public: { } + enum EvalBetweenStage { + BETWEEN_LEFT, + BETWEEN_RIGHT, + BETWEEN_MAX + }; + virtual int cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const override; @@ -37,20 +43,13 @@ public: ObEvalCtx &ctx, const ObBitVector &skip, const EvalBound &bound); - enum EvalBetweenStage { - BETWEEN_LEFT, - BETWEEN_RIGHT, - BETWEEN_MAX - }; - struct EvalVectorBetweenCmp; - - typedef int (*EvalVectorBetweenFunc) (const ObExpr &expr, - const ObExpr &left, - const ObExpr &right, - ObEvalCtx &ctx, - ObBitVector &skip, - const EvalBound &bound); + template + static int inner_eval_between_vector(const ObExpr &expr, + ObEvalCtx &ctx, + ObBitVector &skip, + const EvalBound &bound); private: // types and constants private: diff --git a/src/sql/engine/expr/ob_expr_func_round.cpp b/src/sql/engine/expr/ob_expr_func_round.cpp index 4fa8e5faa8..501cce07dc 100644 --- a/src/sql/engine/expr/ob_expr_func_round.cpp +++ b/src/sql/engine/expr/ob_expr_func_round.cpp @@ -751,7 +751,7 @@ int ObExprFuncRound::calc_round_expr_numeric1_batch(const ObExpr &expr, return ret; } -#define ROUND_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT(func_name, res_vec) \ +#define ROUND_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT(func_name, res_vec) \ switch (left_format) { \ case VEC_FIXED: { \ ret = func_name(expr, ctx, skip, bound); \ @@ -778,31 +778,31 @@ switch (left_format) { } \ } -#define ROUND_DISPATCH_VECTOR_IN_RES_ARG_FORMAT(func_name) \ -switch (res_format) { \ - case VEC_FIXED: { \ - ROUND_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT(func_name, ObFixedLengthBase); \ - break; \ - } \ - case VEC_DISCRETE: { \ - ROUND_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT(func_name, ObDiscreteFormat); \ - break; \ - } \ - case VEC_CONTINUOUS: { \ - ROUND_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT(func_name, ObContinuousFormat); \ - break; \ - } \ - case VEC_UNIFORM: { \ - ROUND_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT(func_name, ObUniformFormat); \ - break; \ - } \ - case VEC_UNIFORM_CONST: { \ - ROUND_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT(func_name, ObUniformFormat); \ - break; \ - } \ - default: { \ - ROUND_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT(func_name, ObVectorBase); \ - } \ +#define ROUND_DISPATCH_VECTOR_IN_RES_ARG_FORMAT(func_name) \ +switch (res_format) { \ + case VEC_FIXED: { \ + ROUND_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT(func_name, ObFixedLengthBase); \ + break; \ + } \ + case VEC_DISCRETE: { \ + ROUND_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT(func_name, ObDiscreteFormat); \ + break; \ + } \ + case VEC_CONTINUOUS: { \ + ROUND_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT(func_name, ObContinuousFormat); \ + break; \ + } \ + case VEC_UNIFORM: { \ + ROUND_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT(func_name, ObUniformFormat); \ + break; \ + } \ + case VEC_UNIFORM_CONST: { \ + ROUND_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT(func_name, ObUniformFormat); \ + break; \ + } \ + default: { \ + ROUND_DISPATCH_VECTOR_IN_LEFT_ARG_FORMAT(func_name, ObVectorBase); \ + } \ } int ObExprFuncRound::calc_round_expr_numeric1_vector(const ObExpr &expr, diff --git a/src/sql/engine/ob_serializable_function.h b/src/sql/engine/ob_serializable_function.h index f1a893a970..6d0cada88e 100644 --- a/src/sql/engine/ob_serializable_function.h +++ b/src/sql/engine/ob_serializable_function.h @@ -120,7 +120,7 @@ typedef void (*ser_eval_vector_function)(ObEvalVectorFuncTag &); OB_SFA_DECIMAL_INT_BASIC_PART1, \ OB_SFA_DECIMAL_INT_BASIC_PART2, \ OB_SFA_DECIMAL_INT_NULLSAFE_CMP, \ - OB_SFA_CMP_BETWEEN_EXPR_EVAL_VECTOR, \ + OB_SFA_VECTOR_CMP, \ OB_SFA_SQL_EXPR_ABS_EVAL_VEC, \ OB_SFA_VECTOR_CAST, \ OB_SFA_VECTOR_EVAL_ARG_CAST, \