diff --git a/src/sql/engine/expr/ob_expr_coalesce.cpp b/src/sql/engine/expr/ob_expr_coalesce.cpp index 4bb950dbd..7c6026b47 100644 --- a/src/sql/engine/expr/ob_expr_coalesce.cpp +++ b/src/sql/engine/expr/ob_expr_coalesce.cpp @@ -102,13 +102,17 @@ int ObExprCoalesce::calc_result_typeN(ObExprResType &type, int calc_coalesce_expr(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res_datum) { - int ret = OB_SUCCESS; + int ret = OB_SUCCESS; + bool is_udt_type = lib::is_oracle_mode() && expr.obj_meta_.is_ext(); + bool v = false; res_datum.set_null(); for (int64_t i = 0; OB_SUCC(ret) && i < expr.arg_cnt_; ++i) { ObDatum *child_res = NULL; if (OB_FAIL(expr.args_[i]->eval(ctx, child_res))) { LOG_WARN("eval arg failed", K(ret), K(i)); - } else if (!(child_res->is_null())) { + } else if (OB_FAIL(pl::ObPLDataType::datum_is_null(child_res, is_udt_type, v))) { + LOG_WARN("failed to check datum null", K(ret), K(child_res), K(is_udt_type)); + } else if (!v) { // TODO: @shaoge coalesce的结果可以不用预分配内存,直接使用某个子节点的结果 res_datum.set_datum(*child_res); break; @@ -136,7 +140,9 @@ int ObExprCoalesce::cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, int ObExprCoalesce::calc_batch_coalesce_expr(const ObExpr &expr, ObEvalCtx &ctx, const ObBitVector &skip, const int64_t batch_size) { - int ret = OB_SUCCESS; + int ret = OB_SUCCESS; + bool is_udt_type = lib::is_oracle_mode() && expr.obj_meta_.is_ext(); + bool v = false; LOG_DEBUG("calculate batch coalesce expr", K(batch_size)); ObDatum *results = expr.locate_batch_datums(ctx); @@ -160,13 +166,15 @@ int ObExprCoalesce::calc_batch_coalesce_expr(const ObExpr &expr, ObEvalCtx &ctx, my_skip, batch_size, [&](int64_t idx) __attribute__((always_inline)) { - if (!dv.at(idx)->is_null()) { + if (OB_FAIL(pl::ObPLDataType::datum_is_null(dv.at(idx), is_udt_type, v))) { + LOG_WARN("failed to check datum null", K(ret), K(dv.at(idx)), K(is_udt_type)); + } else if (!v) { results[idx].set_datum(*dv.at(idx)); eval_flags.set(idx); my_skip.set(idx); skip_cnt++; } - return OB_SUCCESS; + return ret; } ); } diff --git a/src/sql/engine/expr/ob_expr_nvl.cpp b/src/sql/engine/expr/ob_expr_nvl.cpp index bec129444..e95e73de2 100644 --- a/src/sql/engine/expr/ob_expr_nvl.cpp +++ b/src/sql/engine/expr/ob_expr_nvl.cpp @@ -303,8 +303,13 @@ int ObExprOracleNvl::calc_nvl_oralce_result_type(ObExprResType &type, OZ (deduce_string_param_calc_type_and_charset(*type_ctx.get_session(), type, params)); OX (type.set_length(MAX(type1.get_calc_length(), type2.get_calc_length()))); } else if (lib::is_oracle_mode() && type.is_ext()) { - CK (type1.get_udt_id() == type2.get_udt_id()); - OX (type.set_udt_id(type1.get_udt_id())); + ObExprResType &null_type = type1.is_null() ? type1 : type2; + ObExprResType &res_type = !type1.is_null() ? type1 : type2; + CK ((type1.get_udt_id() == type2.get_udt_id()) || type1.is_null() || type2.is_null()); + OX (type.set_udt_id(res_type.get_udt_id())); + if (null_type.is_null()) { + OX (null_type.set_calc_accuracy(res_type.get_accuracy())); + } } else if (type.is_temporal_type()) { type.set_scale(0); } else if (type.is_user_defined_sql_type()) { @@ -383,13 +388,13 @@ int ObExprNvlUtil::calc_nvl_expr(const ObExpr &expr, ObEvalCtx &ctx, // nvl(arg0, arg1) ObDatum *arg0 = NULL; ObDatum *arg1 = NULL; - bool is_udt_type = lib::is_oracle_mode() && expr.args_[0]->obj_meta_.is_ext(); + bool is_udt_type = lib::is_oracle_mode() && expr.obj_meta_.is_ext(); bool v = false; if (OB_FAIL(expr.eval_param_value(ctx, arg0, arg1))) { LOG_WARN("eval args failed", K(ret)); } else if (OB_FAIL(pl::ObPLDataType::datum_is_null(arg0, is_udt_type, v))) { - LOG_WARN("check complex value is null not support"); + LOG_WARN("failed to check datum null", K(ret), K(arg0), K(is_udt_type)); } else if (!v) { res_datum.set_datum(*arg0); } else { @@ -408,7 +413,7 @@ int ObExprNvlUtil::calc_nvl_expr_batch(const ObExpr &expr, ObBitVector &eval_flags = expr.get_evaluated_flags(ctx); ObDatumVector args0; ObDatumVector args1; - bool is_udt_type = lib::is_oracle_mode() && expr.args_[0]->obj_meta_.is_ext(); + bool is_udt_type = lib::is_oracle_mode() && expr.obj_meta_.is_ext(); bool v = false; if (OB_FAIL(expr.eval_batch_param_value(ctx, skip, batch_size, args0, args1))) { @@ -422,7 +427,7 @@ int ObExprNvlUtil::calc_nvl_expr_batch(const ObExpr &expr, ObDatum *arg0 = args0.at(i); ObDatum *arg1 = args1.at(i); if (OB_FAIL(pl::ObPLDataType::datum_is_null(arg0, is_udt_type, v))) { - LOG_WARN("check complex value is null not support"); + LOG_WARN("failed to check datum null", K(ret), K(arg0), K(is_udt_type)); } else if (!v) { results[i].set_datum(*arg0); } else { @@ -442,13 +447,13 @@ int ObExprNvlUtil::calc_nvl_expr2(const ObExpr &expr, ObEvalCtx &ctx, ObDatum *arg0 = NULL; ObDatum *arg1 = NULL; ObDatum *arg2 = NULL; - bool is_udt_type = lib::is_oracle_mode() && expr.args_[0]->obj_meta_.is_ext(); + bool is_udt_type = lib::is_oracle_mode() && expr.obj_meta_.is_ext(); bool v = false; if (OB_FAIL(expr.eval_param_value(ctx, arg0, arg1, arg2))) { LOG_WARN("eval args failed", K(ret)); } else if (OB_FAIL(pl::ObPLDataType::datum_is_null(arg0, is_udt_type, v))) { - LOG_WARN("check complex value is null not support"); + LOG_WARN("failed to check datum null", K(ret), K(arg0), K(is_udt_type)); } else if (!v) { res_datum.set_datum(*arg1); } else { diff --git a/src/sql/engine/expr/ob_expr_nvl2_oracle.cpp b/src/sql/engine/expr/ob_expr_nvl2_oracle.cpp index 016a61ecb..deb83e163 100644 --- a/src/sql/engine/expr/ob_expr_nvl2_oracle.cpp +++ b/src/sql/engine/expr/ob_expr_nvl2_oracle.cpp @@ -67,7 +67,7 @@ int ObExprNvl2Oracle::calc_nvl2_oracle_expr_batch(const ObExpr &expr, ObDatum *arg1 = args1.at(i); ObDatum *arg2 = args2.at(i); if (OB_FAIL(pl::ObPLDataType::datum_is_null(arg0, is_udt_type, v))) { - LOG_WARN("check complex value is null not support"); + LOG_WARN("failed to check datum null", K(ret), K(arg0), K(is_udt_type)); } else if (!v) { results[i].set_datum(*arg1); } else { diff --git a/src/sql/engine/expr/ob_expr_nvl_promotion.map b/src/sql/engine/expr/ob_expr_nvl_promotion.map index 1dc784722..c93d6eaf6 100644 --- a/src/sql/engine/expr/ob_expr_nvl_promotion.map +++ b/src/sql/engine/expr/ob_expr_nvl_promotion.map @@ -1008,7 +1008,7 @@ static const ObObjType NVL_TYPE_PROMOTION_ORACLE[ObMaxTC][ObMaxTC] = ObMaxType,/*time*/ ObMaxType,/*year*/ ObVarcharType,/*string*/ - ObMaxType,/*extend*/ + ObExtendType,/*extend*/ ObMaxType,/*unknown*/ ObLongTextType,/*text*/ ObMaxType,/*bit*/ @@ -1359,7 +1359,7 @@ static const ObObjType NVL_TYPE_PROMOTION_ORACLE[ObMaxTC][ObMaxTC] = }, { /*extend -> XXX*/ - ObMaxType,/*null*/ + ObExtendType,/*null*/ ObMaxType,/*int*/ ObMaxType,/*uint*/ ObMaxType,/*float*/ diff --git a/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp b/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp index 7e8725788..def2add6f 100644 --- a/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp @@ -4043,6 +4043,10 @@ int ObRawExprDeduceType::try_add_cast_expr_above_for_deduce_type(ObRawExpr &expr : dst_type.get_calc_accuracy().get_accuracy(); cast_dst_type.set_udt_id(udt_id); } + if (lib::is_oracle_mode() && cast_dst_type.is_ext()) { + uint64_t udt_id = dst_type.is_ext() ? dst_type.get_udt_id() : dst_type.get_calc_accuracy().get_accuracy(); + cast_dst_type.set_udt_id(udt_id); + } // 这里仅设置部分情况的accuracy,其他情况的accuracy信息交给cast类型推导设置 if (lib::is_mysql_mode() && cast_dst_type.is_string_type() && cast_dst_type.has_result_flag(ZEROFILL_FLAG)) {