fix:dml with multivalue index

This commit is contained in:
obdev
2024-11-11 04:44:23 +00:00
committed by ob-robot
parent 4f1bf0cf64
commit acba5dcdcd
4 changed files with 96 additions and 70 deletions

View File

@ -280,7 +280,30 @@ int ObDropFTSIndexTask::check_switch_succ()
&& OB_FAIL(schema_guard.check_table_exist(tenant_id_, rowkey_doc_.table_id_, is_rowkey_doc_exist))) {
LOG_WARN("fail to check table exist", K(ret), K(tenant_id_), K(rowkey_doc_));
} else if (!is_domain_index_exist && !is_doc_word_exist && !is_rowkey_doc_exist && !is_doc_rowkey_exist) {
task_status_ = ObDDLTaskStatus::SUCCESS;
uint64_t doc_id_col_id = OB_INVALID_ID;
uint64_t ft_col_id = OB_INVALID_ID;
const ObTableSchema *data_table_schema = nullptr;
bool has_fts_index = false;
bool has_multivalue_index = false;
int tmp_ret = schema_guard.get_table_schema(tenant_id_, object_id_, data_table_schema);
if (tmp_ret != OB_SUCCESS) {
} else if (OB_ISNULL(data_table_schema)) {
} else if ((tmp_ret = data_table_schema->check_has_fts_index(schema_guard, has_fts_index))!= OB_SUCCESS) {
} else if ((tmp_ret = data_table_schema->check_has_multivalue_index(schema_guard, has_multivalue_index))!= OB_SUCCESS) {
} else if (!has_fts_index && !has_multivalue_index
&& (tmp_ret = data_table_schema->get_fulltext_column_ids(doc_id_col_id, ft_col_id)) != OB_SUCCESS) {
}
// 主表存在,并且fts,multivalue索引不存在了,doc-id列从主表中移除
// 否则可能出现小概率的dml的时候,schema没有刷新,导致cg阶段多了doc-id列
if (tmp_ret == OB_SUCCESS
&& OB_ISNULL(data_table_schema)
&& doc_id_col_id != OB_INVALID_ID) {
// do nothing
} else {
task_status_ = ObDDLTaskStatus::SUCCESS;
}
}
return ret;
}
@ -529,7 +552,11 @@ int ObDropFTSIndexTask::create_drop_doc_rowkey_task()
int ObDropFTSIndexTask::succ()
{
return cleanup();
int ret = OB_SUCCESS;
if (OB_FAIL(cleanup())) {
LOG_WARN("cleanup task failed", K(ret));
}
return ret;
}
int ObDropFTSIndexTask::fail()

View File

@ -52,7 +52,7 @@ public:
error_type_(0),
is_empty_default_const_(false),
is_error_default_const_(false),
is_alias_(false),
is_asis_(false),
is_multivalue_(false),
empty_val_(),
error_val_(),
@ -76,7 +76,7 @@ public:
int8_t error_type_;
bool is_empty_default_const_;
bool is_error_default_const_;
bool is_alias_;
bool is_asis_;
bool is_multivalue_;
ObDatum *empty_val_;
ObDatum *error_val_;

View File

@ -240,7 +240,6 @@ int ObExprJsonQuery::eval_json_query(const ObExpr &expr, ObEvalCtx &ctx, ObDatum
is_cover_by_error = false;
LOG_WARN("fail to init param ctx", K(ret));
} else if (OB_ISNULL(param_ctx->json_param_.json_path_)
&& !param_ctx->json_param_.is_alias_
&& OB_FAIL(ObJsonUtil::get_json_path(expr.args_[JSN_QUE_PATH], ctx, // parse json path
is_null_result, param_ctx,
temp_allocator, is_cover_by_error))) { // ctx_cache->path_cache_
@ -250,14 +249,12 @@ int ObExprJsonQuery::eval_json_query(const ObExpr &expr, ObEvalCtx &ctx, ObDatum
is_cover_by_error))) {
// get clause param value, set into param_ctx
LOG_WARN("fail to parse clause value", K(ret));
} else if (!param_ctx->json_param_.is_multivalue_ && param_ctx->json_param_.is_alias_) {
is_null_result = true;
} else if (OB_FAIL(ObJsonUtil::get_json_doc(expr.args_[JSN_QUE_DOC], ctx, temp_allocator,
j_base, is_null_result,
is_cover_by_error, true))) { // parse json doc
LOG_WARN("get_json_doc failed", K(ret));
} else if (param_ctx->json_param_.json_path_ == nullptr) { // do seek
if (param_ctx->json_param_.is_alias_ && param_ctx->json_param_.is_multivalue_) {
if (param_ctx->json_param_.is_asis_) {
if (OB_FAIL(hits.push_node(j_base))) {
LOG_WARN("fail to store j-doc", K(ret));
}
@ -278,7 +275,7 @@ int ObExprJsonQuery::eval_json_query(const ObExpr &expr, ObEvalCtx &ctx, ObDatum
ObCollationType dst_coll_type = expr.datum_meta_.cs_type_;
ObJsonCastParam cast_param(param_ctx->json_param_.dst_type_, in_coll_type, dst_coll_type, 0);
bool is_multivalue = param_ctx->json_param_.is_multivalue_;
bool is_alias = param_ctx->json_param_.is_alias_;
bool is_asis = param_ctx->json_param_.is_asis_;
// fill output
if (OB_FAIL(ret)) {
@ -289,10 +286,9 @@ int ObExprJsonQuery::eval_json_query(const ObExpr &expr, ObEvalCtx &ctx, ObDatum
}
LOG_WARN("json_query failed", K(ret));
} else if (is_null_result) {
// ToDo: need check is_multivalue?
res.set_null();
if (is_multivalue &&
OB_FAIL(set_multivalue_result(ctx, temp_allocator, nullptr, expr,
if (is_asis &&
OB_FAIL(set_multivalue_result(is_multivalue, ctx, temp_allocator, nullptr, expr,
param_ctx->json_param_.error_type_,
in_coll_type, dst_coll_type,
param_ctx->json_param_.error_val_,
@ -329,8 +325,8 @@ int ObExprJsonQuery::eval_json_query(const ObExpr &expr, ObEvalCtx &ctx, ObDatum
}
if (try_set_error_val(&temp_allocator, ctx, &param_ctx->json_param_, expr, res, ret)) {
} else if (is_multivalue) {
if (OB_FAIL(set_multivalue_result(ctx, temp_allocator, jb_res, expr,
} else if (is_asis) {
if (OB_FAIL(set_multivalue_result(is_multivalue, ctx, temp_allocator, jb_res, expr,
param_ctx->json_param_.error_type_,
in_coll_type, dst_coll_type,
param_ctx->json_param_.error_val_,
@ -344,46 +340,34 @@ int ObExprJsonQuery::eval_json_query(const ObExpr &expr, ObEvalCtx &ctx, ObDatum
} else if (is_json_arr) {
ObJsonArray j_arr_var(&temp_allocator);
jb_empty = &j_arr_var;
if (is_multivalue || is_alias) {
if (!is_multivalue) {
res.set_null();
} else {
ret = set_multivalue_result(ctx, temp_allocator, jb_empty, expr,
if (is_multivalue || is_asis) {
ret = set_multivalue_result(is_multivalue, ctx, temp_allocator, jb_empty, expr,
param_ctx->json_param_.error_type_,
in_coll_type, dst_coll_type,
param_ctx->json_param_.error_val_,
param_ctx->json_param_.accuracy_, cast_param, res);
}
} else {
ret = set_result(&param_ctx->json_param_, jb_empty, &temp_allocator, ctx, expr, res);
}
} else if (is_json_obj) {
ObJsonObject j_obj_var(&temp_allocator);
jb_empty = &j_obj_var;
if (is_multivalue || is_alias) {
if (!is_multivalue) {
res.set_null();
} else {
ret = set_multivalue_result(ctx, temp_allocator, jb_empty, expr,
param_ctx->json_param_.error_type_,
in_coll_type, dst_coll_type,
param_ctx->json_param_.error_val_,
param_ctx->json_param_.accuracy_, cast_param, res);
}
if (is_multivalue || is_asis) {
ret = set_multivalue_result(is_multivalue, ctx, temp_allocator, jb_empty, expr,
param_ctx->json_param_.error_type_,
in_coll_type, dst_coll_type,
param_ctx->json_param_.error_val_,
param_ctx->json_param_.accuracy_, cast_param, res);
} else {
ret = set_result(&param_ctx->json_param_, jb_empty, &temp_allocator, ctx, expr, res);
}
} else {
if (is_multivalue || is_alias) {
if (!is_multivalue) {
res.set_null();
} else {
ret = set_multivalue_result(ctx, temp_allocator, hits[0], expr,
if (is_multivalue || is_asis) {
ret = set_multivalue_result(is_multivalue, ctx, temp_allocator, hits[0], expr,
param_ctx->json_param_.error_type_,
in_coll_type, dst_coll_type,
param_ctx->json_param_.error_val_,
param_ctx->json_param_.accuracy_, cast_param, res);
}
} else {
ret = set_result(&param_ctx->json_param_, hits[0], &temp_allocator, ctx, expr, res);
}
@ -426,7 +410,8 @@ int ObExprJsonQuery::check_enable_cast_index_array(ObIJsonBase* json_base, bool
return ret;
}
int ObExprJsonQuery::set_multivalue_result(ObEvalCtx& ctx,
int ObExprJsonQuery::set_multivalue_result(bool is_result_array,
ObEvalCtx& ctx,
ObIAllocator& allocator,
ObIJsonBase* origin_result,
const ObExpr &expr,
@ -452,6 +437,8 @@ int ObExprJsonQuery::set_multivalue_result(ObEvalCtx& ctx,
ObAccuracy accuracy = origin_accuracy;
ObIJsonBase* json_base = nullptr;
ObObj tmp_obj;
ObObj* object_ptr = &tmp_obj;
if (OB_FAIL(expr.args_[2]->eval(ctx, opt_type))) {
LOG_WARN("eval dst type datum failed", K(ret));
@ -499,14 +486,15 @@ int ObExprJsonQuery::set_multivalue_result(ObEvalCtx& ctx,
ObJsonBin tmp;
ObIJsonBase* iter = &tmp;
ObObj *tmp_array_obj = new (obj_array + i) ObObj();
ObObj *tmp_obj = tmp_array_obj;
ObObj *temp_obj = tmp_array_obj;
object_ptr = temp_obj;
if (OB_FAIL(json_base->get_array_element(i, iter))) {
LOG_WARN("get json array element failed", K(ret));
} else if (OB_FAIL(check_enable_cast_index_array(iter, true, dest_type))) {
LOG_WARN("failed to check index array size", K(ret));
} else if (OB_FAIL(ObJsonUtil::cast_json_scalar_to_sql_obj(&allocator, ctx, iter, dst_collation,
accuracy, dest_type, scale, *tmp_obj))) {
accuracy, dest_type, scale, *temp_obj))) {
LOG_WARN("failed to cast to res", K(ret), K(dest_type));
ret = OB_ERR_JSON_VALUE_CAST_FUNCTION_INDEX;
LOG_USER_ERROR(OB_ERR_JSON_VALUE_CAST_FUNCTION_INDEX);
@ -514,7 +502,7 @@ int ObExprJsonQuery::set_multivalue_result(ObEvalCtx& ctx,
}
// 2. do sort
if (OB_SUCC(ret) && OB_NOT_NULL(obj_array)) {
if (OB_SUCC(ret) && is_result_array && OB_NOT_NULL(obj_array)) {
lib::ObMallocHookAttrGuard malloc_guard(lib::ObMemAttr(ObXMLExprHelper::get_tenant_id(ctx.exec_ctx_.get_my_session()), "JSONMultivalue"));
ObJsonObjectCompare cmp;
lib::ob_sort(obj_array, obj_array + element_count, cmp);
@ -522,51 +510,50 @@ int ObExprJsonQuery::set_multivalue_result(ObEvalCtx& ctx,
uint32_t real_store_count = 0;
ObObj *last_obj = nullptr;
for (int i = 0; OB_SUCC(ret) && i < element_count; ++i) {
ObObj *tmp_obj = obj_array + i;
for (int i = 0; OB_SUCC(ret) && is_result_array && i < element_count; ++i) {
ObObj *temp_obj = obj_array + i;
int64_t pos = str_buff.length();
if (ob_is_numeric_type(dest_type) || ob_is_temporal_type(dest_type)) {
tmp_obj->set_collation_level(CS_LEVEL_NUMERIC);
temp_obj->set_collation_level(CS_LEVEL_NUMERIC);
} else {
tmp_obj->set_collation_level(CS_LEVEL_IMPLICIT);
temp_obj->set_collation_level(CS_LEVEL_IMPLICIT);
}
// Remove duplicates
int obj_cmp_ret = 0;
if (OB_ISNULL(last_obj)) {
++real_store_count;
last_obj = tmp_obj;
last_obj = temp_obj;
} else {
bool is_case_comp = last_obj->is_string_type() && tmp_obj->is_string_type();
if (is_case_comp && OB_FAIL(last_obj->compare(*tmp_obj, CS_TYPE_UTF8MB4_GENERAL_CI, obj_cmp_ret))) {
LOG_WARN("failed compare obobj data", K(ret), K(*last_obj), K(*tmp_obj));
} else if (!is_case_comp && OB_FAIL(last_obj->compare(*tmp_obj, obj_cmp_ret))) {
LOG_WARN("failed compare obobj data", K(ret), K(*last_obj), K(*tmp_obj));
bool is_case_comp = last_obj->is_string_type() && temp_obj->is_string_type();
if (is_case_comp && OB_FAIL(last_obj->compare(*temp_obj, CS_TYPE_UTF8MB4_GENERAL_CI, obj_cmp_ret))) {
LOG_WARN("failed compare obobj data", K(ret), K(*last_obj), K(*temp_obj));
} else if (!is_case_comp && OB_FAIL(last_obj->compare(*temp_obj, obj_cmp_ret))) {
LOG_WARN("failed compare obobj data", K(ret), K(*last_obj), K(*temp_obj));
} else if (obj_cmp_ret == 0) { // ObCmpRes::CR_EQ
continue;
} else {
last_obj = tmp_obj;
last_obj = temp_obj;
++real_store_count;
}
}
if (OB_FAIL(ret)) {
} else if (FALSE_IT(reserve_len = tmp_obj->get_serialize_size())) {
} else if (FALSE_IT(reserve_len = temp_obj->get_serialize_size())) {
} else if (OB_FAIL(str_buff.reserve(reserve_len + 128))) {
LOG_WARN("failed to reserve size", K(ret), K(reserve_len));
} else if (OB_FAIL(tmp_obj->serialize(str_buff.ptr(), str_buff.capacity(), pos))) {
} else if (OB_FAIL(temp_obj->serialize(str_buff.ptr(), str_buff.capacity(), pos))) {
LOG_WARN("failed to serialize datum", K(ret), K(reserve_len));
} else {
str_buff.set_length(pos);
}
}
if (OB_SUCC(ret)) {
if (OB_SUCC(ret) && is_result_array) {
// update real element count
*reinterpret_cast<uint32_t*>(str_buff.ptr()) = real_store_count;
}
} else if (element_count > 0) {
ObObj tmp_obj;
int64_t pos = str_buff.length();
if (ob_is_numeric_type(dest_type) || ob_is_temporal_type(dest_type)) {
@ -593,30 +580,41 @@ int ObExprJsonQuery::set_multivalue_result(ObEvalCtx& ctx,
} else {
// empty result, set a minimal
ObObj tmp_obj;
tmp_obj.set_type(dest_type);
tmp_obj.set_collation_type(dst_collation);
tmp_obj.set_scale(scale);
ObObj temp_obj;
temp_obj.set_type(dest_type);
temp_obj.set_collation_type(dst_collation);
temp_obj.set_scale(scale);
if (ob_is_number_or_decimal_int_tc(dest_type)) {
tmp_obj.set_null();
temp_obj.set_null();
} else {
tmp_obj.set_min_value();
temp_obj.set_min_value();
}
int64_t pos = str_buff.length();
uint64_t reserve_len = 0;
if (FALSE_IT(reserve_len = tmp_obj.get_serialize_size())) {
if (FALSE_IT(reserve_len = temp_obj.get_serialize_size())) {
} else if (OB_FAIL(str_buff.reserve(reserve_len + 128))) {
LOG_WARN("failed to reserve size", K(ret), K(reserve_len));
} else if (OB_FAIL(tmp_obj.serialize(str_buff.ptr(), str_buff.capacity(), pos))) {
} else if (OB_FAIL(temp_obj.serialize(str_buff.ptr(), str_buff.capacity(), pos))) {
LOG_WARN("failed to serialize datum", K(ret), K(reserve_len));
} else {
str_buff.set_length(pos);
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(ret)) {
} else if (!is_result_array) {
ObObjDatumMapType type = ObDatum::get_obj_datum_map_type(dest_type);
if (element_count == 0) {
res.set_null();
} else if (OB_ISNULL(object_ptr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed get object", K(ret));
} else if (OB_FAIL(res.from_obj(*object_ptr, type))) {
LOG_WARN("failed from object", K(ret), K(*object_ptr));
}
} else {
apaque.set_value(str_buff.string());
if (OB_FAIL(apaque.get_raw_binary(str_bin, &allocator))) {
LOG_WARN("json extarct get result binary failed", K(ret));
@ -641,7 +639,7 @@ int ObExprJsonQuery::init_ctx_var(ObJsonParamCacheCtx*& param_ctx, ObEvalCtx &ct
// parse asis
if (OB_FAIL(ObJsonExprHelper::get_clause_opt(expr.args_[JSN_QUE_ASIS], ctx, val))) {
LOG_WARN("fail to get clause option", K(ret));
} else if (FALSE_IT(param_ctx->json_param_.is_alias_ = val)) {
} else if (FALSE_IT(param_ctx->json_param_.is_asis_ = val)) {
} else if (OB_NOT_NULL(info)
&& OB_FAIL(extract_plan_cache_param(info, param_ctx->json_param_))) {
LOG_WARN("fail to extract param from plan cache", K(ret));
@ -750,7 +748,7 @@ int ObExprJsonQuery::check_params_valid(const ObExpr &expr,
json_param->dst_type_, expr.datum_meta_.cs_type_, JSON_QUERY_EXPR))) {
is_cover_by_error = false;
LOG_WARN("check item func with return type fail", K(ret));
} else if ( !json_param->is_alias_
} else if ( !json_param->is_asis_
&&json_param->dst_type_ != ObVarcharType
&& json_param->dst_type_ != ObLongTextType
&& json_param->dst_type_ != ObJsonType) {
@ -819,7 +817,7 @@ int ObExprJsonQuery::get_clause_param_value(const ObExpr &expr,
json_param->empty_type_ = param_vec[JSN_QUE_EMPTY_OPT];
json_param->on_mismatch_.push_back(param_vec[JSN_QUE_MISMATCH_OPT]);
// ToDo: double check
json_param->is_alias_ = param_vec[JSN_QUE_ASIS_OPT] > 0;
json_param->is_asis_ = param_vec[JSN_QUE_ASIS_OPT] > 0;
json_param->is_multivalue_ = param_vec[JSN_QUE_MULTIVALUE_OPT] > 0;
if (json_param->is_multivalue_) {
json_param->dst_type_ = ObJsonType;
@ -862,7 +860,7 @@ int ObExprJsonQuery::doc_do_seek(ObIJsonBase* j_base,
is_null_result = true;
}
} else {
if (json_param->is_multivalue_ && json_param->json_path_->can_match_many()) {
if (json_param->is_asis_ && json_param->json_path_->can_match_many()) {
use_wrapper = 1;
} else if (OB_FAIL(get_single_obj_wrapper(json_param->wrapper_, use_wrapper, hits[0]->json_type(), json_param->scalars_type_))) {
is_cover_by_error = true;
@ -883,7 +881,7 @@ int ObExprJsonQuery::doc_do_seek(ObIJsonBase* j_base,
}
} else if (hits.size() > 1) {
// return val decide by wrapper option
if (json_param->is_multivalue_) {
if (json_param->is_asis_) {
use_wrapper = 1;
} else if (OB_FAIL(get_multi_scalars_wrapper_type(json_param->wrapper_, use_wrapper))) {
is_cover_by_error = true;

View File

@ -66,7 +66,8 @@ private:
ObEvalCtx& ctx,
ObObjType &dest_type,
bool &is_cover_by_error);
static int set_multivalue_result(ObEvalCtx& ctx,
static int set_multivalue_result(bool is_array,
ObEvalCtx& ctx,
ObIAllocator& allocator,
ObIJsonBase* json_base,
const ObExpr &expr,