fix an exec_param and a expr copy_on_replace bugs

This commit is contained in:
jingtaoye35
2024-02-09 12:25:58 +00:00
committed by ob-robot
parent 49c4063930
commit a291a8ffaf
7 changed files with 196 additions and 24 deletions

View File

@ -637,6 +637,7 @@ int ObLogSubPlanFilter::replace_nested_subquery_exprs(ObRawExprReplacer &replace
}
for (int64_t i = 0; OB_SUCC(ret) && i < subquery_exprs_.count(); ++i) {
ObRawExpr *expr = subquery_exprs_.at(i);
int64_t ref_id = subquery_exprs_.at(i)->get_ref_id();
if (ObOptimizerUtil::find_item(plan->get_onetime_query_refs(), expr)) {
// do not replace onetime expr ref query, only adjust nested subquery
} else if (OB_FAIL(replace_expr_action(replacer, expr))) {
@ -648,6 +649,7 @@ int ObLogSubPlanFilter::replace_nested_subquery_exprs(ObRawExprReplacer &replace
LOG_WARN("unexpected expr type", K(ret));
} else {
subquery_exprs_.at(i) = static_cast<ObQueryRefRawExpr*>(expr);
subquery_exprs_.at(i)->set_ref_id(ref_id);
}
}
return ret;

View File

@ -64,6 +64,8 @@ int ObAggrExprPushUpAnalyzer::analyze_and_push_up_aggr_expr(ObRawExprFactory &ex
} else if (OB_FAIL(ObTransformUtils::decorrelate(reinterpret_cast<ObRawExpr *&>(aggr_expr),
final_exec_params))) {
LOG_WARN("failed to decorrelate exec params", K(ret));
} else if (OB_FAIL(replace_final_exec_param_in_aggr(final_exec_params, param_query_refs, expr_factory))) {
LOG_WARN("failed to replace real exec param in aggr", K(ret));
}
if (OB_SUCC(ret)) {
if (OB_FAIL(final_aggr_resolver->add_aggr_expr(aggr_expr))) {
@ -444,5 +446,136 @@ int ObAggrExprPushUpAnalyzer::get_exec_params(ObDMLResolver *resolver,
return ret;
}
int ObAggrExprPushUpAnalyzer::replace_final_exec_param_in_aggr(const ObIArray<ObExecParamRawExpr *> &exec_params,
ObIArray<ObQueryRefRawExpr *> &param_query_refs,
ObRawExprFactory &expr_factory)
{
int ret = OB_SUCCESS;
ObSEArray<ObExecParamRawExpr *, 4> new_execs;
for (int64_t i = 0; OB_SUCC(ret) && i < exec_params.count(); ++i) {
ObExecParamRawExpr *new_expr = NULL;
if (OB_FAIL(ObRawExprUtils::create_new_exec_param(expr_factory,
exec_params.at(i)->get_ref_expr(),
new_expr,
false))) {
LOG_WARN("failed to create new exec param", K(ret));
} else if (OB_FAIL(new_execs.push_back(static_cast<ObExecParamRawExpr *>(new_expr)))) {
LOG_WARN("failed to push back", K(ret));
}
}
if (OB_SUCC(ret)) {
ObStmtExecParamReplacer replacer;
replacer.set_relation_scope();
if (OB_FAIL(replacer.add_replace_exprs(exec_params, new_execs))) {
LOG_WARN("failed to add replace exprs", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < param_query_refs.count(); i++) {
if (OB_FAIL(replacer.do_visit(reinterpret_cast<ObRawExpr *&>(param_query_refs.at(i))))) {
LOG_WARN("failed to replace exec param", K(ret));
}
}
}
}
return ret;
}
int ObStmtExecParamReplacer::check_need_replace(const ObRawExpr *old_expr,
ObRawExpr *&new_expr,
bool &need_replace)
{
int ret = OB_SUCCESS;
uint64_t key = reinterpret_cast<uint64_t>(old_expr);
uint64_t val = 0;
need_replace = false;
if (OB_UNLIKELY(!expr_replace_map_.created())) {
// do nothing
} else if (OB_FAIL(expr_replace_map_.get_refactored(key, val))) {
if (OB_HASH_NOT_EXIST == ret) {
ret = OB_SUCCESS;
} else {
LOG_WARN("failed to get expr from hash map", K(ret));
}
} else {
need_replace = true;
new_expr = reinterpret_cast<ObRawExpr *>(val);
}
return ret;
}
int ObStmtExecParamReplacer::add_replace_exprs(const ObIArray<ObExecParamRawExpr *> &from_exprs,
const ObIArray<ObExecParamRawExpr *> &to_exprs)
{
int ret = OB_SUCCESS;
int64_t bucket_size = MAX(from_exprs.count(), 64);
if (OB_UNLIKELY(from_exprs.count() != to_exprs.count())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr size mismatch", K(from_exprs.count()), K(to_exprs.count()), K(ret));
} else if (expr_replace_map_.created()) {
/* do nothing */
} else if (OB_FAIL(expr_replace_map_.create(bucket_size, ObModIds::OB_SQL_COMPILE))) {
LOG_WARN("failed to create expr map", K(ret));
} else if (OB_FAIL(to_exprs_.create(bucket_size))) {
LOG_WARN("failed to create expr set", K(ret));
}
const ObRawExpr *from_expr = NULL;
const ObRawExpr *to_expr = NULL;
for (int64_t i = 0; OB_SUCC(ret) && i < from_exprs.count(); ++i) {
bool is_existed = false;
ObRawExpr *new_expr = NULL;
if (OB_ISNULL(from_expr = from_exprs.at(i)) || OB_ISNULL(to_expr = to_exprs.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected null expr", KP(from_expr), KP(to_expr), K(ret));
} else if (OB_FAIL(check_need_replace(from_expr, new_expr, is_existed))) {
LOG_WARN("failed to check need replace", K(ret));
} else if (is_existed) {
/* do nothing */
} else if (OB_FAIL(expr_replace_map_.set_refactored(reinterpret_cast<uint64_t>(from_expr),
reinterpret_cast<uint64_t>(to_expr)))) {
LOG_WARN("failed to add replace expr into map", K(ret));
} else if (OB_FAIL(to_exprs_.set_refactored(reinterpret_cast<uint64_t>(to_expr)))) {
LOG_WARN("failed to add replace expr into set", K(ret));
}
}
return ret;
}
int ObStmtExecParamReplacer::do_visit(ObRawExpr *&expr)
{
int ret = OB_SUCCESS;
bool is_happended = false;
if (OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr is null", K(ret), K(expr));
} else if (expr->is_exec_param_expr()) {
bool need_replace = false;
ObRawExpr *to_expr;
if (OB_FAIL(check_need_replace(expr, to_expr, need_replace))) {
LOG_WARN("failed to check need replace", K(ret));
} else if (need_replace) {
expr = to_expr;
}
} else if (expr->is_query_ref_expr()) {
ObQueryRefRawExpr *query_ref_expr = static_cast<ObQueryRefRawExpr*>(expr);
for (int64_t i = 0; OB_SUCC(ret) && i < query_ref_expr->get_param_count(); ++i) {
if (OB_FAIL(SMART_CALL(do_visit(reinterpret_cast<ObRawExpr *&>(
query_ref_expr->get_exec_params().at(i)))))) {
LOG_WARN("failed to remove const exec param", K(ret));
}
}
if (NULL == query_ref_expr->get_ref_stmt()) {
/* ref_stmt may has not been resolve yet */
} else if (OB_FAIL(SMART_CALL(query_ref_expr->get_ref_stmt()->iterate_stmt_expr(*this)))) {
LOG_WARN("failed to iterator stmt expr", K(ret));
}
} else if (expr->has_flag(CNT_SUB_QUERY)) {
for (int64_t i = 0; OB_SUCC(ret) && i < expr->get_param_count(); i++) {
if (OB_FAIL(SMART_CALL(do_visit(expr->get_param_expr(i))))) {
LOG_WARN("failed to do replace exec param", K(ret));
}
}
}
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -15,6 +15,7 @@
#include "lib/container/ob_array.h"
#include "sql/ob_sql_utils.h"
#include "sql/resolver/expr/ob_raw_expr.h"
#include "sql/resolver/dml/ob_stmt_expr_visitor.h"
namespace oceanbase
{
namespace sql
@ -23,6 +24,20 @@ class ObDMLResolver;
class ObAggFunRawExpr;
class ObSelectResolver;
class ObSelectStmt;
class ObStmtExecParamReplacer : public ObStmtExprVisitor
{
public:
ObStmtExecParamReplacer() {}
virtual int do_visit(ObRawExpr *&expr) override;
int add_replace_exprs(const ObIArray<ObExecParamRawExpr *> &from_exprs,
const ObIArray<ObExecParamRawExpr *> &to_exprs);
int check_need_replace(const ObRawExpr *old_expr, ObRawExpr *&new_expr, bool &need_replace);
private:
hash::ObHashSet<uint64_t> to_exprs_;
hash::ObHashMap<uint64_t, uint64_t> expr_replace_map_;
};
class ObAggrExprPushUpAnalyzer
{
public:
@ -63,7 +78,9 @@ private:
int remove_alias_exprs();
int remove_alias_exprs(ObRawExpr* &expr);
int replace_final_exec_param_in_aggr(const ObIArray<ObExecParamRawExpr *> &exec_params,
ObIArray<ObQueryRefRawExpr *> &param_query_refs,
ObRawExprFactory &expr_factory);
private:
// contain current layer column (a real column or a alias select item)
bool has_cur_layer_column_;

View File

@ -262,4 +262,4 @@ int ObStmtExecParamFormatter::do_formalize_exec_param(ObRawExpr *&expr, bool &is
}
}
return ret;
}
}

View File

@ -65,6 +65,7 @@ public:
const ObIArray<ObRawExpr *> &to_exprs);
int add_replace_exprs(const ObIArray<std::pair<ObRawExpr *, ObRawExpr *>> &to_replace_exprs);
int append_replace_exprs(const ObRawExprReplacer &other);
int check_need_replace(const ObRawExpr *old_expr, ObRawExpr *&new_expr, bool &need_replace);
private:
// types and constants
@ -76,9 +77,6 @@ private:
const bool overwrite,
bool &is_existed);
int check_skip_expr(const ObRawExpr &expr, bool &skip_expr);
int check_need_replace(const ObRawExpr *old_expr,
ObRawExpr *&new_expr,
bool &need_replace);
// disallow copy
DISALLOW_COPY_AND_ASSIGN(ObRawExprReplacer);
// function members

View File

@ -4576,29 +4576,52 @@ int ObRawExprUtils::get_exec_param_expr(ObRawExprFactory &expr_factory,
// we create a new one here
if (OB_SUCC(ret) && NULL == param_expr) {
ObExecParamRawExpr *exec_param = NULL;
if (OB_FAIL(expr_factory.create_raw_expr(T_QUESTIONMARK, exec_param))) {
LOG_WARN("failed to create raw expr", K(ret));
} else if (OB_ISNULL(exec_param)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("exec param is null", K(ret), K(exec_param));
if (OB_FAIL(ObRawExprUtils::create_new_exec_param(expr_factory,
outer_val_expr,
exec_param,
false))) {
LOG_WARN("failed to create new exec param", K(ret));
} else if (OB_FAIL(query_ref->add_exec_param_expr(exec_param))) {
LOG_WARN("failed to add exec param expr", K(ret));
} else if (OB_FAIL(exec_param->set_enum_set_values(outer_val_expr->get_enum_set_values()))) {
LOG_WARN("failed to set enum set values", K(ret));
} else if (OB_FAIL(exec_param->add_flag(IS_CONST))) {
LOG_WARN("failed to add flag", K(ret));
} else if (OB_FAIL(exec_param->add_flag(IS_DYNAMIC_PARAM))) {
LOG_WARN("failed to add flag", K(ret));
} else {
exec_param->set_ref_expr(outer_val_expr);
exec_param->set_param_index(-1);
exec_param->set_result_type(outer_val_expr->get_result_type());
param_expr = exec_param;
}
}
return ret;
}
int ObRawExprUtils::create_new_exec_param(ObRawExprFactory &expr_factory,
ObRawExpr *ref_expr,
ObExecParamRawExpr *&exec_param,
bool is_onetime /*=false*/)
{
int ret = OB_SUCCESS;
exec_param = NULL;
if (OB_ISNULL(ref_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr is null", K(ret), K(ref_expr));
} else if (OB_FAIL(expr_factory.create_raw_expr(T_QUESTIONMARK, exec_param))) {
LOG_WARN("failed to create exec param expr", K(ret));
} else if (OB_ISNULL(exec_param)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("exec param is null", K(ret), K(exec_param));
} else if (OB_FAIL(exec_param->set_enum_set_values(ref_expr->get_enum_set_values()))) {
LOG_WARN("failed to set enum set values", K(ret));
} else if (OB_FAIL(exec_param->add_flag(IS_CONST))) {
LOG_WARN("failed to add flag", K(ret));
} else if (OB_FAIL(exec_param->add_flag(IS_DYNAMIC_PARAM))) {
LOG_WARN("failed to add flag", K(ret));
} else {
exec_param->set_ref_expr(ref_expr, is_onetime);
exec_param->set_param_index(-1);
exec_param->set_result_type(ref_expr->get_result_type());
if (is_onetime) {
exec_param->add_flag(IS_ONETIME);
}
}
return ret;
}
int ObRawExprUtils::create_new_exec_param(ObQueryCtx *query_ctx,
ObRawExprFactory &expr_factory,
ObRawExpr *&expr,

View File

@ -557,11 +557,10 @@ public:
ObRawExprFactory &expr_factory,
ObRawExpr *&expr,
bool is_onetime = false);
static int create_exec_param_expr(ObQueryCtx *query_ctx,
ObRawExprFactory &expr_factory,
ObRawExpr *&src_expr,
std::pair<int64_t, ObRawExpr*> &init_expr);
static int create_new_exec_param(ObRawExprFactory &expr_factory,
ObRawExpr *ref_expr,
ObExecParamRawExpr *&exec_param,
bool is_onetime = false);
static int create_param_expr(ObRawExprFactory &expr_factory, int64_t param_idx, ObRawExpr *&expr);
static int build_trim_expr(const share::schema::ObColumnSchemaV2 *column_schema,
ObRawExprFactory &expr_factory,