fix an exec_param and a expr copy_on_replace bugs
This commit is contained in:
@ -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) {
|
for (int64_t i = 0; OB_SUCC(ret) && i < subquery_exprs_.count(); ++i) {
|
||||||
ObRawExpr *expr = subquery_exprs_.at(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)) {
|
if (ObOptimizerUtil::find_item(plan->get_onetime_query_refs(), expr)) {
|
||||||
// do not replace onetime expr ref query, only adjust nested subquery
|
// do not replace onetime expr ref query, only adjust nested subquery
|
||||||
} else if (OB_FAIL(replace_expr_action(replacer, expr))) {
|
} 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));
|
LOG_WARN("unexpected expr type", K(ret));
|
||||||
} else {
|
} else {
|
||||||
subquery_exprs_.at(i) = static_cast<ObQueryRefRawExpr*>(expr);
|
subquery_exprs_.at(i) = static_cast<ObQueryRefRawExpr*>(expr);
|
||||||
|
subquery_exprs_.at(i)->set_ref_id(ref_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@ -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),
|
} else if (OB_FAIL(ObTransformUtils::decorrelate(reinterpret_cast<ObRawExpr *&>(aggr_expr),
|
||||||
final_exec_params))) {
|
final_exec_params))) {
|
||||||
LOG_WARN("failed to decorrelate exec params", K(ret));
|
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_SUCC(ret)) {
|
||||||
if (OB_FAIL(final_aggr_resolver->add_aggr_expr(aggr_expr))) {
|
if (OB_FAIL(final_aggr_resolver->add_aggr_expr(aggr_expr))) {
|
||||||
@ -444,5 +446,136 @@ int ObAggrExprPushUpAnalyzer::get_exec_params(ObDMLResolver *resolver,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ObAggrExprPushUpAnalyzer::replace_final_exec_param_in_aggr(const ObIArray<ObExecParamRawExpr *> &exec_params,
|
||||||
|
ObIArray<ObQueryRefRawExpr *> ¶m_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 sql
|
||||||
} // namespace oceanbase
|
} // namespace oceanbase
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
#include "lib/container/ob_array.h"
|
#include "lib/container/ob_array.h"
|
||||||
#include "sql/ob_sql_utils.h"
|
#include "sql/ob_sql_utils.h"
|
||||||
#include "sql/resolver/expr/ob_raw_expr.h"
|
#include "sql/resolver/expr/ob_raw_expr.h"
|
||||||
|
#include "sql/resolver/dml/ob_stmt_expr_visitor.h"
|
||||||
namespace oceanbase
|
namespace oceanbase
|
||||||
{
|
{
|
||||||
namespace sql
|
namespace sql
|
||||||
@ -23,6 +24,20 @@ class ObDMLResolver;
|
|||||||
class ObAggFunRawExpr;
|
class ObAggFunRawExpr;
|
||||||
class ObSelectResolver;
|
class ObSelectResolver;
|
||||||
class ObSelectStmt;
|
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
|
class ObAggrExprPushUpAnalyzer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -63,7 +78,9 @@ private:
|
|||||||
int remove_alias_exprs();
|
int remove_alias_exprs();
|
||||||
|
|
||||||
int remove_alias_exprs(ObRawExpr* &expr);
|
int remove_alias_exprs(ObRawExpr* &expr);
|
||||||
|
int replace_final_exec_param_in_aggr(const ObIArray<ObExecParamRawExpr *> &exec_params,
|
||||||
|
ObIArray<ObQueryRefRawExpr *> ¶m_query_refs,
|
||||||
|
ObRawExprFactory &expr_factory);
|
||||||
private:
|
private:
|
||||||
// contain current layer column (a real column or a alias select item)
|
// contain current layer column (a real column or a alias select item)
|
||||||
bool has_cur_layer_column_;
|
bool has_cur_layer_column_;
|
||||||
|
|||||||
@ -65,6 +65,7 @@ public:
|
|||||||
const ObIArray<ObRawExpr *> &to_exprs);
|
const ObIArray<ObRawExpr *> &to_exprs);
|
||||||
int add_replace_exprs(const ObIArray<std::pair<ObRawExpr *, ObRawExpr *>> &to_replace_exprs);
|
int add_replace_exprs(const ObIArray<std::pair<ObRawExpr *, ObRawExpr *>> &to_replace_exprs);
|
||||||
int append_replace_exprs(const ObRawExprReplacer &other);
|
int append_replace_exprs(const ObRawExprReplacer &other);
|
||||||
|
int check_need_replace(const ObRawExpr *old_expr, ObRawExpr *&new_expr, bool &need_replace);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// types and constants
|
// types and constants
|
||||||
@ -76,9 +77,6 @@ private:
|
|||||||
const bool overwrite,
|
const bool overwrite,
|
||||||
bool &is_existed);
|
bool &is_existed);
|
||||||
int check_skip_expr(const ObRawExpr &expr, bool &skip_expr);
|
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
|
||||||
DISALLOW_COPY_AND_ASSIGN(ObRawExprReplacer);
|
DISALLOW_COPY_AND_ASSIGN(ObRawExprReplacer);
|
||||||
// function members
|
// function members
|
||||||
|
|||||||
@ -4576,29 +4576,52 @@ int ObRawExprUtils::get_exec_param_expr(ObRawExprFactory &expr_factory,
|
|||||||
// we create a new one here
|
// we create a new one here
|
||||||
if (OB_SUCC(ret) && NULL == param_expr) {
|
if (OB_SUCC(ret) && NULL == param_expr) {
|
||||||
ObExecParamRawExpr *exec_param = NULL;
|
ObExecParamRawExpr *exec_param = NULL;
|
||||||
if (OB_FAIL(expr_factory.create_raw_expr(T_QUESTIONMARK, exec_param))) {
|
if (OB_FAIL(ObRawExprUtils::create_new_exec_param(expr_factory,
|
||||||
LOG_WARN("failed to create raw expr", K(ret));
|
outer_val_expr,
|
||||||
} else if (OB_ISNULL(exec_param)) {
|
exec_param,
|
||||||
ret = OB_ERR_UNEXPECTED;
|
false))) {
|
||||||
LOG_WARN("exec param is null", K(ret), K(exec_param));
|
LOG_WARN("failed to create new exec param", K(ret));
|
||||||
} else if (OB_FAIL(query_ref->add_exec_param_expr(exec_param))) {
|
} else if (OB_FAIL(query_ref->add_exec_param_expr(exec_param))) {
|
||||||
LOG_WARN("failed to add exec param expr", K(ret));
|
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 {
|
} 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;
|
param_expr = exec_param;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
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,
|
int ObRawExprUtils::create_new_exec_param(ObQueryCtx *query_ctx,
|
||||||
ObRawExprFactory &expr_factory,
|
ObRawExprFactory &expr_factory,
|
||||||
ObRawExpr *&expr,
|
ObRawExpr *&expr,
|
||||||
|
|||||||
@ -557,11 +557,10 @@ public:
|
|||||||
ObRawExprFactory &expr_factory,
|
ObRawExprFactory &expr_factory,
|
||||||
ObRawExpr *&expr,
|
ObRawExpr *&expr,
|
||||||
bool is_onetime = false);
|
bool is_onetime = false);
|
||||||
|
static int create_new_exec_param(ObRawExprFactory &expr_factory,
|
||||||
static int create_exec_param_expr(ObQueryCtx *query_ctx,
|
ObRawExpr *ref_expr,
|
||||||
ObRawExprFactory &expr_factory,
|
ObExecParamRawExpr *&exec_param,
|
||||||
ObRawExpr *&src_expr,
|
bool is_onetime = false);
|
||||||
std::pair<int64_t, ObRawExpr*> &init_expr);
|
|
||||||
static int create_param_expr(ObRawExprFactory &expr_factory, int64_t param_idx, ObRawExpr *&expr);
|
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,
|
static int build_trim_expr(const share::schema::ObColumnSchemaV2 *column_schema,
|
||||||
ObRawExprFactory &expr_factory,
|
ObRawExprFactory &expr_factory,
|
||||||
|
|||||||
Reference in New Issue
Block a user