fix:multivalue query bug

This commit is contained in:
obdev 2024-12-24 17:16:21 +00:00 committed by ob-robot
parent ed7e1c91de
commit 72e6feaf48
6 changed files with 48 additions and 178 deletions

View File

@ -2381,7 +2381,9 @@ int ObJoinOrder::add_access_filters(AccessPath *path,
ObOptimizerUtil::find_equal_expr(*range_exprs, restrict_infos.at(i))) ||
(OB_NOT_NULL(unprecise_range_exprs) &&
ObOptimizerUtil::find_equal_expr(*unprecise_range_exprs, restrict_infos.at(i)))) {
if (OB_FAIL(path->filter_.push_back(restrict_infos.at(i)))) {
if (path->est_cost_info_.index_meta_info_.is_multivalue_index_ && !deduced_expr_info.is_precise_) {
// deduced new pred for multivalue needn't add into new filter, just remain orginal filter is ok
} else if (OB_FAIL(path->filter_.push_back(restrict_infos.at(i)))) {
LOG_WARN("push back error", K(ret));
} else if (OB_FAIL(append(helper.const_param_constraints_, deduced_expr_info.const_param_constraints_))) {
LOG_WARN("append failed", K(ret));
@ -17064,49 +17066,6 @@ int ObJoinOrder::build_prefix_index_compare_expr(ObRawExpr &column_expr,
return ret;
}
int ObJoinOrder::try_get_json_generated_col_index_expr(ObRawExpr *depend_expr,
ObColumnRefRawExpr *col_expr,
ObRawExprCopier& copier,
ObRawExprFactory& expr_factory,
ObSQLSessionInfo *session_info,
ObRawExpr *&qual,
int64_t qual_pos,
ObRawExpr *&new_qual)
{
int ret = OB_SUCCESS;
if (OB_FAIL(ObRawExprUtils::replace_domain_wrapper_expr(depend_expr,
col_expr, copier, expr_factory, session_info, qual, qual_pos, new_qual))) {
LOG_WARN("failed to replace expr", K(ret));
}
for ( ++qual_pos; OB_SUCC(ret) && qual_pos < qual->get_param_count(); ++qual_pos) {
ObRawExpr *child = qual->get_param_expr(qual_pos);
ObExprEqualCheckContext equal_ctx;
equal_ctx.override_const_compare_ = true;
bool is_same = false;
if (OB_ISNULL(child)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("child is null", K(ret));
} else if (OB_FAIL(ObOptimizerUtil::get_expr_without_lossless_cast(child, child))) {
LOG_WARN("fail to get real child without lossless cast", K(ret));
} else if (OB_ISNULL(child)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("real child is null", K(ret));
} else if (depend_expr->same_as(*child, &equal_ctx)) {
if (ObRawExprUtils::is_domain_expr_need_special_replace(child, depend_expr)) {
ObRawExpr *tmp_qual = new_qual;
new_qual = nullptr;
if (OB_FAIL(ObRawExprUtils::replace_domain_wrapper_expr(depend_expr,
col_expr, copier, expr_factory, session_info, tmp_qual, qual_pos, new_qual))) {
LOG_WARN("failed to replace expr", K(ret));
}
}
}
}
return ret;
}
int ObJoinOrder::check_match_to_type(ObRawExpr *to_type_expr, ObRawExpr *candi_expr, bool &is_same, ObExprEqualCheckContext &equal_ctx) {
int ret = OB_SUCCESS;
bool is_valid = false;
@ -18826,17 +18785,18 @@ int ObJoinOrder::check_simple_expr_match_gen_col_index(ObRawExpr *expr,
} else if (OB_FAIL(get_plan()->get_stmt()->get_column_exprs(table_item->table_id_, column_exprs))) {
LOG_WARN("failed to get column exprs", K(ret));
} else {
bool is_precise_deduced = true;
for (int64_t i = 0; OB_SUCC(ret) && i < column_exprs.count(); i++) {
ObColumnRefRawExpr *gen_col_expr = column_exprs.at(i);
ObRawExpr* depend_expr = NULL;
bool cur_match = false;
int64_t matched_param_idx = -1;
ObRawExpr *from_expr = nullptr;
if (OB_ISNULL(gen_col_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("col is null", K(ret));
} else if (!gen_col_expr->is_generated_column()) {
//do nothing
} else if (OB_FAIL(check_simple_gen_col_cmp_expr(expr, gen_col_expr, dummy, matched_param_idx, cur_match))) {
} else if (OB_FAIL(check_simple_gen_col_cmp_expr(expr, gen_col_expr, dummy, from_expr, cur_match, is_precise_deduced))) {
LOG_WARN("failed to check simple gen col cmp expr", K(ret));
} else if (!cur_match) {
// do nothing
@ -18853,8 +18813,9 @@ int ObJoinOrder::check_simple_expr_match_gen_col_index(ObRawExpr *expr,
int ObJoinOrder::check_simple_gen_col_cmp_expr(ObRawExpr *expr,
ObColumnRefRawExpr *gen_col_expr,
ObIArray<ObPCConstParamInfo> &param_infos,
int64_t &matched_param_idx,
bool &is_match)
ObRawExpr *&matched_expr,
bool &is_match,
bool &is_precise_deduced)
{
int ret = OB_SUCCESS;
is_match = false;
@ -18907,8 +18868,18 @@ int ObJoinOrder::check_simple_gen_col_cmp_expr(ObRawExpr *expr,
}
}
if (OB_SUCC(ret) && is_same) {
matched_param_idx = i;
is_match = true;
matched_expr = param_expr;
if (depend_expr->is_multivalue_define_json_expr() && param_expr->is_domain_json_expr()) {
ObRawExpr *expr = ObRawExprUtils::skip_inner_added_expr(param_expr);
if (OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("param expr is null", K(ret));
} else {
matched_expr = expr->get_json_domain_param_expr();
is_precise_deduced = false;
}
}
// collect param constraints
for(int64_t i = 0; OB_SUCC(ret) && i < equal_ctx.param_expr_.count(); i++) {
int64_t param_idx = equal_ctx.param_expr_.at(i).param_idx_;
@ -18940,6 +18911,7 @@ int ObJoinOrder::deduce_common_gen_col_index_expr(ObRawExpr *pred,
ObSEArray<ObRawExpr*, 4> from_exprs;
ObSEArray<ObRawExpr*, 4> to_exprs;
ObSEArray<ObPCConstParamInfo, 4> const_param_infos;
bool is_precise_deduced = true;
if (OB_ISNULL(pred) || OB_ISNULL(table_item) || OB_ISNULL(gen_col) || OB_ISNULL(get_plan())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(ret), K(pred), K(table_item), K(gen_col));
@ -18947,25 +18919,26 @@ int ObJoinOrder::deduce_common_gen_col_index_expr(ObRawExpr *pred,
for (int64_t i = 0; OB_SUCC(ret) && i < simple_gen_col_preds.count(); i++) {
ObRawExpr *simple_pred = simple_gen_col_preds.at(i);
bool is_match = false;
int64_t matched_param_idx = -1;
ObRawExpr *from_expr = nullptr;
if (OB_ISNULL(simple_pred)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("simple pred is null", K(ret));
} else if (OB_FAIL(check_simple_gen_col_cmp_expr(simple_pred,
gen_col,
const_param_infos,
matched_param_idx,
is_match))) {
from_expr,
is_match,
is_precise_deduced))) {
LOG_WARN("failed to check simple gen col cmp expr", K(ret));
} else if (!is_match || OB_UNLIKELY(matched_param_idx < 0 || matched_param_idx >= simple_pred->get_param_count())) {
} else if (!is_match) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid argument", K(ret), K(is_match), K(matched_param_idx));
} else if (OB_ISNULL(simple_pred->get_param_expr(matched_param_idx))) {
LOG_WARN("invalid argument", K(ret), K(is_match));
} else if (OB_ISNULL(from_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("param expr is null", K(ret));
} else if (ObOptimizerUtil::find_item(from_exprs, simple_pred->get_param_expr(matched_param_idx))) {
} else if (ObOptimizerUtil::find_item(from_exprs, from_expr)) {
// do nothing
} else if (OB_FAIL(from_exprs.push_back(simple_pred->get_param_expr(matched_param_idx)))) {
} else if (OB_FAIL(from_exprs.push_back(from_expr))) {
LOG_WARN("failed to push back array", K(ret));
} else if (OB_FAIL(to_exprs.push_back(gen_col))) {
LOG_WARN("failed to push back array", K(ret));
@ -18993,7 +18966,7 @@ int ObJoinOrder::deduce_common_gen_col_index_expr(ObRawExpr *pred,
}
} else if (OB_FAIL(new_pred->pull_relation_id())) {
LOG_WARN("pullup relids and level failed", K(ret));
} else if (OB_FAIL(add_deduced_expr(new_pred, pred, true, const_param_infos))) {
} else if (OB_FAIL(add_deduced_expr(new_pred, pred, is_precise_deduced, const_param_infos))) {
LOG_WARN("push back failed", K(ret));
}
}

View File

@ -2887,8 +2887,9 @@ struct NullAwareAntiJoinInfo {
int check_simple_gen_col_cmp_expr(ObRawExpr *expr,
ObColumnRefRawExpr *gen_col_expr,
ObIArray<ObPCConstParamInfo> &param_infos,
int64_t &matched_param_idx,
bool &is_match);
ObRawExpr *&matched_expr,
bool &is_match,
bool &is_precise_deduced);
int check_simple_prefix_cmp_expr(ObRawExpr *expr,
ObColumnRefRawExpr *&column_expr,
@ -2904,14 +2905,6 @@ struct NullAwareAntiJoinInfo {
ObRawExpr *&new_pred,
PathHelper &helper);
int try_get_json_generated_col_index_expr(ObRawExpr *depend_expr,
ObColumnRefRawExpr *col_expr,
ObRawExprCopier& copier,
ObRawExprFactory& expr_factory,
ObSQLSessionInfo *session_info,
ObRawExpr *&qual,
int64_t qual_pos,
ObRawExpr *&new_qual);
int get_range_params(const Path *path,
ObIArray<ObRawExpr*> &range_exprs,
ObIArray<ObRawExpr*> &all_table_filters);

View File

@ -2816,9 +2816,11 @@ MOD '(' expr ',' expr ')'
&& expr_param->num_child_ >= 1
&& OB_NOT_NULL(expr_param->children_[0])) {
ParseNode* param = expr_param->children_[0];
if (param->type_ == T_FUN_SYS_JSON_VALUE && param->num_child_ == 2) {
path = param->children_[1];
data = param->children_[0];
if (param->type_ == T_FUN_SYS_JSON_VALUE) {
if (OB_NOT_NULL(param->children_)) {
path = param->children_[1];
data = param->children_[0];
}
} else if (param->num_child_ >= 2) {
expr_name = param->children_[0];
expr_param = param->children_[1];

View File

@ -697,13 +697,17 @@ bool ObRawExpr::is_domain_json_expr() const
bool ObRawExpr::is_multivalue_define_json_expr() const
{
bool b_ret = false;
const ObRawExpr *sub_expr = nullptr;
const ObRawExpr *asis_expr = nullptr;
const ObRawExpr *multi_expr = nullptr;
if (type_ == T_FUN_SYS_JSON_QUERY &&
get_param_count() >= 13 &&
OB_NOT_NULL(sub_expr = get_param_expr(12)) &&
sub_expr->is_const_expr()) {
const ObConstRawExpr *const_expr = static_cast<const ObConstRawExpr*>(sub_expr);
b_ret = const_expr->get_value().get_int() == 0;
OB_NOT_NULL(asis_expr = get_param_expr(8)) &&
asis_expr->is_const_expr() &&
OB_NOT_NULL(multi_expr = get_param_expr(12)) &&
multi_expr->is_const_expr()) {
const ObConstRawExpr *const_expr1 = static_cast<const ObConstRawExpr*>(asis_expr);
const ObConstRawExpr *const_expr2 = static_cast<const ObConstRawExpr*>(multi_expr);
b_ret = (const_expr1->get_value().get_int() == 1 && const_expr2->get_value().get_int() == 0);
}
return b_ret;

View File

@ -4857,96 +4857,6 @@ int ObRawExprUtils::replace_json_wrapper_expr_if_need(ObRawExpr* qual,
return ret;
}
int ObRawExprUtils::replace_qual_param_if_need(ObRawExpr* qual,
int64_t qual_idx,
ObColumnRefRawExpr *col_expr)
{
INIT_SUCC(ret);
ObRawExpr* qual_expr = nullptr;
const ObRawExpr* param_expr = nullptr;
int32_t idx = 0;
if ((qual->get_expr_type() == T_OP_BOOL
|| (OB_NOT_NULL(qual = qual->get_param_expr(qual_idx)) && qual->get_expr_type() == T_OP_BOOL))
&& OB_NOT_NULL(qual_expr = qual->get_param_expr(0))
&& qual_expr->is_domain_json_expr()) {
if (qual_expr->get_expr_type() == T_FUN_SYS_JSON_MEMBER_OF) {
if (OB_FAIL(static_cast<ObOpRawExpr *>(qual_expr)->replace_param_expr(1, col_expr))) {
LOG_WARN("replace const int expr failed", K(ret));
}
} else {
if (OB_NOT_NULL(param_expr = qual_expr->get_param_expr(0)) && param_expr->is_const_expr()) {
idx = 1;
}
if (OB_FAIL(static_cast<ObOpRawExpr *>(qual_expr)->replace_param_expr(idx, col_expr))) {
LOG_WARN("replace const int expr failed", K(ret));
}
}
}
return ret;
}
bool ObRawExprUtils::is_domain_expr_need_special_replace(ObRawExpr* qual_expr,
ObRawExpr *depend_expr)
{
bool b_ret = false;
const ObRawExpr *const_depend_expr = depend_expr;
if (depend_expr->get_expr_type() == T_FUN_SYS_CAST) {
depend_expr = depend_expr->get_param_expr(0);
b_ret = (depend_expr->get_expr_type() == T_FUN_SYS_JSON_EXTRACT || depend_expr->get_expr_type() == T_FUN_SYS_JSON_UNQUOTE)
&& qual_expr->get_expr_type() == T_FUN_SYS_JSON_EXTRACT;
} else if (depend_expr->get_expr_type() == T_FUN_SYS_JSON_QUERY) {
b_ret = qual_expr->is_domain_json_expr();
} else if (const_depend_expr->extract_multivalue_json_expr(const_depend_expr)
&& const_depend_expr->get_expr_type() == T_FUN_SYS_JSON_QUERY) {
b_ret = qual_expr->is_domain_json_expr();
}
return b_ret;
}
int ObRawExprUtils::replace_domain_wrapper_expr(ObRawExpr *depend_expr,
ObColumnRefRawExpr *col_expr,
ObRawExprCopier& copier,
ObRawExprFactory& factory,
ObSQLSessionInfo *session_info,
ObRawExpr *&qual,
int64_t qual_idx,
ObRawExpr *&new_qual)
{
INIT_SUCC(ret);
ObSEArray<ObRawExpr *, 4> column_exprs;
bool need_specific_replace = false;
if (OB_ISNULL(qual)) {
} else if (qual->get_expr_type() != T_OP_BOOL &&
qual->get_param_expr(qual_idx)->get_expr_type() != T_OP_BOOL) {
} else if (OB_FAIL(replace_json_wrapper_expr_if_need(
qual, qual_idx, depend_expr, factory, session_info, need_specific_replace))) {
LOG_WARN("failed to replace expr", K(ret));
} else if (OB_FAIL(extract_column_exprs(qual, column_exprs))) {
LOG_WARN("extract_column_exprs error", K(ret));
} else if (OB_FAIL(copier.add_skipped_expr(column_exprs))) {
LOG_WARN("failed to add skipped exprs", K(ret));
} else if (OB_FAIL(copier.copy(qual, new_qual))) {
LOG_WARN("failed to copy expr node", K(ret));
//depend_expr's res type may be diff from its column's. copy real_qual and deduce type again.
} else if (!need_specific_replace
&& OB_FAIL(static_cast<ObOpRawExpr *>(new_qual)->replace_param_expr(qual_idx, col_expr))) {
LOG_WARN("replace failed", K(ret));
} else if (need_specific_replace
&& OB_FAIL(replace_qual_param_if_need(new_qual, qual_idx, col_expr))) {
LOG_WARN("specific replace failed", K(ret));
}
return ret;
}
int ObRawExprUtils::create_substr_expr(ObRawExprFactory &expr_factory,
ObSQLSessionInfo *session_info,
ObRawExpr *first_expr,

View File

@ -595,16 +595,6 @@ public:
const ObLocalSessionVar *local_vars = NULL,
int64_t local_var_id = OB_INVALID_INDEX_INT64);
static bool is_domain_expr_need_special_replace(ObRawExpr* qual_expr,
ObRawExpr *depend_expr);
static int replace_domain_wrapper_expr(ObRawExpr *depend_expr,
ObColumnRefRawExpr *col_expr,
ObRawExprCopier& copier,
ObRawExprFactory& factory,
ObSQLSessionInfo *session_info,
ObRawExpr *&qual,
int64_t qual_idx,
ObRawExpr *&new_qual);
static int replace_json_wrapper_expr_if_need(ObRawExpr* qual,
int64_t qual_idx,
ObRawExpr *depend_expr,
@ -612,8 +602,6 @@ public:
ObSQLSessionInfo *session_info,
bool& is_done_replace);
static int replace_qual_param_if_need(ObRawExpr* qual, int64_t qual_idx, ObColumnRefRawExpr *col_expr);
static int build_pad_expr(ObRawExprFactory &expr_factory,
bool is_char,
const share::schema::ObColumnSchemaV2 *column_schema,