enhance or expansion with cast

This commit is contained in:
jingtaoye35 2024-10-08 22:47:14 +00:00 committed by ob-robot
parent 44c5f42248
commit 84b5f69ee1
5 changed files with 151 additions and 119 deletions

View File

@ -114,7 +114,6 @@ public:
bool with_rows() const
{ return ObStmt::is_select_stmt(stmt_type_) || is_returning() || need_drive_dml_query_; }
int copy_common_info(ObPhysicalPlan &src);
int extract_query_range(ObExecContext &ctx) const;
//user var
bool is_contains_assignment() const {return is_contains_assignment_;}
void set_contains_assignment(bool v) {is_contains_assignment_ = v;}

View File

@ -8836,6 +8836,35 @@ int ObRawExprUtils::build_or_exprs(ObRawExprFactory &expr_factory,
return ret;
}
int ObRawExprUtils::get_exprs_inside_and_or(ObRawExpr *and_or_expr,
ObIArray<ObRawExpr *> &exprs)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(and_or_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("got unexpected null ptr", K(ret));
} else if (OB_UNLIKELY(T_OP_OR != and_or_expr->get_expr_type() &&
T_OP_AND != and_or_expr->get_expr_type())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("got unexpected expr type", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < and_or_expr->get_param_count(); i++) {
ObRawExpr *expr = and_or_expr->get_param_expr(i);
if (OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("got unexpected null ptr", K(ret));
} else if (expr->get_expr_type() == T_OP_OR || expr->get_expr_type() == T_OP_AND) {
if (OB_FAIL(SMART_CALL(get_exprs_inside_and_or(expr, exprs)))) {
LOG_WARN("failed to get all expr inside and or", K(ret));
}
} else if (OB_FAIL(exprs.push_back(expr))) {
LOG_WARN("failed to push back");
}
}
}
return ret;
}
int ObRawExprUtils::build_and_expr(ObRawExprFactory &expr_factory,
const ObIArray<ObRawExpr*> &exprs,
ObRawExpr * &and_expr)

View File

@ -1087,7 +1087,7 @@ public:
static int build_or_exprs(ObRawExprFactory &expr_factory,
const ObIArray<ObRawExpr*> &exprs,
ObRawExpr* &or_expr);
static int get_exprs_inside_and_or(ObRawExpr *and_or_expr, ObIArray<ObRawExpr *> &exprs);
static int build_and_expr(ObRawExprFactory &expr_factory,
const ObIArray<ObRawExpr*> &exprs,
ObRawExpr * &and_expr);

View File

@ -1754,98 +1754,88 @@ int ObTransformOrExpansion::is_contain_join_cond(const ObDMLStmt *stmt,
return ret;
}
int ObTransformOrExpansion::is_match_index(const ObDMLStmt *stmt,
const ObRawExpr *expr,
EqualSets &equal_sets,
ObIArray<ObRawExpr*> &const_exprs,
bool &is_match)
// just wanna know this expr may extract query range
int ObTransformOrExpansion::may_expr_extract_query_range(const ObDMLStmt *stmt,
const ObRawExpr *expr,
EqualSets &equal_sets,
ObIArray<ObRawExpr*> &const_exprs,
bool &is_match)
{
int ret = OB_SUCCESS;
const ObRawExpr *l_expr = NULL;
const ObRawExpr *r_expr = NULL;
const ObRawExpr *r2_expr = NULL;
const ObColumnRefRawExpr *col_expr = NULL;
bool is_right_const = false;
is_match = false;
if (OB_ISNULL(ctx_) || OB_ISNULL(stmt) || OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null ctx", K(ret));
} else if (expr->has_flag(IS_SIMPLE_COND) ||
expr->has_flag(IS_RANGE_COND) ||
T_OP_IS == expr->get_expr_type()) {
ObSEArray<ObRawExpr*, 2> column_exprs;
ObColumnRefRawExpr *col_expr = NULL;
if (OB_FAIL(ObRawExprUtils::extract_column_exprs(expr, column_exprs))) {
LOG_WARN("failed to extrace column exprs", K(ret));
} else if (1 != column_exprs.count()) {
//do nothing
} else if (OB_ISNULL(column_exprs.at(0))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null expr", K(ret));
} else if (!column_exprs.at(0)->is_column_ref_expr()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expect column ref expr", K(*column_exprs.at(0)), K(ret));
} else if (OB_FALSE_IT(col_expr = static_cast<ObColumnRefRawExpr*>(column_exprs.at(0)))) {
} else if (OB_ISNULL(stmt->get_table_item_by_id(col_expr->get_table_id()))) {
//do nothing
} else if (OB_FAIL(ObTransformUtils::is_match_index(ctx_->sql_schema_guard_,
stmt,
col_expr,
is_match,
&equal_sets,
&const_exprs))) {
LOG_WARN("failed to check is match index", K(ret));
} else if (T_OP_AND == expr->get_expr_type() || T_OP_OR == expr->get_expr_type()) {
for (int64_t i = 0; OB_SUCC(ret) && !is_match && i < expr->get_param_count(); ++i) {
if (OB_FAIL(SMART_CALL(may_expr_extract_query_range(stmt, expr->get_param_expr(i),
equal_sets, const_exprs, is_match)))) {
LOG_WARN("failed to check is match index", K(ret));
}
}
} else if (T_OP_IN == expr->get_expr_type()) {
const ObRawExpr *right_expr = NULL;
if (OB_UNLIKELY(2 != expr->get_param_count())) {
}
if (OB_SUCC(ret) && !is_match) {
const ObItemType com_type = expr->get_expr_type();
// EQ、NSEQ、LE、LT、GE、GT、NE、IS、IS_NOT
if ((T_OP_EQ <= com_type && T_OP_NE >= com_type) || T_OP_IS == com_type || T_OP_IS_NOT == com_type) {
if (OB_UNLIKELY(expr->get_param_count() != 2) ||
OB_ISNULL(l_expr = expr->get_param_expr(0)) || OB_ISNULL(r_expr = expr->get_param_expr(1))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("in expr should have 2 param", K(expr->get_param_count()), K(ret));
} else if (OB_ISNULL(right_expr = expr->get_param_expr(1))) {
LOG_WARN("unexpect null expr", K(ret));
} else if (T_OP_ROW == l_expr->get_expr_type()) {
/* do nothing, may support T_OP_ROW oneday*/
} else if (l_expr->is_const_expr()) {
l_expr = r_expr;
is_right_const = true;
} else if (r_expr->is_const_expr()) {
is_right_const = true;
}
} else if (T_OP_IN == com_type || T_OP_NOT_IN == com_type) {
if (OB_UNLIKELY(expr->get_param_count() != 2) ||
OB_ISNULL(l_expr = expr->get_param_expr(0)) || OB_ISNULL(r_expr = expr->get_param_expr(1))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null expr", K(ret));
} else if (T_OP_ROW == right_expr->get_expr_type()) {
bool is_const = true;
for (int64_t i = 0;
OB_SUCC(ret) && is_const && i < right_expr->get_param_count(); i++) {
const ObRawExpr *temp_expr = right_expr->get_param_expr(i);
LOG_WARN("unexpect null expr", K(ret));
} else if (T_OP_ROW == r_expr->get_expr_type()) {
is_right_const = true;
for (int64_t i = 0; OB_SUCC(ret) && is_right_const && i < r_expr->get_param_count(); i++) {
const ObRawExpr *temp_expr = r_expr->get_param_expr(i);
if (OB_ISNULL(temp_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null expr", K(ret));
} else if (!temp_expr->is_const_expr()) {
is_const = false;
} else { /*do nothing*/ }
is_right_const = false;
}
}
const ObColumnRefRawExpr *col_expr = NULL;
if (OB_FAIL(ret) || !is_const) {
//do nothing
} else if (OB_ISNULL(expr->get_param_expr(0))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null expr", K(ret));
} else if (!expr->get_param_expr(0)->is_column_ref_expr()) {
//do nothing
} else if (OB_FALSE_IT(col_expr = static_cast<const ObColumnRefRawExpr*>(expr->get_param_expr(0)))) {
} else if (OB_ISNULL(stmt->get_table_item_by_id(col_expr->get_table_id()))) {
//do nothing
} else if (OB_FAIL(ObTransformUtils::is_match_index(ctx_->sql_schema_guard_,
stmt,
col_expr,
is_match,
&equal_sets,
&const_exprs))) {
LOG_WARN("failed to check is match index", K(ret));
}
} else { /*do nothing*/ }
} else if (T_OP_AND == expr->get_expr_type()) {
for (int64_t i = 0; OB_SUCC(ret) && !is_match && i < expr->get_param_count(); ++i) {
if (OB_FAIL(SMART_CALL(is_match_index(stmt,
expr->get_param_expr(i),
equal_sets,
const_exprs,
is_match)))) {
}
} else if (T_OP_BTW == com_type || T_OP_NOT_BTW == com_type || T_OP_LIKE == com_type) {
if (OB_UNLIKELY(expr->get_param_count() != 3) || OB_ISNULL(l_expr = expr->get_param_expr(0)) ||
OB_ISNULL(r_expr = expr->get_param_expr(1)) || OB_ISNULL(r2_expr = expr->get_param_expr(2))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null expr", K(ret));
} else if (r_expr->is_const_expr() && r2_expr->is_const_expr()) {
is_right_const = true;
}
} else if (expr->has_flag(CNT_COLUMN) &&
(expr->has_flag(IS_ROWID_SIMPLE_COND) || expr->has_flag(IS_ROWID_RANGE_COND))) {
//rowid = const or rowid belong const range can choose primary key.
is_match = true;
}
if (OB_SUCC(ret) && !is_match && is_right_const) {
if (OB_FAIL(ObOptimizerUtil::get_expr_without_lossless_cast(l_expr, l_expr))) {
LOG_WARN("failed to get lossless cast expr", K(ret));
} else if (!l_expr->is_column_ref_expr()) {
} else if (FALSE_IT(col_expr = static_cast<const ObColumnRefRawExpr*>(l_expr))) {
} else if (OB_ISNULL(stmt->get_table_item_by_id(col_expr->get_table_id()))) {
} else if (OB_FAIL(ObTransformUtils::is_match_index(ctx_->sql_schema_guard_,
stmt, col_expr, is_match, &equal_sets, &const_exprs))) {
LOG_WARN("failed to check is match index", K(ret));
}
}
} else if (expr->has_flag(CNT_COLUMN) &&
(expr->has_flag(IS_ROWID_SIMPLE_COND) ||
expr->has_flag(IS_ROWID_RANGE_COND))) {
//rowid = const or rowid belong const range can choose primary key.
is_match = true;
}
return ret;
}
@ -2126,7 +2116,7 @@ int ObTransformOrExpansion::is_condition_valid(const ObDMLStmt *stmt,
}
if (OB_SUCC(ret) && match_index &&
OB_FAIL(is_match_index(stmt, child_expr, equal_sets, const_exprs, match_index))) {
OB_FAIL(may_expr_extract_query_range(stmt, child_expr, equal_sets, const_exprs, match_index))) {
LOG_WARN("failed to check is match index", K(ret));
}
if (OB_SUCC(ret) && !has_valid_subquery &&
@ -2850,40 +2840,58 @@ int ObTransformOrExpansion::is_expected_multi_index_plan(ObLogicalOperator* op,
int ret = OB_SUCCESS;
is_valid = true;
const int64_t N = ctx.expand_exprs_.count();
ObSEArray<ObRawExpr*, 4> range_exprs;
ObSEArray<ObRawExpr*, 4> candi_exprs;
for (int64_t i = 0; OB_SUCC(ret) && is_valid && i < N; ++i) {
candi_exprs.reuse();
if (OB_FAIL(get_candi_match_index_exprs(ctx.expand_exprs_.at(i), candi_exprs))) {
LOG_WARN("failed to get candi match index exprs", K(ret));
} else if (OB_FAIL(remove_filter_exprs(op, candi_exprs))) {
LOG_WARN("failed to remove filter exprs", K(ret));
} else if (candi_exprs.empty()) {
is_valid = false;
ObSEArray<ObRawExpr*, 4> result_exprs;
if (OB_FAIL(get_range_exprs(op, range_exprs))) {
LOG_WARN("failed to get range exprs", K(ret));
} else if (range_exprs.empty()) {
is_valid = false;
} else {
for (int64_t i = 0; OB_SUCC(ret) && is_valid && i < N; ++i) {
candi_exprs.reuse();
result_exprs.reuse();
if (OB_FAIL(get_candi_match_index_exprs(ctx.expand_exprs_.at(i), candi_exprs))) {
LOG_WARN("failed to get candi match index exprs", K(ret));
} else if (candi_exprs.empty()) {
is_valid = false;
LOG_TRACE("expr is not candi match index expr", K(*ctx.expand_exprs_.at(i)));
} else if (OB_FAIL(ObOptimizerUtil::intersect_exprs(candi_exprs, range_exprs, result_exprs))) {
LOG_WARN("failed to intersect exprs", K(ret));
} else if (result_exprs.empty()) {
is_valid = false;
}
}
}
LOG_TRACE("is expand exprs match range exprs", K(range_exprs), K(ctx.expand_exprs_), K(is_valid));
return ret;
}
int ObTransformOrExpansion::remove_filter_exprs(ObLogicalOperator* op,
ObIArray<ObRawExpr*> &candi_exprs)
int ObTransformOrExpansion::get_range_exprs(ObLogicalOperator* op,
ObIArray<ObRawExpr*> &range_exprs)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(op) || candi_exprs.empty()) {
if (OB_ISNULL(op)) {
/* do nothing */
} else if (!op->get_filter_exprs().empty() &&
OB_FAIL(ObOptimizerUtil::except_exprs(candi_exprs,
op->get_filter_exprs(),
candi_exprs))) {
LOG_WARN("failed to get except exprs", K(ret));
} else if (log_op_def::LOG_JOIN == op->get_type() &&
!static_cast<ObLogJoin*>(op)->get_join_filters().empty() &&
OB_FAIL(ObOptimizerUtil::except_exprs(candi_exprs,
static_cast<ObLogJoin*>(op)->get_join_filters(),
candi_exprs))) {
LOG_WARN("failed to get except exprs", K(ret));
} else if (log_op_def::LOG_TABLE_SCAN == op->get_type()) {
ObLogTableScan *table_scan = static_cast<ObLogTableScan*>(op);
for (int64_t i = 0; OB_SUCC(ret) && i < table_scan->get_range_conditions().count(); i++) {
ObRawExpr *range_expr = table_scan->get_range_conditions().at(i);
if (OB_ISNULL(range_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("got unexpected null ptr", K(ret));
} else if (T_OP_OR == range_expr->get_expr_type() ||
T_OP_AND == range_expr->get_expr_type()) {
if (OB_FAIL(ObRawExprUtils::get_exprs_inside_and_or(range_expr, range_exprs))) {
LOG_WARN("failed to get all expr inside and or", K(ret));
}
} else if (OB_FAIL(range_exprs.push_back(range_expr))) {
LOG_WARN("failed to push back", K(ret));
}
}
} else {
for (int64_t i = 0; OB_SUCC(ret) && !candi_exprs.empty() && i < op->get_num_of_child(); ++i) {
if (OB_FAIL(SMART_CALL(remove_filter_exprs(op->get_child(i), candi_exprs)))) {
for (int64_t i = 0; OB_SUCC(ret) && i < op->get_num_of_child(); ++i) {
if (OB_FAIL(SMART_CALL(get_range_exprs(op->get_child(i), range_exprs)))) {
LOG_WARN("failed to remove filter exprs", K(ret));
}
}
@ -2895,22 +2903,19 @@ int ObTransformOrExpansion::is_candi_match_index_exprs(ObRawExpr *expr, bool &re
{
int ret = OB_SUCCESS;
result = true;
ObItemType com_type = T_INVALID;
if (OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect NULL", K(ret));
} else if (expr->has_flag(IS_SIMPLE_COND) || expr->has_flag(IS_RANGE_COND)
|| T_OP_IN == expr->get_expr_type()) {
} else if (FALSE_IT(com_type = expr->get_expr_type())) {
} else if ((T_OP_EQ <= com_type && T_OP_NE >= com_type) ||
T_OP_IS == com_type || T_OP_IS_NOT == com_type ||
T_OP_IN == com_type || T_OP_NOT_IN == com_type ||
T_OP_BTW == com_type || T_OP_NOT_BTW || T_OP_LIKE == com_type) {
if (expr->get_relation_ids().is_empty()) {
// can not use as range candition
result = false;
}
} else if (T_OP_OR == expr->get_expr_type() || T_OP_AND == expr->get_expr_type()) {
for (int64_t i = 0; OB_SUCC(ret) && result && i < expr->get_param_count(); ++i) {
if (OB_FAIL(SMART_CALL(is_candi_match_index_exprs(expr->get_param_expr(i),
result)))) {
LOG_WARN("failed to check is candi match index exprs", K(ret));
}
}
} else if (expr->has_flag(IS_ROWID_SIMPLE_COND) ||
expr->has_flag(IS_ROWID_RANGE_COND)) {
//rowid = const or rowid belong const range can choose primary key.
@ -2928,7 +2933,7 @@ int ObTransformOrExpansion::get_candi_match_index_exprs(ObRawExpr *expr,
if (OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect NULL", K(ret));
} else if (T_OP_AND == expr->get_expr_type()) {
} else if (T_OP_AND == expr->get_expr_type() || T_OP_OR == expr->get_expr_type()) {
for (int64_t i = 0; OB_SUCC(ret) && i < expr->get_param_count(); ++i) {
if (OB_FAIL(SMART_CALL(get_candi_match_index_exprs(expr->get_param_expr(i),
candi_exprs)))) {

View File

@ -233,11 +233,11 @@ private:
const ObRawExpr &expr,
bool &using_same_cols);
int is_match_index(const ObDMLStmt *stmt,
const ObRawExpr *expr,
EqualSets &equal_sets,
ObIArray<ObRawExpr*> &const_exprs,
bool &is_match);
int may_expr_extract_query_range(const ObDMLStmt *stmt,
const ObRawExpr *expr,
EqualSets &equal_sets,
ObIArray<ObRawExpr*> &const_exprs,
bool &is_match);
int is_valid_subquery_cond(const ObDMLStmt &stmt,
const ObRawExpr &expr,
@ -369,8 +369,7 @@ private:
int is_expected_multi_index_plan(ObLogicalOperator* op,
ObCostBasedRewriteCtx &ctx,
bool &is_valid);
int remove_filter_exprs(ObLogicalOperator* op,
ObIArray<ObRawExpr*> &candi_exprs);
int get_range_exprs(ObLogicalOperator* op, ObIArray<ObRawExpr*> &candi_exprs);
int is_candi_match_index_exprs(ObRawExpr *expr, bool &result);
int get_candi_match_index_exprs(ObRawExpr *expr,
ObIArray<ObRawExpr*> &candi_exprs);