patch 4.0
This commit is contained in:
@ -21,14 +21,18 @@
|
||||
//#include "sql/engine/expr/ob_expr_promotion_util.h"
|
||||
#include "sql/engine/expr/ob_expr_equal.h"
|
||||
#include "sql/session/ob_sql_session_info.h"
|
||||
#include "sql/engine/expr/ob_datum_cast.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
|
||||
namespace oceanbase {
|
||||
namespace oceanbase
|
||||
{
|
||||
using namespace oceanbase::common;
|
||||
namespace sql {
|
||||
namespace sql
|
||||
{
|
||||
|
||||
ObExprNullif::ObExprNullif(ObIAllocator& alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_NULLIF, N_NULLIF, MORE_THAN_ONE, NOT_ROW_DIMENSION),
|
||||
first_param_can_be_null_(true)
|
||||
ObExprNullif::ObExprNullif(ObIAllocator &alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_NULLIF, N_NULLIF, 2, NOT_ROW_DIMENSION),
|
||||
first_param_can_be_null_(true)
|
||||
{}
|
||||
|
||||
// in engine 3.0, we have 3 copy of params
|
||||
@ -38,147 +42,34 @@ ObExprNullif::ObExprNullif(ObIAllocator& alloc)
|
||||
// because type deduce maybe unstable.
|
||||
// 2. cast expr will add on e2 and e3
|
||||
// 3. e4 is used for result. e5 is useless
|
||||
int ObExprNullif::calc_result_typeN(
|
||||
ObExprResType& type, ObExprResType* types, int64_t param_num, ObExprTypeCtx& type_ctx) const
|
||||
int ObExprNullif::calc_result_type2(ObExprResType &type,
|
||||
ObExprResType &type1,
|
||||
ObExprResType &type2,
|
||||
ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const ObSQLSessionInfo* session = type_ctx.get_session();
|
||||
CK(OB_NOT_NULL(session));
|
||||
if (OB_SUCC(ret)) {
|
||||
if (session->use_static_typing_engine()) {
|
||||
CK(6 == param_num);
|
||||
CK(lib::is_mysql_mode());
|
||||
if (types[0].is_null()) {
|
||||
// eval_nullif() just return null, no need to set cmp type
|
||||
type.set_type(ObCharType);
|
||||
type.set_collation_level(types[0].get_collation_level());
|
||||
type.set_default_collation_type();
|
||||
types[4].set_calc_type(ObCharType);
|
||||
types[4].set_calc_collation_type(ObCharset::get_system_collation());
|
||||
} else {
|
||||
// setup cmp type
|
||||
ObExprResType cmp_type;
|
||||
OZ(se_deduce_type(type, cmp_type, types[0], types[1], type_ctx));
|
||||
OX(types[2].set_calc_meta(cmp_type.get_calc_meta()));
|
||||
OX(types[2].set_calc_accuracy(cmp_type.get_calc_accuracy()));
|
||||
OX(types[3].set_calc_meta(cmp_type.get_calc_meta()));
|
||||
OX(types[3].set_calc_accuracy(cmp_type.get_calc_accuracy()));
|
||||
|
||||
// setup res type
|
||||
OX(types[4].set_calc_meta(type.get_obj_meta()));
|
||||
OX(types[4].set_calc_accuracy(type.get_calc_accuracy()));
|
||||
}
|
||||
} else {
|
||||
CK(2 == param_num);
|
||||
CK(lib::is_mysql_mode());
|
||||
OZ(deduce_type(type, types[0], types[1], type_ctx));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprNullif::deduce_type(
|
||||
ObExprResType& type, ObExprResType& type1, ObExprResType& type2, ObExprTypeCtx& type_ctx) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObExprResType cmp_type;
|
||||
const ObSQLSessionInfo* session = type_ctx.get_session();
|
||||
if (OB_ISNULL(session)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("session is NULL", K(ret));
|
||||
} else if (OB_FAIL(calc_cmp_type2(cmp_type, type1, type2, type_ctx.get_coll_type()))) {
|
||||
LOG_WARN("failed to calc cmp type", K(ret), K(type1), K(type2));
|
||||
if (type1.is_null()) {
|
||||
// eval_nullif() just return null, no need to set cmp type
|
||||
type.set_type(ObCharType);
|
||||
type.set_collation_level(type1.get_collation_level());
|
||||
type.set_default_collation_type();
|
||||
type.set_calc_type(ObCharType);
|
||||
type.set_calc_collation_type(ObCharset::get_system_collation());
|
||||
} else {
|
||||
type.set_type(type1.get_type());
|
||||
type.set_accuracy(type1.get_accuracy());
|
||||
if (ob_is_string_type(type.get_type()) || ob_is_enumset_tc(type.get_type())) {
|
||||
ObCollationLevel res_cs_level = CS_LEVEL_INVALID;
|
||||
ObCollationType res_cs_type = CS_TYPE_INVALID;
|
||||
if (OB_FAIL(ObCharset::aggregate_collation(type1.get_collation_level(),
|
||||
type1.get_collation_type(),
|
||||
type2.get_collation_level(),
|
||||
type2.get_collation_type(),
|
||||
res_cs_level,
|
||||
res_cs_type))) {
|
||||
LOG_WARN("failed to calc collation", K(ret));
|
||||
} else {
|
||||
type.set_collation_level(res_cs_level);
|
||||
type.set_collation_type(res_cs_type);
|
||||
// deduce length
|
||||
if (type.get_collation_type() == CS_TYPE_BINARY) {
|
||||
ObLength len_in_byte = -1;
|
||||
if (OB_FAIL(type1.get_length_for_meta_in_bytes(len_in_byte))) {
|
||||
LOG_WARN("get length in bytes failed", K(ret), K(type1));
|
||||
} else {
|
||||
type.set_length(len_in_byte);
|
||||
}
|
||||
} else {
|
||||
type.set_length(type1.get_length());
|
||||
}
|
||||
}
|
||||
} else if (type.is_null()) {
|
||||
type.set_type(ObCharType);
|
||||
type.set_default_collation_type();
|
||||
}
|
||||
type.set_calc_type(cmp_type.get_calc_type());
|
||||
type.set_calc_collation(cmp_type);
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
if (ob_is_enumset_tc(type1.get_type()) || ob_is_enumset_tc(type2.get_type())) {
|
||||
ObObjType calc_type = enumset_calc_types_[OBJ_TYPE_TO_CLASS[cmp_type.get_calc_type()]];
|
||||
if (OB_UNLIKELY(ObMaxType == calc_type)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SQL_ENG_LOG(WARN, "invalid type of parameter ", K(type1), K(type2), K(cmp_type), K(ret));
|
||||
} else if (ObVarcharType == calc_type) {
|
||||
if (ob_is_enumset_tc(type1.get_type())) {
|
||||
type1.set_calc_type(calc_type);
|
||||
}
|
||||
if (ob_is_enumset_tc(type2.get_type())) {
|
||||
type2.set_calc_type(calc_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
// setup cmp type
|
||||
ObExprResType cmp_type;
|
||||
if (OB_FAIL(se_deduce_type(type, cmp_type, type1, type2, type_ctx))) {
|
||||
LOG_WARN("se deduce type failed", K(ret));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprNullif::calc_resultN(ObObj& result, const ObObj* objs_stack, int64_t param_num, ObExprCtx& expr_ctx) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
EXPR_DEFINE_CMP_CTX(result_type_.get_calc_meta(), true, expr_ctx);
|
||||
EXPR_DEFINE_CAST_CTX(expr_ctx, CM_NONE);
|
||||
ObObj cmp;
|
||||
if (OB_UNLIKELY(2 != param_num && 6 != param_num) || OB_ISNULL(objs_stack)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid argument", K(ret), K(param_num), K(objs_stack));
|
||||
} else {
|
||||
const ObObj& obj1 = objs_stack[0];
|
||||
const ObObj& obj2 = objs_stack[1];
|
||||
if (OB_FAIL(ObExprEqual::calc(cmp, obj1, obj2, cmp_ctx, cast_ctx))) {
|
||||
LOG_WARN("failed to compare objects", K(ret), K(obj1), K(obj2));
|
||||
} else if (cmp.is_true()) {
|
||||
result.set_null();
|
||||
} else if (OB_UNLIKELY(ob_is_enumset_inner_tc(obj1.get_type()))) {
|
||||
ObObj obj_ret;
|
||||
ObEnumSetInnerValue inner_value;
|
||||
if (OB_FAIL(obj1.get_enumset_inner_value(inner_value))) {
|
||||
LOG_WARN("failed to get enumset_inner_value", K(ret), K(obj1), K(obj2));
|
||||
} else if (ObEnumInnerType == obj1.get_type()) {
|
||||
obj_ret.set_enum(inner_value.numberic_value_);
|
||||
} else {
|
||||
obj_ret.set_set(inner_value.numberic_value_);
|
||||
}
|
||||
result = obj_ret;
|
||||
} else {
|
||||
result = obj1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprNullif::se_deduce_type(ObExprResType& type, ObExprResType& cmp_type, const ObExprResType& type1,
|
||||
const ObExprResType& type2, ObExprTypeCtx& type_ctx) const
|
||||
int ObExprNullif::se_deduce_type(ObExprResType &type,
|
||||
ObExprResType &cmp_type,
|
||||
ObExprResType &type1,
|
||||
ObExprResType &type2,
|
||||
ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
type.set_meta(type1.get_obj_meta());
|
||||
@ -186,16 +77,13 @@ int ObExprNullif::se_deduce_type(ObExprResType& type, ObExprResType& cmp_type, c
|
||||
if (ob_is_string_type(type.get_type()) || ob_is_enumset_tc(type.get_type())) {
|
||||
ObCollationLevel res_cs_level = CS_LEVEL_INVALID;
|
||||
ObCollationType res_cs_type = CS_TYPE_INVALID;
|
||||
OZ(ObCharset::aggregate_collation(type1.get_collation_level(),
|
||||
type1.get_collation_type(),
|
||||
type2.get_collation_level(),
|
||||
type2.get_collation_type(),
|
||||
res_cs_level,
|
||||
res_cs_type));
|
||||
OZ(ObCharset::aggregate_collation(type1.get_collation_level(), type1.get_collation_type(),
|
||||
type2.get_collation_level(), type2.get_collation_type(),
|
||||
res_cs_level, res_cs_type));
|
||||
if (OB_SUCC(ret)) {
|
||||
type.set_collation_level(res_cs_level);
|
||||
type.set_collation_type(res_cs_type);
|
||||
// deduce length
|
||||
//deduce length
|
||||
if (type.get_collation_type() == CS_TYPE_BINARY) {
|
||||
ObLength len_in_byte = -1;
|
||||
OZ(type1.get_length_for_meta_in_bytes(len_in_byte));
|
||||
@ -205,91 +93,297 @@ int ObExprNullif::se_deduce_type(ObExprResType& type, ObExprResType& cmp_type, c
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ob_is_enumset_tc(type.get_type()) || ob_is_enumset_inner_tc(type.get_type())) {
|
||||
type.set_varchar();
|
||||
}
|
||||
OZ(calc_cmp_type2(cmp_type, type1, type2, type_ctx.get_coll_type()));
|
||||
if (OB_SUCC(ret)) {
|
||||
if (ob_is_enumset_tc(type1.get_type()) || ob_is_enumset_tc(type2.get_type())) {
|
||||
ObObjType calc_type = enumset_calc_types_[OBJ_TYPE_TO_CLASS[cmp_type.get_calc_type()]];
|
||||
CK(ObMaxType != calc_type);
|
||||
if (OB_SUCC(ret) && ObVarcharType == calc_type) {
|
||||
if (OB_SUCC(ret)) {
|
||||
cmp_type.set_calc_type(calc_type);
|
||||
cmp_type.set_calc_collation_type(ObCharset::get_system_collation());
|
||||
if (ObVarcharType == calc_type) {
|
||||
if (ob_is_enumset_tc(type1.get_type())) {
|
||||
// only set calc type when calc_type is varchar.
|
||||
// EnumWrapper will add EnumToStr when calc_type is varchar, and otherwise add EnumToInner.
|
||||
// If set calc type when calc_type is not varchar, for example, uint64,
|
||||
// implicit cast from enum_inner to uint64 will be added on EnumToInner expression.
|
||||
type1.set_calc_type(calc_type);
|
||||
type1.set_calc_collation_type(cmp_type.get_calc_collation_type());
|
||||
}
|
||||
//if (ob_is_enumset_tc(type2.get_type())) {
|
||||
//}
|
||||
}
|
||||
// set calc type for type2 no matter whether calc_type is varchar or not, and no matther which param is enum.
|
||||
type2.set_calc_type(calc_type);
|
||||
type2.set_calc_collation_type(cmp_type.get_calc_collation_type());
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
type.set_calc_meta(cmp_type.get_calc_meta());
|
||||
type.set_calc_accuracy(cmp_type.get_calc_accuracy());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprNullif::cg_expr(ObExprCGCtx& expr_cg_ctx, const ObRawExpr& raw_expr, ObExpr& rt_expr) const
|
||||
int ObExprNullif::set_extra_info(ObExprCGCtx &expr_cg_ctx, const ObObjType cmp_type,
|
||||
const ObCollationType cmp_cs_type, const ObScale scale,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
UNUSED(raw_expr);
|
||||
CK(6 == rt_expr.arg_cnt_);
|
||||
const uint32_t param_num = rt_expr.arg_cnt_;
|
||||
const uint32_t real_param_num = param_num / 3;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < real_param_num; i++) {
|
||||
if (OB_FAIL(ObStaticEngineExprCG::replace_var_rt_expr(
|
||||
rt_expr.args_[i], rt_expr.args_[i + real_param_num], &rt_expr, i + real_param_num))) {
|
||||
LOG_WARN("replace var rt expr failed", K(ret), K(i), K(raw_expr));
|
||||
} else if (OB_FAIL(ObStaticEngineExprCG::replace_var_rt_expr(
|
||||
rt_expr.args_[i], rt_expr.args_[i + 2 * real_param_num], &rt_expr, i + 2 * real_param_num))) {
|
||||
LOG_WARN("replace var rt_expr failed", K(ret), K(i), K(raw_expr));
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (ObNullType == rt_expr.args_[0]->datum_meta_.type_) {
|
||||
OX(rt_expr.eval_func_ = eval_nullif);
|
||||
ObCastMode cm = CM_NONE;
|
||||
const bool is_explicit_cast = false;
|
||||
const int32_t result_flag = 0;
|
||||
DatumCastExtraInfo *info = OB_NEWx(DatumCastExtraInfo, expr_cg_ctx.allocator_, *(expr_cg_ctx.allocator_), type_);
|
||||
if (OB_ISNULL(info)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("alloc memory failed", K(ret));
|
||||
} else if (OB_ISNULL(expr_cg_ctx.session_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("ctx.session is null", K(ret));
|
||||
} else if (OB_FAIL(ObSQLUtils::get_default_cast_mode(is_explicit_cast, result_flag,
|
||||
expr_cg_ctx.session_, cm))) {
|
||||
LOG_WARN("get default cast mode failed", K(ret));
|
||||
} else {
|
||||
OV(OB_NOT_NULL(rt_expr.inner_functions_ =
|
||||
reinterpret_cast<void**>(expr_cg_ctx.allocator_->alloc(sizeof(DatumCmpFunc) * 1))),
|
||||
OB_ALLOCATE_MEMORY_FAILED);
|
||||
info->cmp_meta_.type_ = cmp_type;
|
||||
info->cmp_meta_.cs_type_ = cmp_cs_type;
|
||||
info->cmp_meta_.scale_ = scale;
|
||||
info->cm_ = cm;
|
||||
rt_expr.extra_info_ = info;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprNullif::cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
CK(2 == rt_expr.arg_cnt_);
|
||||
const uint32_t param_num = rt_expr.arg_cnt_;
|
||||
const ObObjMeta &cmp_meta = result_type_.get_calc_meta();
|
||||
if (ObNullType == rt_expr.args_[0]->datum_meta_.type_) {
|
||||
OX(rt_expr.eval_func_ = eval_nullif);
|
||||
} else if (OB_FAIL(set_extra_info(expr_cg_ctx, cmp_meta.get_type(),
|
||||
cmp_meta.get_collation_type(), cmp_meta.get_scale(),
|
||||
rt_expr))) {
|
||||
LOG_WARN("set extra info failed", K(ret));
|
||||
} else if (ob_is_enumset_inner_tc(rt_expr.args_[0]->datum_meta_.type_)) {
|
||||
if (OB_UNLIKELY(!ob_is_uint_tc(rt_expr.args_[1]->datum_meta_.type_))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected param type", K(ret), K(rt_expr.args_[1]->datum_meta_));
|
||||
} else {
|
||||
rt_expr.eval_func_ = eval_nullif_enumset;
|
||||
}
|
||||
} else if (ob_is_enumset_inner_tc(rt_expr.args_[1]->datum_meta_.type_)) {
|
||||
if (OB_UNLIKELY(rt_expr.datum_meta_.type_ != rt_expr.args_[0]->datum_meta_.type_
|
||||
|| rt_expr.datum_meta_.cs_type_ != rt_expr.args_[0]->datum_meta_.cs_type_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected type", K(ret), K(rt_expr.datum_meta_), K(rt_expr.args_[0]->datum_meta_));
|
||||
} else {
|
||||
rt_expr.eval_func_ = eval_nullif_enumset;
|
||||
}
|
||||
} else {
|
||||
OV(OB_NOT_NULL(rt_expr.inner_functions_ = reinterpret_cast<void**>(
|
||||
expr_cg_ctx.allocator_->alloc(sizeof(DatumCmpFunc) * 1))),
|
||||
OB_ALLOCATE_MEMORY_FAILED);
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
DatumCmpFunc cmp_func = NULL;
|
||||
const ObDatumMeta& left_meta = rt_expr.args_[2]->datum_meta_;
|
||||
const ObDatumMeta& right_meta = rt_expr.args_[3]->datum_meta_;
|
||||
const ObCollationType cmp_cs_type = left_meta.cs_type_;
|
||||
CK(left_meta.cs_type_ == right_meta.cs_type_);
|
||||
CK(OB_NOT_NULL(cmp_func = ObExprCmpFuncsHelper::get_datum_expr_cmp_func(
|
||||
left_meta.type_, right_meta.type_, lib::is_oracle_mode(), cmp_cs_type)));
|
||||
OX(rt_expr.inner_func_cnt_ = 1);
|
||||
OX(rt_expr.inner_functions_[0] = reinterpret_cast<void*>(cmp_func));
|
||||
if (!cmp_meta.is_null()) {
|
||||
DatumCmpFunc cmp_func = NULL;
|
||||
if (rt_expr.args_[0]->datum_meta_.cs_type_ == rt_expr.args_[1]->datum_meta_.cs_type_) {
|
||||
cmp_func = ObExprCmpFuncsHelper::get_datum_expr_cmp_func(
|
||||
rt_expr.args_[0]->datum_meta_.type_,
|
||||
rt_expr.args_[1]->datum_meta_.type_,
|
||||
lib::is_oracle_mode(),
|
||||
rt_expr.args_[0]->datum_meta_.cs_type_);
|
||||
}
|
||||
if (NULL != cmp_func) {
|
||||
rt_expr.inner_func_cnt_ = 1;
|
||||
rt_expr.inner_functions_[0] = reinterpret_cast<void*>(cmp_func);
|
||||
DatumCastExtraInfo *info = static_cast<DatumCastExtraInfo *>(rt_expr.extra_info_);
|
||||
// assign null type means can compare directly.
|
||||
info->cmp_meta_.type_ = ObNullType;
|
||||
} else {
|
||||
if (OB_ISNULL(cmp_func = ObExprCmpFuncsHelper::get_datum_expr_cmp_func(
|
||||
cmp_meta.get_type(),
|
||||
cmp_meta.get_type(),
|
||||
lib::is_oracle_mode(),
|
||||
cmp_meta.get_collation_type()))){
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("cmp func is null", K(ret), K(cmp_meta));
|
||||
} else {
|
||||
rt_expr.inner_func_cnt_ = 1;
|
||||
rt_expr.inner_functions_[0] = reinterpret_cast<void*>(cmp_func);
|
||||
}
|
||||
}
|
||||
}
|
||||
OX(rt_expr.eval_func_ = eval_nullif);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprNullif::eval_nullif(const ObExpr& expr, ObEvalCtx& ctx, ObDatum& res)
|
||||
int ObExprNullif::cast_param(const ObExpr &src_expr, ObEvalCtx &ctx,
|
||||
const ObDatumMeta &dst_meta,
|
||||
const ObCastMode &cm, ObIAllocator &allocator,
|
||||
ObDatum &res_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum* cmp_e0 = NULL;
|
||||
ObDatum* cmp_e1 = NULL;
|
||||
ObDatum* res_e = NULL;
|
||||
if (OB_FAIL(expr.args_[2]->eval(ctx, cmp_e0))) {
|
||||
LOG_WARN("eval param 0 failed", K(ret));
|
||||
} else if (cmp_e0->is_null()) {
|
||||
res.set_null();
|
||||
} else if (OB_UNLIKELY(1 != expr.inner_func_cnt_) || OB_ISNULL(expr.inner_functions_) ||
|
||||
OB_ISNULL(expr.inner_functions_[0])) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN(
|
||||
"unexpected param", K(ret), K(expr.inner_func_cnt_), KP(expr.inner_functions_), KP(expr.inner_functions_[0]));
|
||||
} else if (OB_FAIL(expr.args_[3]->eval(ctx, cmp_e1)) || OB_FAIL(expr.args_[4]->eval(ctx, res_e))) {
|
||||
LOG_WARN("eval param failed", K(ret), KP(cmp_e1), KP(res_e));
|
||||
} else if (cmp_e1->is_null()) {
|
||||
// e0 is not null, e1 is null
|
||||
res.set_datum(*res_e);
|
||||
const bool string_type = ob_is_string_type(dst_meta.type_);
|
||||
if (src_expr.datum_meta_.type_ == dst_meta.type_
|
||||
&& (!string_type || src_expr.datum_meta_.cs_type_ == dst_meta.cs_type_)) {
|
||||
res_datum = src_expr.locate_expr_datum(ctx);
|
||||
} else if (OB_ISNULL(ctx.datum_caster_) && OB_FAIL(ctx.init_datum_caster())) {
|
||||
LOG_WARN("init datum caster failed", K(ret));
|
||||
} else {
|
||||
bool equal = (0 == reinterpret_cast<DatumCmpFunc>(expr.inner_functions_[0])(*cmp_e0, *cmp_e1));
|
||||
if (equal) {
|
||||
res.set_null();
|
||||
ObDatum *cast_datum = NULL;
|
||||
if (OB_FAIL(ctx.datum_caster_->to_type(dst_meta, src_expr, cm, cast_datum, ctx.get_batch_idx()))) {
|
||||
LOG_WARN("fail to dynamic cast", K(ret), K(cm));
|
||||
} else if (OB_FAIL(res_datum.deep_copy(*cast_datum, allocator))) {
|
||||
LOG_WARN("deep copy datum failed", K(ret));
|
||||
} else {
|
||||
res.set_datum(*res_e);
|
||||
LOG_DEBUG("cast_param", K(src_expr), KP(ctx.frames_[src_expr.frame_idx_]),
|
||||
K(&(src_expr.locate_expr_datum(ctx))),
|
||||
K(ObToStringExpr(ctx, src_expr)), K(dst_meta), K(res_datum));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
int ObExprNullif::cast_result(const ObExpr &src_expr, const ObExpr &dst_expr, ObEvalCtx &ctx,
|
||||
const ObCastMode &cm, ObDatum &expr_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const bool string_type = ob_is_string_type(src_expr.datum_meta_.type_);
|
||||
if (src_expr.datum_meta_.type_ == dst_expr.datum_meta_.type_
|
||||
&& (!string_type || src_expr.datum_meta_.cs_type_ == dst_expr.datum_meta_.cs_type_)) {
|
||||
ObDatum *res_datum = nullptr;
|
||||
if (OB_FAIL(src_expr.eval(ctx, res_datum))) {
|
||||
LOG_WARN("eval param value failed", K(ret));
|
||||
} else {
|
||||
expr_datum = *res_datum;
|
||||
}
|
||||
} else if (OB_ISNULL(ctx.datum_caster_) && OB_FAIL(ctx.init_datum_caster())) {
|
||||
LOG_WARN("init datum caster failed", K(ret));
|
||||
} else {
|
||||
ObDatum *cast_datum = NULL;
|
||||
if (OB_FAIL(ctx.datum_caster_->to_type(dst_expr.datum_meta_, src_expr, cm, cast_datum, ctx.get_batch_idx()))) {
|
||||
LOG_WARN("fail to dynamic cast", K(ret));
|
||||
} else if (OB_FAIL(dst_expr.deep_copy_datum(ctx, *cast_datum))) {
|
||||
LOG_WARN("deep copy datum failed", K(ret));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprNullif::eval_nullif(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum *cmp_e0 = NULL;
|
||||
ObDatum *cmp_e1 = NULL;
|
||||
ObDatum *res_e = NULL;
|
||||
DatumCastExtraInfo *cast_info = NULL;
|
||||
if (OB_FAIL(expr.args_[0]->eval(ctx, cmp_e0))) {
|
||||
LOG_WARN("eval param 0 failed", K(ret));
|
||||
} else if (cmp_e0->is_null()) {
|
||||
res.set_null();
|
||||
} else if (OB_UNLIKELY(1 != expr.inner_func_cnt_) || OB_ISNULL(expr.inner_functions_)
|
||||
|| OB_ISNULL(expr.inner_functions_[0])) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected param", K(ret), K(expr.inner_func_cnt_), KP(expr.inner_functions_),
|
||||
KP(expr.inner_functions_[0]));
|
||||
} else if (OB_FAIL(expr.args_[1]->eval(ctx, cmp_e1))) {
|
||||
LOG_WARN("eval param failed", K(ret));
|
||||
} else if (FALSE_IT(cast_info = static_cast<DatumCastExtraInfo *>(expr.extra_info_))) {
|
||||
} else if (ObNullType == cast_info->cmp_meta_.type_) {
|
||||
// can compare directly.
|
||||
DatumCmpFunc cmp_func = reinterpret_cast<DatumCmpFunc>(expr.inner_functions_[0]);
|
||||
bool equal = cmp_e1->is_null() ? false : (0 == cmp_func(*cmp_e0, *cmp_e1));
|
||||
if (equal) {
|
||||
res.set_null();
|
||||
} else if (OB_FAIL(cast_result(*expr.args_[0], expr, ctx, cast_info->cm_, res))) {
|
||||
LOG_WARN("cast result failed", K(ret));
|
||||
}
|
||||
} else if (cmp_e1->is_null()) {
|
||||
// e0 is not null, e1 is null
|
||||
if (OB_FAIL(cast_result(*expr.args_[0], expr, ctx, cast_info->cm_, res))) {
|
||||
LOG_WARN("cast result failed", K(ret));
|
||||
}
|
||||
} else {
|
||||
DatumCmpFunc cmp_func = reinterpret_cast<DatumCmpFunc>(expr.inner_functions_[0]);
|
||||
ObTempExprCtx::TempAllocGuard tmp_alloc_guard(ctx);
|
||||
ObDatum datum1;
|
||||
ObDatum datum2;
|
||||
if (OB_FAIL(cast_param(*expr.args_[0], ctx, cast_info->cmp_meta_, cast_info->cm_,
|
||||
tmp_alloc_guard.get_allocator(), datum1))) {
|
||||
LOG_WARN("cast param failed", K(ret));
|
||||
} else if (OB_FAIL(cast_param(*expr.args_[1], ctx, cast_info->cmp_meta_, cast_info->cm_,
|
||||
tmp_alloc_guard.get_allocator(), datum2))) {
|
||||
LOG_WARN("cast param failed", K(ret));
|
||||
} else {
|
||||
bool equal = (0 == cmp_func(datum1, datum2));
|
||||
if (equal) {
|
||||
res.set_null();
|
||||
} else if (OB_FAIL(cast_result(*expr.args_[0], expr, ctx, cast_info->cm_, res))) {
|
||||
LOG_WARN("cast result failed", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprNullif::eval_nullif_enumset(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum *cmp_e0 = NULL;
|
||||
ObDatum *cmp_e1 = NULL;
|
||||
ObCastMode cm = CM_NONE;
|
||||
DatumCastExtraInfo *cast_info = NULL;
|
||||
bool equal = 0;
|
||||
if (OB_FAIL(expr.args_[0]->eval(ctx, cmp_e0))) {
|
||||
LOG_WARN("eval param 0 failed", K(ret));
|
||||
} else if (cmp_e0->is_null()) {
|
||||
res.set_null();
|
||||
} else if (OB_FAIL(expr.args_[1]->eval(ctx, cmp_e1))) {
|
||||
LOG_WARN("eval param failed", K(ret));
|
||||
} else if (OB_ISNULL(expr.extra_info_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("extra info is null", K(ret));
|
||||
} else if (FALSE_IT(cast_info = static_cast<DatumCastExtraInfo *>(expr.extra_info_))) {
|
||||
} else if (ob_is_enumset_inner_tc(expr.args_[0]->datum_meta_.type_)) {
|
||||
ObEnumSetInnerValue inner_value;
|
||||
if (OB_FAIL(cmp_e0->get_enumset_inner(inner_value))) {
|
||||
LOG_WARN("failed to inner_value", K(ret));
|
||||
} else if (cmp_e1->is_null()) {
|
||||
res.set_string(inner_value.string_value_);
|
||||
} else if (cmp_e1->get_uint64() == inner_value.numberic_value_) {
|
||||
res.set_null();
|
||||
} else {
|
||||
res.set_string(inner_value.string_value_);
|
||||
}
|
||||
} else {
|
||||
ObDatum datum0;
|
||||
ObEnumSetInnerValue inner_value;
|
||||
ObTempExprCtx::TempAllocGuard tmp_alloc_guard(ctx);
|
||||
if (cmp_e1->is_null()) {
|
||||
res = *cmp_e0;
|
||||
} else if (OB_FAIL(cmp_e1->get_enumset_inner(inner_value))) {
|
||||
LOG_WARN("failed to inner_value", K(ret));
|
||||
} else if (OB_FAIL(cast_param(*expr.args_[0], ctx, cast_info->cmp_meta_, cast_info->cm_,
|
||||
tmp_alloc_guard.get_allocator(), datum0))) {
|
||||
LOG_WARN("cast param failed", K(ret));
|
||||
} else if (datum0.get_uint64() == inner_value.numberic_value_) {
|
||||
res.set_null();
|
||||
} else {
|
||||
res = *cmp_e0;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
Reference in New Issue
Block a user