From d49644bc7d0cb59eed5d5e969728e7b82ca8aa16 Mon Sep 17 00:00:00 2001 From: jingtaoye35 <1255153887@qq.com> Date: Mon, 28 Oct 2024 05:46:13 +0000 Subject: [PATCH] fix master bugs in rewrite --- .../rewrite/ob_transform_join_elimination.cpp | 57 +++++++++++-------- src/sql/rewrite/ob_transform_or_expansion.cpp | 13 +++-- 2 files changed, 41 insertions(+), 29 deletions(-) diff --git a/src/sql/rewrite/ob_transform_join_elimination.cpp b/src/sql/rewrite/ob_transform_join_elimination.cpp index 5d213f788..d401a0665 100644 --- a/src/sql/rewrite/ob_transform_join_elimination.cpp +++ b/src/sql/rewrite/ob_transform_join_elimination.cpp @@ -2581,10 +2581,6 @@ int ObTransformJoinElimination::is_table_column_used_in_subquery(const ObSelectS return ret; } -/* -source_table and target_table come from the same stmt -there must be one simple condition at least in join filters which simple condition is source_table's column equals to target table's same column -*/ int ObTransformJoinElimination::check_semi_join_condition(ObDMLStmt *stmt, ObIArray &semi_conds, const TableItem *source_table, @@ -2597,7 +2593,6 @@ int ObTransformJoinElimination::check_semi_join_condition(ObDMLStmt *stmt, bool &is_simple_filter) { int ret = OB_SUCCESS; - bool source_table_has_filter = false; is_simple_join_condition = true; target_tables_have_filter = false; is_simple_filter = true; @@ -2614,7 +2609,7 @@ int ObTransformJoinElimination::check_semi_join_condition(ObDMLStmt *stmt, ret = OB_ERR_UNEXPECTED; LOG_WARN("expr is null", K(ret)); } else if (!expr->get_relation_ids().has_member(right_idx)) { - source_table_has_filter = true; + /* do nothing */ } else if (!expr->get_relation_ids().has_member(left_idx)) { target_tables_have_filter = true; if (T_OP_OR == expr->get_expr_type()) { // complex right table filter @@ -2651,17 +2646,38 @@ int ObTransformJoinElimination::check_semi_join_condition(ObDMLStmt *stmt, } else {/*do nothing*/} } } + /* source table is required in not null side, bad case: + select * from (t2 left join t1 on t2.c1 = t1.c1) semi join t1 t; + --> following rewriting is wrong when t1 is a empty table. + select * from t2 left join t1 on t2.c1 = t1.c1; + + The following logic can be processed more finely: + if source table is on null side, but where_condition or on_condition has null reject property,can also do this optimization. + + but this is a very corner case, so may modify oneday when there is a need + */ if (OB_SUCC(ret) && is_simple_join_condition && source_exprs.empty()) { bool is_on_null_side = true; - if (!source_table_has_filter) { - is_simple_join_condition = false; - } else if (OB_FAIL(ObOptimizerUtil::is_table_on_null_side(stmt, - source_table->table_id_, - is_on_null_side))) { + bool has_null_reject = false; + ObRelIds left_ids; + if (OB_FAIL(ObOptimizerUtil::is_table_on_null_side(stmt, + source_table->table_id_, + is_on_null_side))) { LOG_WARN("failed to check table is on null side", K(ret)); - } else if (is_on_null_side) { - /* source table is required in not null side, bad case: - select * from (t2 left join t1 on t2.c1 = t1.c1) semi join t1 t on t1.c2 = 1 */ + } else if (!is_on_null_side) { + /* do nothing */ + } else if (OB_FAIL(left_ids.add_member(left_idx))) { + LOG_WARN("failed to add member"); + } else if (OB_FAIL(ObTransformUtils::is_null_reject_conditions(semi_conds, + left_ids, + has_null_reject))) { + LOG_WARN("failed to get is null reject conditions", K(ret)); + } else if (!has_null_reject && + OB_FAIL(ObTransformUtils::is_null_reject_conditions(stmt->get_condition_exprs(), + left_ids, + has_null_reject))) { + LOG_WARN("failed to get is null reject conditions", K(ret)); + } else if (!has_null_reject) { is_simple_join_condition = false; } } @@ -2684,7 +2700,6 @@ int ObTransformJoinElimination::check_semi_join_condition(ObDMLStmt *stmt, bool &is_simple_filter) { int ret = OB_SUCCESS; - bool source_table_has_filter = false; is_simple_join_condition = true; target_tables_have_filter = false; is_simple_filter = true; @@ -2701,7 +2716,7 @@ int ObTransformJoinElimination::check_semi_join_condition(ObDMLStmt *stmt, ret = OB_ERR_UNEXPECTED; LOG_WARN("expr is null", K(ret)); } else if (!select_relids.at(i).has_member(right_idx)) { - source_table_has_filter = true; + /* do nothing */ } else if (!expr->get_relation_ids().has_member(left_idx)) { target_tables_have_filter = true; if (T_OP_OR == expr->get_expr_type()) { // complex right table filter @@ -2750,15 +2765,11 @@ int ObTransformJoinElimination::check_semi_join_condition(ObDMLStmt *stmt, } if (OB_SUCC(ret) && is_simple_join_condition && source_exprs.empty()) { bool is_on_null_side = true; - if (!source_table_has_filter) { - is_simple_join_condition = false; - } else if (OB_FAIL(ObOptimizerUtil::is_table_on_null_side(stmt, - source_table->table_id_, - is_on_null_side))) { + if (OB_FAIL(ObOptimizerUtil::is_table_on_null_side(stmt, + source_table->table_id_, + is_on_null_side))) { LOG_WARN("failed to check table is on null side", K(ret)); } else if (is_on_null_side) { - /* source table is required in not null side, bad case: - select * from (t2 left join t1 on t2.c1 = t1.c1) semi join t1 t on t1.c2 = 1 */ is_simple_join_condition = false; } } diff --git a/src/sql/rewrite/ob_transform_or_expansion.cpp b/src/sql/rewrite/ob_transform_or_expansion.cpp index d7a020367..93248e21b 100644 --- a/src/sql/rewrite/ob_transform_or_expansion.cpp +++ b/src/sql/rewrite/ob_transform_or_expansion.cpp @@ -1781,8 +1781,13 @@ int ObTransformOrExpansion::may_expr_extract_query_range(const ObDMLStmt *stmt, } 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 (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; + } else if ((T_OP_EQ <= com_type && T_OP_NE >= com_type) || + T_OP_IS == com_type || T_OP_IS_NOT == com_type) { + // EQ、NSEQ、LE、LT、GE、GT、NE、IS、IS_NOT 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; @@ -1820,10 +1825,6 @@ int ObTransformOrExpansion::may_expr_extract_query_range(const ObDMLStmt *stmt, } 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))) {