diff --git a/src/pl/ob_pl.cpp b/src/pl/ob_pl.cpp index 3bbb05be54..9f701da6c9 100644 --- a/src/pl/ob_pl.cpp +++ b/src/pl/ob_pl.cpp @@ -2559,7 +2559,7 @@ int ObPLExecState::set_var(int64_t var_idx, const ObObjParam& value) && params->at(var_idx).is_pl_extend() && params->at(var_idx).get_ext() != 0 && params->at(var_idx).get_meta().get_extend_type() != PL_REF_CURSOR_TYPE) { - OZ (ObUserDefinedType::destruct_obj(params->at(var_idx), ctx_.exec_ctx_->get_my_session(), false)); + OZ (ObUserDefinedType::destruct_obj(params->at(var_idx), ctx_.exec_ctx_->get_my_session())); } if (OB_FAIL(ret)) { diff --git a/src/pl/ob_pl_package_state.cpp b/src/pl/ob_pl_package_state.cpp index d398ff9583..45589f3323 100644 --- a/src/pl/ob_pl_package_state.cpp +++ b/src/pl/ob_pl_package_state.cpp @@ -211,7 +211,7 @@ int ObPLPackageState::set_package_var_val(const int64_t var_idx, const ObObj &va && types_.at(var_idx) != PL_CURSOR_TYPE && types_.at(var_idx) != PL_REF_CURSOR_TYPE) { CK (vars_.at(var_idx).get_ext() != 0); - OZ (ObUserDefinedType::destruct_obj(vars_.at(var_idx), NULL, false)); + OZ (ObUserDefinedType::destruct_obj(vars_.at(var_idx), NULL)); } else { vars_.at(var_idx) = value; } diff --git a/src/pl/ob_pl_user_type.cpp b/src/pl/ob_pl_user_type.cpp index aca19f556a..22b767ceb5 100644 --- a/src/pl/ob_pl_user_type.cpp +++ b/src/pl/ob_pl_user_type.cpp @@ -311,7 +311,7 @@ int ObUserDefinedType::deep_copy_obj( return ret; } -int ObUserDefinedType::destruct_obj(ObObj &src, ObSQLSessionInfo *session, bool set_null) +int ObUserDefinedType::destruct_obj(ObObj &src, ObSQLSessionInfo *session) { int ret = OB_SUCCESS; @@ -334,9 +334,9 @@ int ObUserDefinedType::destruct_obj(ObObj &src, ObSQLSessionInfo *session, bool ObPLRecord *record = reinterpret_cast(src.get_ext()); CK (OB_NOT_NULL(record)); for (int64_t i = 0; OB_SUCC(ret) && i < record->get_count(); ++i) { - OZ (SMART_CALL(destruct_obj(record->get_element()[i], session, set_null))); + OZ (SMART_CALL(destruct_obj(record->get_element()[i], session))); } - OX (set_null ? src.set_null() : record->set_null()); + OX (record->set_null()); } break; #ifdef OB_BUILD_ORACLE_PL @@ -347,7 +347,7 @@ int ObUserDefinedType::destruct_obj(ObObj &src, ObSQLSessionInfo *session, bool CK (OB_NOT_NULL(collection)); if (OB_SUCC(ret) && OB_NOT_NULL(collection->get_allocator())) { for (int64_t i = 0; OB_SUCC(ret) && i < collection->get_count(); ++i) { - OZ (SMART_CALL(destruct_obj(collection->get_data()[i], session, set_null))); + OZ (SMART_CALL(destruct_obj(collection->get_data()[i], session))); } } if (OB_SUCC(ret)) { @@ -367,7 +367,7 @@ int ObUserDefinedType::destruct_obj(ObObj &src, ObSQLSessionInfo *session, bool collection->set_count(-1); collection->set_first(OB_INVALID_INDEX); collection->set_last(OB_INVALID_INDEX); - set_null ? src.set_null() : collection->set_null(); + collection->set_null(); if (collection->is_associative_array() && OB_NOT_NULL(assoc = static_cast(collection))) { assoc->set_key(NULL); @@ -398,6 +398,111 @@ int ObUserDefinedType::destruct_obj(ObObj &src, ObSQLSessionInfo *session, bool return ret; } +int ObUserDefinedType::alloc_sub_composite(ObObj &dest_element, ObIAllocator &allocator) +{ + int ret = OB_SUCCESS; + +#define COPY_SUB_COLLECTION(TYPE) \ + do { \ + if (OB_ISNULL(dest_composite = reinterpret_cast(allocator.alloc(old_composite->get_init_size())))) { \ + ret = OB_ALLOCATE_MEMORY_FAILED; \ + LOG_WARN("failed to alloc memory for collection", K(ret)); \ + } else { \ + TYPE *collection = static_cast(dest_composite); \ + CK (OB_NOT_NULL(collection)); \ + LOG_INFO("src is: ", KP(old_composite), KP(dest_composite), K(old_composite->get_init_size())); \ + OX (new(collection)TYPE(old_composite->get_id())); \ + } \ + } while (0) + + if (dest_element.is_ext() && dest_element.get_meta().get_extend_type() != PL_OPAQUE_TYPE) { + ObPLComposite *old_composite = reinterpret_cast(dest_element.get_ext()); + ObPLComposite *dest_composite = nullptr; + CK (OB_NOT_NULL(old_composite)); + if (OB_SUCC(ret)) { + switch (old_composite->get_type()) { + case PL_RECORD_TYPE: { + ObPLRecord *composite = NULL; + dest_composite = reinterpret_cast(allocator.alloc(old_composite->get_init_size())); + composite = static_cast(dest_composite); + if (OB_ISNULL(composite)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("allocate composite memory failed", K(ret)); + } + OX (new(composite)ObPLRecord(old_composite->get_id(), static_cast(old_composite)->get_count())); + } + break; +#ifdef OB_BUILD_ORACLE_PL + case PL_NESTED_TABLE_TYPE: { + COPY_SUB_COLLECTION(ObPLNestedTable); + } + break; + case PL_ASSOCIATIVE_ARRAY_TYPE: { + COPY_SUB_COLLECTION(ObPLAssocArray); + } + break; + case PL_VARRAY_TYPE: { + COPY_SUB_COLLECTION(ObPLVArray); + } + break; +#endif + default: { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("Unexpected type to destruct", K(dest_element), K(dest_element.get_meta().get_extend_type()), K(ret)); + } + break; + } + OX (dest_element.set_extend(reinterpret_cast(dest_composite), + dest_element.get_meta().get_extend_type(), + dest_element.get_val_len())); + } + } +#undef COPY_SUB_COLLECTION + return ret; +} + +int ObUserDefinedType::alloc_for_second_level_composite(ObObj &src, ObIAllocator &allocator) +{ + int ret = OB_SUCCESS; + + if (src.is_pl_extend()) { + switch (src.get_meta().get_extend_type()) { + case PL_RECORD_TYPE: { + ObPLRecord *record = reinterpret_cast(src.get_ext()); + CK (OB_NOT_NULL(record)); + for (int64_t i = 0; OB_SUCC(ret) && i < record->get_count(); ++i) { + ObObj *dest_element = nullptr; + OZ (record->get_element(i, dest_element)); + CK (OB_NOT_NULL(dest_element)); + OZ (alloc_sub_composite(*dest_element, allocator)); + } + } + break; +#ifdef OB_BUILD_ORACLE_PL + case PL_NESTED_TABLE_TYPE: //fallthrough + case PL_ASSOCIATIVE_ARRAY_TYPE: //fallthrough + case PL_VARRAY_TYPE: { + ObPLCollection *collection = reinterpret_cast(src.get_ext()); + CK (OB_NOT_NULL(collection)); + if (OB_SUCC(ret) && OB_NOT_NULL(collection->get_allocator())) { + for (int64_t i = 0; OB_SUCC(ret) && i < collection->get_count(); ++i) { + OZ (alloc_sub_composite(collection->get_data()[i], allocator)); + } + } + } + break; +#endif + default: { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("Unexpected type to destruct", K(src), K(src.get_meta().get_extend_type()), K(ret)); + } + break; + } + } + + return ret; +} + int ObUserDefinedType::serialize_obj(const ObObj &obj, char* buf, const int64_t len, int64_t& pos) { int ret = OB_SUCCESS; @@ -3224,6 +3329,7 @@ int ObPLComposite::copy_element(const ObObj &src, extend_type, src.get_val_len())); OZ (ObUserDefinedType::destruct_obj(dest, session)); + OZ (ObUserDefinedType::alloc_for_second_level_composite(dest, allocator)); OZ (ObPLComposite::deep_copy(*dest_composite, src_composite, allocator, @@ -3724,7 +3830,7 @@ int ObPLCollection::delete_collection_elem(int64_t index) ObObj *obj = static_cast(get_data()); // data的type设置为max表示被delete if (index < get_count()) { - if (OB_FAIL(ObUserDefinedType::destruct_obj(obj[index], NULL, false))) { + if (OB_FAIL(ObUserDefinedType::destruct_obj(obj[index], NULL))) { LOG_WARN("failed to destruct obj", K(ret), K(obj[index]), K(index)); } else { obj[index].set_type(ObMaxType); diff --git a/src/pl/ob_pl_user_type.h b/src/pl/ob_pl_user_type.h index b8e4927147..f1456e59d2 100644 --- a/src/pl/ob_pl_user_type.h +++ b/src/pl/ob_pl_user_type.h @@ -144,7 +144,9 @@ public: static int deep_copy_obj( ObIAllocator &allocator, const ObObj &src, ObObj &dst, bool need_new_allocator = true, bool ignore_del_element = false); - static int destruct_obj(ObObj &src, sql::ObSQLSessionInfo *session = NULL, bool set_null = true); + static int destruct_obj(ObObj &src, sql::ObSQLSessionInfo *session = NULL); + static int alloc_sub_composite(ObObj &dest_element, ObIAllocator &allocator); + static int alloc_for_second_level_composite(ObObj &src, ObIAllocator &allocator); static int serialize_obj(const ObObj &obj, char* buf, const int64_t len, int64_t& pos); static int deserialize_obj(ObObj &obj, const char* buf, const int64_t len, int64_t& pos); static int64_t get_serialize_obj_size(const ObObj &obj); diff --git a/src/sql/ob_spi.cpp b/src/sql/ob_spi.cpp index eba5f36974..75c568dbbb 100644 --- a/src/sql/ob_spi.cpp +++ b/src/sql/ob_spi.cpp @@ -4633,8 +4633,7 @@ int ObSPIService::spi_alloc_complex_var(pl::ObPLExecCtx *ctx, need_alloc = false; int tmp = OB_SUCCESS; if (OB_SUCCESS != (tmp = ObUserDefinedType::destruct_obj(ctx->params_->at(var_idx), - ctx->exec_ctx_->get_my_session(), - false))) { + ctx->exec_ctx_->get_my_session()))) { LOG_WARN("fail to destruct obj", K(tmp)); } }