diff --git a/src/pl/ob_pl_stmt.cpp b/src/pl/ob_pl_stmt.cpp index fbba3c8e4f..a74f888a98 100644 --- a/src/pl/ob_pl_stmt.cpp +++ b/src/pl/ob_pl_stmt.cpp @@ -3974,7 +3974,11 @@ int ObPLInto::generate_into_variable_info(ObPLBlockNS &ns, const ObRawExpr &expr ObDataType ext_type; ObDataType type; ObPLIntegerRange range; - ext_type.set_obj_type(ObExtendType); + ObObjMeta meta; + meta.set_type(ObExtendType); + meta.set_extend_type(final_type.get_type()); + ext_type.set_meta_type(meta); + ext_type.set_udt_id(final_type.get_user_type_id()); OZ (data_type_.push_back(ext_type)); OZ (not_null_flags_.push_back(false)); OZ (pl_integer_ranges_.push_back(range.range_)); diff --git a/src/pl/ob_pl_type.cpp b/src/pl/ob_pl_type.cpp index c68fdf82ab..7d82b574a5 100644 --- a/src/pl/ob_pl_type.cpp +++ b/src/pl/ob_pl_type.cpp @@ -1446,21 +1446,17 @@ case type: { \ return ret; } -int ObPLDataType::datum_is_null(ObDatum* param, bool is_udt_type, bool &is_null) +int ObPLDataType::obj_is_null(ObObj& obj, bool &is_null) { int ret = OB_SUCCESS; - OV(OB_NOT_NULL(param), OB_ERR_UNEXPECTED); + is_null = false; - if (OB_FAIL(ret)) { - // do nothing - } else if (!is_udt_type) { - is_null = param->is_null(); - } else if (param->is_null() || param->extend_obj_->is_null()) { + if (obj.is_null()) { is_null = true; - } else { - uint64_t ext = param->extend_obj_->get_ext(); - switch (param->extend_obj_->get_meta().get_extend_type()) { + } else if (obj.is_ext()) { + uint64_t ext = obj.get_ext(); + switch (obj.get_meta().get_extend_type()) { #ifdef OB_BUILD_ORACLE_PL case pl::PL_NESTED_TABLE_TYPE: case pl::PL_ASSOCIATIVE_ARRAY_TYPE: @@ -1476,9 +1472,10 @@ int ObPLDataType::datum_is_null(ObDatum* param, bool is_udt_type, bool &is_null) } case pl::PL_CURSOR_TYPE: case pl::PL_REF_CURSOR_TYPE: { - is_null = param->extend_obj_->get_ext() == 0; - } break; -#endif + is_null = obj.get_ext() == 0; + break; + } + #endif case pl::PL_RECORD_TYPE: { pl::ObPLRecord *rec = reinterpret_cast(ext); is_null = rec->is_null(); @@ -1486,11 +1483,34 @@ int ObPLDataType::datum_is_null(ObDatum* param, bool is_udt_type, bool &is_null) } default: { ret = OB_NOT_SUPPORTED; - LOG_WARN("check complex value is null not supported", K(ret), K(param->extend_obj_)); + LOG_WARN("check complex value is null not supported", K(ret), K(obj)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "check complex is null"); break; } } + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("check obj is null unexcepted error", K(ret), K(obj)); + } + return ret; +} + +int ObPLDataType::datum_is_null(ObDatum* param, bool is_udt_type, bool &is_null) +{ + int ret = OB_SUCCESS; + + OV(OB_NOT_NULL(param), OB_ERR_UNEXPECTED); + + if (OB_FAIL(ret)) { + // do nothing + } else if (!is_udt_type) { + is_null = param->is_null(); + } else if (param->is_null() || param->extend_obj_->is_null()) { + is_null = true; + } else { + if (OB_FAIL(ObPLDataType::obj_is_null(*(ObObj*)param->extend_obj_, is_null))) { + LOG_WARN("check obj is null failed", K(ret), K(param->extend_obj_)); + } } return ret; } diff --git a/src/pl/ob_pl_type.h b/src/pl/ob_pl_type.h index 660fce0e90..97478dce06 100644 --- a/src/pl/ob_pl_type.h +++ b/src/pl/ob_pl_type.h @@ -608,6 +608,7 @@ public: share::schema::ObRoutineInfo &routine_info); static int deep_copy_pl_type(ObIAllocator &allocator, const ObPLDataType &src, ObPLDataType *&dst); + static int obj_is_null(ObObj &obj, bool &is_null); static int datum_is_null(ObDatum* param, bool is_udt_type, bool &is_null); DECLARE_TO_STRING; diff --git a/src/sql/engine/expr/ob_expr_nvl.cpp b/src/sql/engine/expr/ob_expr_nvl.cpp index e95e73de2c..049871bd5d 100644 --- a/src/sql/engine/expr/ob_expr_nvl.cpp +++ b/src/sql/engine/expr/ob_expr_nvl.cpp @@ -307,6 +307,7 @@ int ObExprOracleNvl::calc_nvl_oralce_result_type(ObExprResType &type, 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())); + OX (type.set_extend_type(res_type.get_extend_type())); if (null_type.is_null()) { OX (null_type.set_calc_accuracy(res_type.get_accuracy())); } diff --git a/src/sql/ob_spi.cpp b/src/sql/ob_spi.cpp index 60f0bd538e..453ea1b58e 100644 --- a/src/sql/ob_spi.cpp +++ b/src/sql/ob_spi.cpp @@ -6385,6 +6385,27 @@ int ObSPIService::prepare_static_sql_params(ObPLExecCtx *ctx, return ret; } +int ObSPIService::convert_ext_null_params(ParamStore ¶ms, ObSQLSessionInfo *session) +{ + int ret = OB_SUCCESS; + bool is_ext_null = false; + + for (int64_t i = 0; OB_SUCC(ret) && i < params.count(); i++) { + if (params.at(i).is_pl_extend()) { + if (OB_FAIL(ObPLDataType::obj_is_null(params.at(i), is_ext_null))) { + LOG_WARN("check obj_is_null failed", K(ret)); + } else if (is_ext_null) { + ObObjMeta param_meta = params.at(i).get_meta(); + CK (OB_NOT_NULL(session)); + OZ (ObUserDefinedType::destruct_obj(params.at(i), session)); + OX (params.at(i).set_null()); + OX (params.at(i).set_param_meta(param_meta)); + } + } + } + return ret; +} + int ObSPIService::inner_open(ObPLExecCtx *ctx, ObIAllocator ¶m_allocator, const ObString &sql, @@ -6428,6 +6449,7 @@ int ObSPIService::inner_open(ObPLExecCtx *ctx, } CK (OB_NOT_NULL(curr_params)); + OZ (convert_ext_null_params(*curr_params, ctx->exec_ctx_->get_my_session())); OZ (inner_open(ctx, sql, ps_sql, type, *curr_params, spi_result, out_params, is_dynamic_sql)); // if failed, we need release complex parameter memory in here @@ -7692,9 +7714,15 @@ int ObSPIService::store_result(ObPLExecCtx *ctx, bool is_schema_object = (!is_type_record && 1 == type_count && 1 == obj_array.count() && - obj_array.at(0).is_pl_extend() && + ((obj_array.at(0).is_pl_extend() && obj_array.at(0).get_meta().get_extend_type() != PL_CURSOR_TYPE && - obj_array.at(0).get_meta().get_extend_type() != PL_OPAQUE_TYPE); // xmltypes may need to do cast + obj_array.at(0).get_meta().get_extend_type() != PL_OPAQUE_TYPE) || // xmltypes may need to do cast + (obj_array.at(0).is_null() && + row_desc.at(0).get_meta_type().is_ext() && + row_desc.at(0).get_meta_type().get_extend_type() > 0 && + row_desc.at(0).get_meta_type().get_extend_type() < T_EXT_SQL_ARRAY && + row_desc.at(0).get_meta_type().get_extend_type() != PL_CURSOR_TYPE && + row_desc.at(0).get_meta_type().get_extend_type() != PL_OPAQUE_TYPE))); // xmltypes may need to do cast if (!is_schema_object) { if (OB_SUCC(ret) && type_count != obj_array.count()) { ret = OB_ERR_SP_INVALID_FETCH_ARG; @@ -7753,6 +7781,24 @@ int ObSPIService::store_result(ObPLExecCtx *ctx, OZ (sql::ObExprPLIntegerChecker::check_range( calc_array->at(i), calc_array->at(i).get_type(), pl_integer_ranges[i])); } + } else if (obj_array.at(0).is_null()) { //null into extend variable,generate extend null obj + if (row_desc.at(0).get_meta_type().is_ext() && + (PL_RECORD_TYPE == row_desc.at(0).get_meta_type().get_extend_type() || + PL_NESTED_TABLE_TYPE == row_desc.at(0).get_meta_type().get_extend_type() || + PL_VARRAY_TYPE == row_desc.at(0).get_meta_type().get_extend_type())) { + int64_t udt_id = row_desc.at(0).get_udt_id(); + const ObUserDefinedType *type = nullptr; + int64_t ptr = 0; + int64_t init_size = OB_INVALID_SIZE; + ObObj tmp_obj; + OX (tmp_obj.reset()); + OZ (ctx->get_user_type(udt_id, type)); + OZ (type->newx(*cast_ctx.allocator_v2_, ctx, ptr)); + OZ (type->get_size(PL_TYPE_INIT_SIZE, init_size)); + OX (tmp_obj.set_extend(ptr, type->get_type(), init_size)); + OZ (tmp_obj_array.push_back(tmp_obj)); + OX (calc_array = &tmp_obj_array); + } } // 向变量赋值 if (OB_SUCC(ret)) { @@ -8154,7 +8200,7 @@ int ObSPIService::store_datums(ObObj &dest_addr, ObIArray &obj_array, 拷贝时,要求src id和dest id必须一致. */ CK (1 == obj_array.count()); OX (src = obj_array.at(0)); - CK (src.is_pl_extend()); + OV (src.is_pl_extend(), OB_ERR_EXPRESSION_WRONG_TYPE); OZ (check_and_deep_copy_result(*alloc, src, dest_addr)); } else { int64_t current_datum = 0; diff --git a/src/sql/ob_spi.h b/src/sql/ob_spi.h index 9bbb22f19d..251da71135 100644 --- a/src/sql/ob_spi.h +++ b/src/sql/ob_spi.h @@ -562,6 +562,8 @@ public: ObObjParam **params, ParamStore *&exec_params); + static int convert_ext_null_params(ParamStore ¶ms, ObSQLSessionInfo *session); + static int inner_open(pl::ObPLExecCtx *ctx, ObIAllocator ¶m_allocator, //用于拷贝执行期参数 const ObString &sql, diff --git a/src/sql/ob_sql.cpp b/src/sql/ob_sql.cpp index 429e63a4d6..770fb84734 100644 --- a/src/sql/ob_sql.cpp +++ b/src/sql/ob_sql.cpp @@ -873,6 +873,7 @@ int ObSql::fill_select_result_set(ObResultSet &result_set, ObSqlCtx *context, co const ObSimpleDatabaseSchema *db_schema = NULL; uint64_t udt_id = expr->get_result_type().get_udt_id(); const uint64_t tenant_id = get_tenant_id_by_object_id(udt_id); + field.type_.meta_.set_extend_type(expr->get_result_type().get_extend_type()); if (OB_FAIL(context->schema_guard_->get_udt_info(tenant_id, udt_id, udt_info))) { LOG_WARN("fail to get udt info. ", K(tenant_id), K(udt_id), K(ret)); } else if (NULL == udt_info) { diff --git a/src/sql/plan_cache/ob_cache_object.cpp b/src/sql/plan_cache/ob_cache_object.cpp index caefbe66bb..5afcf3451d 100644 --- a/src/sql/plan_cache/ob_cache_object.cpp +++ b/src/sql/plan_cache/ob_cache_object.cpp @@ -88,7 +88,7 @@ int ObPlanCacheObject::set_params_info(const ParamStore ¶ms) K(params.at(i).get_type()), K(common::lbt())); } - if (params.at(i).is_ext()) { + if (params.at(i).is_ext_sql_array()) { ObDataType data_type; if (OB_FAIL(ObSQLUtils::get_ext_obj_data_type(params.at(i), data_type))) { LOG_WARN("fail to get ext obj data type", K(ret)); @@ -97,7 +97,7 @@ int ObPlanCacheObject::set_params_info(const ParamStore ¶ms) param_info.scale_ = data_type.get_scale(); } LOG_DEBUG("ext params info", K(data_type), K(param_info), K(params.at(i))); - } else if (params.at(i).is_user_defined_sql_type() || params.at(i).is_collection_sql_type()) { + } else if (params.at(i).get_param_meta().is_ext() || params.at(i).is_user_defined_sql_type() || params.at(i).is_collection_sql_type()) { param_info.scale_ = 0; uint64_t udt_id = params.at(i).get_accuracy().get_accuracy(); *(reinterpret_cast(¶m_info.ext_real_type_)) = (udt_id >> 32) & UINT_MAX32; diff --git a/src/sql/plan_cache/ob_plan_set.cpp b/src/sql/plan_cache/ob_plan_set.cpp index a584fc4522..ead8cfd954 100644 --- a/src/sql/plan_cache/ob_plan_set.cpp +++ b/src/sql/plan_cache/ob_plan_set.cpp @@ -253,16 +253,20 @@ int ObPlanSet::match_param_info(const ObParamInfo ¶m_info, } if (param.get_collation_type() != param_info.col_type_ - && !(param.is_user_defined_sql_type() || param.is_collection_sql_type())) { + && !(param.get_param_meta().is_ext() || param.is_user_defined_sql_type() || param.is_collection_sql_type())) { is_same = false; } else if (param.get_param_meta().get_type() != param_info.type_) { is_same = false; } else if (param.is_user_defined_sql_type() || param.is_collection_sql_type()) { - uint64_t udt_id_param = param.get_accuracy().get_accuracy(); - uint64_t udt_id_info = static_cast(param_info.ext_real_type_) << 32 + if (param_info.is_oracle_null_value_) { + is_same = false; + } else { + uint64_t udt_id_param = param.get_accuracy().get_accuracy(); + uint64_t udt_id_info = static_cast(param_info.ext_real_type_) << 32 | static_cast(param_info.col_type_); - is_same = (udt_id_info == udt_id_param) ? true : false; - } else if (param.is_ext()) { + is_same = (udt_id_info == udt_id_param) ? true : false; + } + } else if (param.is_ext_sql_array()) { ObDataType data_type; if (!param_info.flag_.need_to_check_extend_type_) { // do nothing @@ -276,6 +280,16 @@ int ObPlanSet::match_param_info(const ObParamInfo ¶m_info, LOG_TRACE("ext match param info", K(data_type), K(param_info), K(is_same), K(ret)); } LOG_DEBUG("ext match param info", K(data_type), K(param_info), K(is_same), K(ret)); + } else if (param.get_param_meta().is_ext()) { + if (!param_info.flag_.need_to_check_extend_type_) { + // do nothing + } else { + uint64_t udt_id_param = param.get_accuracy().get_accuracy(); + uint64_t udt_id_info = static_cast(param_info.ext_real_type_) << 32 + | static_cast(param_info.col_type_); + is_same = (udt_id_info == udt_id_param) ? true : false; + } + LOG_DEBUG("ext match param info", K(param.get_accuracy()), K(param_info), K(is_same), K(ret)); } else if (param_info.is_oracle_null_value_ && !param.is_null()) { is_same = false; } else if (ObSQLUtils::is_oracle_null_with_normal_type(param)