diff --git a/src/sql/plan_cache/ob_plan_cache_util.h b/src/sql/plan_cache/ob_plan_cache_util.h index c982554e3b..ebf8d42184 100644 --- a/src/sql/plan_cache/ob_plan_cache_util.h +++ b/src/sql/plan_cache/ob_plan_cache_util.h @@ -275,7 +275,8 @@ struct ObPCConstParamInfo TO_STRING_KV(K_(const_idx), K_(const_params)); bool operator==(const ObPCConstParamInfo &other) const { - bool cmp_ret = true; + bool cmp_ret = const_idx_.count() == other.const_idx_.count() + && const_params_.count() == other.const_params_.count(); for (int i=0; cmp_ret && i < const_idx_.count(); i++) { cmp_ret = const_idx_.at(i) == other.const_idx_.at(i); } diff --git a/src/sql/resolver/dml/ob_group_by_checker.cpp b/src/sql/resolver/dml/ob_group_by_checker.cpp index fbfc78712d..25812046d7 100644 --- a/src/sql/resolver/dml/ob_group_by_checker.cpp +++ b/src/sql/resolver/dml/ob_group_by_checker.cpp @@ -354,7 +354,7 @@ bool ObGroupByChecker::find_in_rollup(ObRawExpr &expr) } } if (OB_SUCCESS == check_ctx.err_code_ && !found && is_top_select_stmt()) { - for (int64_t nth_rollup = 0; !found && nth_rollup < rollup_cnt; ++nth_rollup) { + for (int64_t nth_rollup = 0; !found_same_structure && nth_rollup < rollup_cnt; ++nth_rollup) { //in oracle mode, only non static const expr will be replaced later in replace_group_by_exprs if (is_mysql_mode() || !rollup_exprs_->at(nth_rollup)->is_static_const_expr()) { check_ctx.reset(); @@ -448,10 +448,10 @@ bool ObGroupByChecker::find_in_grouping_sets(ObRawExpr &expr) } } if (OB_SUCCESS == check_ctx.err_code_ && !found && is_top_select_stmt()) { - for (int64_t nth_gs = 0; !found && nth_gs < gs_cnt; ++nth_gs) { + for (int64_t nth_gs = 0; !found_same_structure && nth_gs < gs_cnt; ++nth_gs) { int64_t group_by_cnt = grouping_sets_exprs_->at(nth_gs).groupby_exprs_.count(); //in oracle mode, only non static const expr will be replaced later in replace_group_by_exprs - for (int64_t nth_group_by = 0; !found && nth_group_by < group_by_cnt; ++nth_group_by) { + for (int64_t nth_group_by = 0; !found_same_structure && nth_group_by < group_by_cnt; ++nth_group_by) { check_ctx.reset(); check_ctx.ignore_param_ = true; check_ctx.override_const_compare_ = true; diff --git a/src/sql/rewrite/ob_predicate_deduce.cpp b/src/sql/rewrite/ob_predicate_deduce.cpp index 31b13efa6e..bd856bd0f7 100644 --- a/src/sql/rewrite/ob_predicate_deduce.cpp +++ b/src/sql/rewrite/ob_predicate_deduce.cpp @@ -627,6 +627,7 @@ int ObPredicateDeduce::get_equal_exprs(ObRawExpr *pred, { int ret = OB_SUCCESS; ObSEArray first_params; + ObSEArray candi_exprs; int64_t param_idx = -1; ObRawExpr *param_expr = NULL; if (OB_ISNULL(pred) || OB_ISNULL(param_expr = pred->get_param_expr(0))) { @@ -637,23 +638,101 @@ int ObPredicateDeduce::get_equal_exprs(ObRawExpr *pred, } else if (ObOptimizerUtil::find_item(input_exprs_, param_expr, ¶m_idx)) { for (int64_t i = 0; OB_SUCC(ret) && i < N; ++i) { ObRawExpr *expr = input_exprs_.at(i); + const ObRawExpr *real_expr = expr; + bool need_check_type_safe = false; if (!has(graph_, param_idx, i, EQ) || i == param_idx) { // do nothing } else if (OB_ISNULL(expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("input expr is null", K(ret)); - } else if (!expr->is_column_ref_expr()) { + } else if (OB_FAIL(ObRawExprUtils::get_real_expr_without_cast(expr, real_expr))) { + LOG_WARN("fail to get real expr", K(ret), K(expr)); + } else if (!real_expr->is_column_ref_expr()) { // do nothing - } else if (expr->get_result_type() != param_expr->get_result_type()) { - // do nothing - } else if (!ObOptimizerUtil::find_item(target_exprs, expr)) { + } else if (!ObOptimizerUtil::find_item(target_exprs, real_expr)) { // do nothing } else if (ObOptimizerUtil::find_item(first_params, expr)) { // do nothing + } else if (param_expr->get_result_type().get_type() != expr->get_result_type().get_type()) { + need_check_type_safe = is_type_safe(param_idx, i); + } else if (ob_is_string_or_lob_type(param_expr->get_result_type().get_type()) + && ((param_expr->get_result_type().get_collation_level() != expr->get_result_type().get_collation_level()) + || (param_expr->get_result_type().get_collation_type() != expr->get_result_type().get_collation_type()))) { + need_check_type_safe = is_type_safe(param_idx, i); } else if (OB_FAIL(equal_exprs.push_back(expr))) { LOG_WARN("failed to push back equal expr", K(ret)); } + if (OB_SUCC(ret) && need_check_type_safe && OB_FAIL(candi_exprs.push_back(expr))) { + LOG_WARN("failed to push back candi exprs whose result type is different from param_expr", K(ret)); + } } + if (OB_SUCC(ret) && !candi_exprs.empty()) { + bool type_safe = false; + if (OB_FAIL(check_cmp_metas_for_general_preds(param_expr, pred, type_safe))) { + LOG_WARN("fail to get cmp metas for the param expr", K(ret)); + } else if (type_safe) { + for (int64_t i = 0; OB_SUCC(ret) && i < candi_exprs.count(); ++i) { + type_safe = false; + if (OB_FAIL(check_cmp_metas_for_general_preds(candi_exprs.at(i), pred, type_safe))) { + LOG_WARN("fail to get cmp metas for candi exprs", K(ret)); + } else if (type_safe && OB_FAIL(equal_exprs.push_back(candi_exprs.at(i)))) { + LOG_WARN("failed to push back equal expr", K(ret)); + } + } + } + } + } + return ret; +} + +int ObPredicateDeduce::check_cmp_metas_for_general_preds(ObRawExpr *left_expr, ObRawExpr *pred, bool &type_safe) { + int ret = OB_SUCCESS; + ObObjMeta cmp_meta; + if (OB_ISNULL(left_expr) || OB_ISNULL(pred)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), K(left_expr), K(pred)); + } else if (T_OP_IN == pred->get_expr_type()) { + //params of preds like 'A in (a,b,c...)' has been grouped by result types in pre-process phase, + //for example: 'A in (int_a, int_b, float_a, float_b)' <=> A in (int_a, int_b) or A in (float_a, float_b) + //so only check the cmp type of A and the first param of row_op + ObRawExpr *right_expr = NULL; + if (OB_ISNULL(right_expr = pred->get_param_expr(1))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), K(right_expr)); + } else if (T_OP_ROW != right_expr->get_expr_type()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("the second param of in expr is not row_op", K(ret), K(right_expr->get_expr_type())); + } else if (OB_ISNULL(right_expr = right_expr->get_param_expr(0))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), K(right_expr)); + } else if (OB_FAIL(ObRelationalExprOperator::get_equal_meta(cmp_meta, left_expr->get_result_type(),right_expr->get_result_type()))) { + LOG_WARN("failed to get equal meta", K(ret)); + } else { + type_safe = (cmp_meta == cmp_type_); + } + } else if (T_OP_NE == pred->get_expr_type()) { + if (OB_ISNULL(pred->get_param_expr(1))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), K(pred->get_param_expr(1))); + } else if (OB_FAIL(ObRelationalExprOperator::get_equal_meta(cmp_meta, left_expr->get_result_type(),pred->get_param_expr(1)->get_result_type()))) { + LOG_WARN("failed to get equal meta", K(ret)); + } else { + type_safe = (cmp_meta == cmp_type_); + } + } else if (T_OP_BTW == pred->get_expr_type()) { + if (OB_ISNULL(pred->get_param_expr(1)) || OB_ISNULL(pred->get_param_expr(2))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), K(pred->get_param_expr(1)), K(pred->get_param_expr(2))); + } else if (OB_FAIL(ObRelationalExprOperator::get_equal_meta(cmp_meta, left_expr->get_result_type(), pred->get_param_expr(1)->get_result_type()))) { + LOG_WARN("failed to get equal meta", K(ret)); + } else if (cmp_meta != cmp_type_) { + } else if (OB_FAIL(ObRelationalExprOperator::get_equal_meta(cmp_meta, left_expr->get_result_type(), pred->get_param_expr(2)->get_result_type()))) { + LOG_WARN("failed to get equal meta", K(ret)); + } else { + type_safe = (cmp_meta == cmp_type_); + } + } else { + type_safe = false; } return ret; } diff --git a/src/sql/rewrite/ob_predicate_deduce.h b/src/sql/rewrite/ob_predicate_deduce.h index dc469f102f..2b62e798d4 100644 --- a/src/sql/rewrite/ob_predicate_deduce.h +++ b/src/sql/rewrite/ob_predicate_deduce.h @@ -243,6 +243,8 @@ private: ObRawExpr *right_expr, bool &is_valid); + int check_cmp_metas_for_general_preds(ObRawExpr *left_pexr, ObRawExpr *pred, bool &type_safe); + private: ObObjMeta cmp_type_; // the compare meta used by all exprs in the graph diff --git a/src/sql/rewrite/ob_transform_predicate_move_around.cpp b/src/sql/rewrite/ob_transform_predicate_move_around.cpp index fb5e008ef1..6a50f0c7d4 100644 --- a/src/sql/rewrite/ob_transform_predicate_move_around.cpp +++ b/src/sql/rewrite/ob_transform_predicate_move_around.cpp @@ -1487,18 +1487,34 @@ int ObTransformPredicateMoveAround::pullup_predicates_from_const_select(ObSelect ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid select list", K(child_select_list.count()), K(parent_select_list), K(ret)); } else { - for (int64_t i = 0; OB_SUCC(ret) && i < child_select_list.count(); ++i) { - ObRawExpr *child_expr = child_select_list.at(i); + for (int64_t i = 0; OB_SUCC(ret) && i < parent_select_list.count(); ++i) { + ObRawExpr *child_expr = NULL; ObRawExpr *parent_expr = parent_select_list.at(i); + const ObRawExpr *real_parent_expr = parent_select_list.at(i); ObRawExpr *generated_expr = NULL; bool is_not_null = false; - if (OB_ISNULL(child_expr) || OB_ISNULL(parent_expr)) { + int64_t child_idx = OB_INVALID_ID; + if (OB_ISNULL(parent_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid expr", K(ret)); + } else if (OB_FAIL(ObRawExprUtils::get_real_expr_without_cast(parent_expr, real_parent_expr))) { + LOG_WARN("fail to get real expr", K(ret)); + } else if (OB_ISNULL(real_parent_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid expr", K(ret), K(real_parent_expr)); + } else if (!real_parent_expr->is_set_op_expr()) { + // do nothing + } else if (FALSE_IT(child_idx = static_cast(real_parent_expr)->get_idx())) { + } else if (OB_UNLIKELY(child_idx < 0 || child_idx >= child_select_list.count())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("set op index is invalid", K(ret), K(child_idx)); + } else if (OB_ISNULL(child_expr = child_select_list.at(child_idx))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid expr", K(ret)); } else if (!child_expr->is_const_expr()) { // do nothing } else if (child_expr->get_result_type().is_ext() || - parent_expr->get_result_type().is_ext()) { + real_parent_expr->get_result_type().is_ext()) { // OP_EQ between udt not supported } else if (OB_FAIL(ObTransformUtils::is_expr_not_null( ctx_, child_stmt, child_expr, NULLABLE_SCOPE::NS_TOP, is_not_null))) { @@ -1519,10 +1535,10 @@ int ObTransformPredicateMoveAround::pullup_predicates_from_const_select(ObSelect && !(lib::is_oracle_mode() && result.is_null_oracle()))) { //do nothing } else if (OB_FAIL(ObRawExprUtils::build_is_not_null_expr(*ctx_->expr_factory_, - parent_expr, + const_cast(real_parent_expr), false, generated_expr))) { - LOG_WARN("fail to build is null expr", K(ret), K(parent_expr)); + LOG_WARN("fail to build is null expr", K(ret), K(real_parent_expr)); } else if (OB_ISNULL(generated_expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("is_null expr is null", K(ret)); @@ -1531,7 +1547,7 @@ int ObTransformPredicateMoveAround::pullup_predicates_from_const_select(ObSelect } else {} } else if (OB_FAIL(ObRawExprUtils::create_double_op_expr( *(ctx_->expr_factory_), ctx_->session_info_, T_OP_EQ, - generated_expr, parent_expr, child_expr))) { + generated_expr, const_cast(real_parent_expr), child_expr))) { LOG_WARN("failed to create double op expr", K(ret)); } if (OB_FAIL(ret) || NULL == generated_expr) { diff --git a/tools/deploy/mysql_test/test_suite/transformer/r/mysql/transformer_predicate_deduce.result b/tools/deploy/mysql_test/test_suite/transformer/r/mysql/transformer_predicate_deduce.result index 43f873e6cb..a4143ca86b 100644 --- a/tools/deploy/mysql_test/test_suite/transformer/r/mysql/transformer_predicate_deduce.result +++ b/tools/deploy/mysql_test/test_suite/transformer/r/mysql/transformer_predicate_deduce.result @@ -3781,5 +3781,506 @@ Outputs & filters: drop table if exists t1, t2, t3; drop table if exists tt1, tt2, tt3; drop table if exists cghldinf, puzdjypf, pujydypf; +drop table if exists v0; +CREATE TABLE v0 ( v1 varchar(127)); +EXPLAIN select * from v0 where v1 in (select -127 minus select _BINARY 'x'); +Query Plan +============================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +---------------------------------------------- +|0 |MERGE JOIN | |1 |2 | +|1 | SUBPLAN SCAN|VIEW1|1 |1 | +|2 | EXPRESSION | |1 |1 | +|3 | SORT | |1 |2 | +|4 | TABLE SCAN |v0 |1 |2 | +============================================== +Outputs & filters: +------------------------------------- + 0 - output([v0.v1]), filter(nil), rowset=256 + equal_conds([v0.v1 = VIEW1.-127]), other_conds(nil) + merge_directions([ASC]) + 1 - output([VIEW1.-127]), filter(nil), rowset=256 + access([VIEW1.-127]) + 2 - output([cast(-127, VARCHAR(20))]), filter(nil) + values({cast(-127, VARCHAR(20))}) + 3 - output([v0.v1]), filter(nil), rowset=256 + sort_keys([v0.v1, ASC]) + 4 - output([v0.v1]), filter(nil), rowset=256 + access([v0.v1]), partitions(p0) + is_index_back=false, is_global_index=false, + range_key([v0.__pk_increment]), range(MIN ; MAX)always true +select * from v0 where v1 in (select -127 minus select _BINARY 'x'); +ERROR HY000: Internal error +explain select * from v0 where v1 in (select -127 minus select _BINARY 'x'); +Query Plan +============================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +---------------------------------------------- +|0 |MERGE JOIN | |1 |2 | +|1 | SUBPLAN SCAN|VIEW1|1 |1 | +|2 | EXPRESSION | |1 |1 | +|3 | SORT | |1 |2 | +|4 | TABLE SCAN |v0 |1 |2 | +============================================== +Outputs & filters: +------------------------------------- + 0 - output([v0.v1]), filter(nil), rowset=256 + equal_conds([v0.v1 = VIEW1.-127]), other_conds(nil) + merge_directions([ASC]) + 1 - output([VIEW1.-127]), filter(nil), rowset=256 + access([VIEW1.-127]) + 2 - output([cast(-127, VARCHAR(20))]), filter(nil) + values({cast(-127, VARCHAR(20))}) + 3 - output([v0.v1]), filter(nil), rowset=256 + sort_keys([v0.v1, ASC]) + 4 - output([v0.v1]), filter(nil), rowset=256 + access([v0.v1]), partitions(p0) + is_index_back=false, is_global_index=false, + range_key([v0.__pk_increment]), range(MIN ; MAX)always true +drop table if exists v0; + +explain_protocol: 0 +drop table if exists t1; +drop table if exists t2; +drop table if exists t3; +create table t1(c1 decimal(10), c2 varchar(10), c3 varbinary(20)); +insert into t1(c1,c2) values(10,'a'),(20,'ab'),(50,'ad'),(100,'b'),(150,'c'); +create table t2(c1 decimal(20), c2 double, c3 varchar(20)); +insert into t2(c1,c2,c3) values(10,10,'a'),(20,20,'b'),(50,50,NULL),(100,100,NULL),(150,150,NULL); +create table t3(c1 decimal(16), c2 float); +insert into t3(c1,c2) values(10,10),(20,20),(50,50),(100,100),(150,150); +explain_protocol: 2 +test IN pred +### different accuracy +EXPLAIN select t1.c1,t2.c1 from t1,t2 where t1.c1 = t2.c1 and t2.c1 in (10,20,40); +Query Plan +=========================================== +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +------------------------------------------- +|0 |HASH JOIN | |4 |5 | +|1 | TABLE SCAN|t1 |4 |2 | +|2 | TABLE SCAN|t2 |4 |2 | +=========================================== +Outputs & filters: +------------------------------------- + 0 - output([t1.c1], [t2.c1]), filter(nil), rowset=256 + equal_conds([t1.c1 = t2.c1]), other_conds(nil) + 1 - output([t1.c1]), filter([t1.c1 IN (cast(10, DECIMAL(2, 0)), cast(20, DECIMAL(2, 0)), cast(40, DECIMAL(2, 0)))]), rowset=256 + access([t1.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t1.__pk_increment]), range(MIN ; MAX)always true + 2 - output([t2.c1]), filter([t2.c1 IN (cast(10, DECIMAL(2, 0)), cast(20, DECIMAL(2, 0)), cast(40, DECIMAL(2, 0)))]), rowset=256 + access([t2.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t2.__pk_increment]), range(MIN ; MAX)always true +select t1.c1,t2.c1 from t1,t2 where t1.c1 = t2.c1 and t2.c1 in (10,20,40); ++------+------+ +| c1 | c1 | ++------+------+ +| 10 | 10 | +| 20 | 20 | ++------+------+ +EXPLAIN select t1.c1,t2.c1 from t1,t2 where t1.c1 = t2.c1 and t1.c1 in (10,20,40); +Query Plan +=========================================== +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +------------------------------------------- +|0 |HASH JOIN | |4 |5 | +|1 | TABLE SCAN|t1 |4 |2 | +|2 | TABLE SCAN|t2 |4 |2 | +=========================================== +Outputs & filters: +------------------------------------- + 0 - output([t1.c1], [t2.c1]), filter(nil), rowset=256 + equal_conds([t1.c1 = t2.c1]), other_conds(nil) + 1 - output([t1.c1]), filter([t1.c1 IN (cast(10, DECIMAL(2, 0)), cast(20, DECIMAL(2, 0)), cast(40, DECIMAL(2, 0)))]), rowset=256 + access([t1.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t1.__pk_increment]), range(MIN ; MAX)always true + 2 - output([t2.c1]), filter([t2.c1 IN (cast(10, DECIMAL(2, 0)), cast(20, DECIMAL(2, 0)), cast(40, DECIMAL(2, 0)))]), rowset=256 + access([t2.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t2.__pk_increment]), range(MIN ; MAX)always true +select t1.c1,t2.c1 from t1,t2 where t1.c1 = t2.c1 and t1.c1 in (10,20,40); ++------+------+ +| c1 | c1 | ++------+------+ +| 10 | 10 | +| 20 | 20 | ++------+------+ +EXPLAIN select t1.c1,t2.c1 from t1,t2,t3 where t1.c1 = t3.c1 and t2.c1 = t3.c1 and t1.c1 in (10,20,40); +Query Plan +============================================ +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +-------------------------------------------- +|0 |HASH JOIN | |4 |8 | +|1 | TABLE SCAN |t3 |4 |2 | +|2 | HASH JOIN | |4 |5 | +|3 | TABLE SCAN|t1 |4 |2 | +|4 | TABLE SCAN|t2 |4 |2 | +============================================ +Outputs & filters: +------------------------------------- + 0 - output([t1.c1], [t2.c1]), filter(nil), rowset=256 + equal_conds([t1.c1 = t3.c1]), other_conds(nil) + 1 - output([t3.c1]), filter([t3.c1 IN (cast(10, DECIMAL(2, 0)), cast(20, DECIMAL(2, 0)), cast(40, DECIMAL(2, 0)))]), rowset=256 + access([t3.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t3.__pk_increment]), range(MIN ; MAX)always true + 2 - output([t1.c1], [t2.c1]), filter(nil), rowset=256 + equal_conds([t1.c1 = t2.c1]), other_conds(nil) + 3 - output([t1.c1]), filter([t1.c1 IN (cast(10, DECIMAL(2, 0)), cast(20, DECIMAL(2, 0)), cast(40, DECIMAL(2, 0)))]), rowset=256 + access([t1.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t1.__pk_increment]), range(MIN ; MAX)always true + 4 - output([t2.c1]), filter([t2.c1 IN (cast(10, DECIMAL(2, 0)), cast(20, DECIMAL(2, 0)), cast(40, DECIMAL(2, 0)))]), rowset=256 + access([t2.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t2.__pk_increment]), range(MIN ; MAX)always true +select t1.c1,t2.c1 from t1,t2,t3 where t1.c1 = t3.c1 and t2.c1 = t3.c1 and t1.c1 in (10,20,40); ++------+------+ +| c1 | c1 | ++------+------+ +| 10 | 10 | +| 20 | 20 | ++------+------+ +### different types +####preds are 'cast(t1.c1,double) = cast(t3.c2,double)' and 'cast(t3.c2,double) in (10,20,40)'. cast(t3.c2,double) is not column ref, so 't1.c1 in (10,20,40)' won't be deduced. +EXPLAIN select * from t1,t3 where t1.c1 = t3.c2 and t3.c2 in (10,20,40); +Query Plan +=========================================== +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +------------------------------------------- +|0 |HASH JOIN | |5 |5 | +|1 | TABLE SCAN|t3 |4 |3 | +|2 | TABLE SCAN|t1 |5 |2 | +=========================================== +Outputs & filters: +------------------------------------- + 0 - output([t1.c1], [t1.c2], [t1.c3], [t3.c1], [t3.c2]), filter(nil), rowset=256 + equal_conds([cast(t1.c1, DOUBLE(-1, -1)) = cast(t3.c2, DOUBLE(-1, -1))]), other_conds(nil) + 1 - output([t3.c2], [t3.c1], [cast(t3.c2, DOUBLE(-1, -1))]), filter([cast(t3.c2, DOUBLE(-1, -1)) IN (cast(10, DOUBLE(-1, -1)), cast(20, DOUBLE(-1, -1)), +cast(40, DOUBLE(-1, -1)))]), rowset=256 + access([t3.c2], [t3.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t3.__pk_increment]), range(MIN ; MAX)always true + 2 - output([t1.c1], [t1.c2], [t1.c3]), filter(nil), rowset=256 + access([t1.c1], [t1.c2], [t1.c3]), partitions(p0) + is_index_back=false, is_global_index=false, + range_key([t1.__pk_increment]), range(MIN ; MAX)always true +select * from t1,t3 where t1.c1 = t3.c2 and t3.c2 in (10,20,40); ++------+------+------+------+------+ +| c1 | c2 | c3 | c1 | c2 | ++------+------+------+------+------+ +| 10 | a | NULL | 10 | 10 | +| 20 | ab | NULL | 20 | 20 | ++------+------+------+------+------+ +####different collection type +EXPLAIN select * from t1,t2 where t1.c3 = t2.c3 and t2.c3 in ('a','b','c'); +Query Plan +=========================================== +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +------------------------------------------- +|0 |HASH JOIN | |4 |7 | +|1 | TABLE SCAN|t2 |4 |2 | +|2 | TABLE SCAN|t1 |5 |2 | +=========================================== +Outputs & filters: +------------------------------------- + 0 - output([t1.c1], [t1.c2], [t1.c3], [t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=256 + equal_conds([t1.c3 = cast(t2.c3, VARCHAR(1048576))]), other_conds(nil) + 1 - output([t2.c3], [t2.c1], [t2.c2]), filter([t2.c3 IN ('a', 'b', 'c')]), rowset=256 + access([t2.c3], [t2.c1], [t2.c2]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t2.__pk_increment]), range(MIN ; MAX)always true + 2 - output([t1.c3], [t1.c1], [t1.c2]), filter(nil), rowset=256 + access([t1.c3], [t1.c1], [t1.c2]), partitions(p0) + is_index_back=false, is_global_index=false, + range_key([t1.__pk_increment]), range(MIN ; MAX)always true +select * from t1,t2 where t1.c3 = t2.c3 and t2.c3 in ('a','b','c'); ++------+------+------+------+------+------+ +| c1 | c2 | c3 | c1 | c2 | c3 | ++------+------+------+------+------+------+ ++------+------+------+------+------+------+ +EXPLAIN select * from t1,t2 where t1.c3 = t2.c3 and t1.c3 in ('a','b','c'); +Query Plan +=========================================== +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +------------------------------------------- +|0 |HASH JOIN | |1 |5 | +|1 | TABLE SCAN|t2 |1 |2 | +|2 | TABLE SCAN|t1 |4 |2 | +=========================================== +Outputs & filters: +------------------------------------- + 0 - output([t1.c1], [t1.c2], [t1.c3], [t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=256 + equal_conds([t1.c3 = cast(t2.c3, VARCHAR(1048576))]), other_conds(nil) + 1 - output([t2.c3], [t2.c1], [t2.c2], [cast(t2.c3, VARCHAR(1048576))]), filter([cast(t2.c3, VARCHAR(1048576)) IN (cast('a', VARCHAR(1048576)), cast('b', +VARCHAR(1048576)), cast('c', VARCHAR(1048576)))]), rowset=256 + access([t2.c3], [t2.c1], [t2.c2]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t2.__pk_increment]), range(MIN ; MAX)always true + 2 - output([t1.c3], [t1.c1], [t1.c2]), filter([t1.c3 IN (cast('a', VARCHAR(1048576)), cast('b', VARCHAR(1048576)), cast('c', VARCHAR(1048576)))]), rowset=256 + access([t1.c3], [t1.c1], [t1.c2]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t1.__pk_increment]), range(MIN ; MAX)always true +select * from t1,t2 where t1.c3 = t2.c3 and t1.c3 in ('a','b','c'); ++------+------+------+------+------+------+ +| c1 | c2 | c3 | c1 | c2 | c3 | ++------+------+------+------+------+------+ ++------+------+------+------+------+------+ +test NOT EQUAL +EXPLAIN select t1.c1,t2.c1 from t1,t2 where t1.c1 = t2.c1 and t2.c1 <> 20; +Query Plan +=========================================== +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +------------------------------------------- +|0 |HASH JOIN | |4 |5 | +|1 | TABLE SCAN|t1 |4 |2 | +|2 | TABLE SCAN|t2 |4 |2 | +=========================================== +Outputs & filters: +------------------------------------- + 0 - output([t1.c1], [t2.c1]), filter(nil), rowset=256 + equal_conds([t1.c1 = t2.c1]), other_conds(nil) + 1 - output([t1.c1]), filter([t1.c1 != cast(20, DECIMAL(2, 0))]), rowset=256 + access([t1.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t1.__pk_increment]), range(MIN ; MAX)always true + 2 - output([t2.c1]), filter([t2.c1 != cast(20, DECIMAL(2, 0))]), rowset=256 + access([t2.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t2.__pk_increment]), range(MIN ; MAX)always true +select t1.c1,t2.c1 from t1,t2 where t1.c1 = t2.c1 and t2.c1 <> 20; ++------+------+ +| c1 | c1 | ++------+------+ +| 10 | 10 | +| 50 | 50 | +| 100 | 100 | +| 150 | 150 | ++------+------+ +EXPLAIN select t1.c1,t2.c1 from t1,t2 where t1.c1 = t2.c1 and t1.c1 <> 20; +Query Plan +=========================================== +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +------------------------------------------- +|0 |HASH JOIN | |4 |5 | +|1 | TABLE SCAN|t1 |4 |2 | +|2 | TABLE SCAN|t2 |4 |2 | +=========================================== +Outputs & filters: +------------------------------------- + 0 - output([t1.c1], [t2.c1]), filter(nil), rowset=256 + equal_conds([t1.c1 = t2.c1]), other_conds(nil) + 1 - output([t1.c1]), filter([t1.c1 != cast(20, DECIMAL(2, 0))]), rowset=256 + access([t1.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t1.__pk_increment]), range(MIN ; MAX)always true + 2 - output([t2.c1]), filter([t2.c1 != cast(20, DECIMAL(2, 0))]), rowset=256 + access([t2.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t2.__pk_increment]), range(MIN ; MAX)always true +select t1.c1,t2.c1 from t1,t2 where t1.c1 = t2.c1 and t1.c1 <> 20; ++------+------+ +| c1 | c1 | ++------+------+ +| 10 | 10 | +| 50 | 50 | +| 100 | 100 | +| 150 | 150 | ++------+------+ +EXPLAIN select t1.c1,t2.c1 from t1,t2,t3 where t1.c1 = t3.c1 and t2.c1 = t3.c1 and t1.c1 <>20; +Query Plan +============================================ +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +-------------------------------------------- +|0 |HASH JOIN | |4 |8 | +|1 | TABLE SCAN |t3 |4 |2 | +|2 | HASH JOIN | |4 |5 | +|3 | TABLE SCAN|t1 |4 |2 | +|4 | TABLE SCAN|t2 |4 |2 | +============================================ +Outputs & filters: +------------------------------------- + 0 - output([t1.c1], [t2.c1]), filter(nil), rowset=256 + equal_conds([t1.c1 = t3.c1]), other_conds(nil) + 1 - output([t3.c1]), filter([t3.c1 != cast(20, DECIMAL(2, 0))]), rowset=256 + access([t3.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t3.__pk_increment]), range(MIN ; MAX)always true + 2 - output([t1.c1], [t2.c1]), filter(nil), rowset=256 + equal_conds([t1.c1 = t2.c1]), other_conds(nil) + 3 - output([t1.c1]), filter([t1.c1 != cast(20, DECIMAL(2, 0))]), rowset=256 + access([t1.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t1.__pk_increment]), range(MIN ; MAX)always true + 4 - output([t2.c1]), filter([t2.c1 != cast(20, DECIMAL(2, 0))]), rowset=256 + access([t2.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t2.__pk_increment]), range(MIN ; MAX)always true +select t1.c1,t2.c1 from t1,t2,t3 where t1.c1 = t3.c1 and t2.c1 = t3.c1 and t1.c1 <>20; ++------+------+ +| c1 | c1 | ++------+------+ +| 10 | 10 | +| 50 | 50 | +| 100 | 100 | +| 150 | 150 | ++------+------+ +EXPLAIN select * from t1,t3 where t1.c1 = t3.c2 and t3.c2 <> 20; +Query Plan +=========================================== +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +------------------------------------------- +|0 |HASH JOIN | |5 |6 | +|1 | TABLE SCAN|t3 |4 |3 | +|2 | TABLE SCAN|t1 |5 |2 | +=========================================== +Outputs & filters: +------------------------------------- + 0 - output([t1.c1], [t1.c2], [t1.c3], [t3.c1], [t3.c2]), filter(nil), rowset=256 + equal_conds([cast(t1.c1, DOUBLE(-1, -1)) = cast(t3.c2, DOUBLE(-1, -1))]), other_conds(nil) + 1 - output([t3.c2], [t3.c1], [cast(t3.c2, DOUBLE(-1, -1))]), filter([cast(t3.c2, DOUBLE(-1, -1)) != cast(20, DOUBLE(-1, -1))]), rowset=256 + access([t3.c2], [t3.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t3.__pk_increment]), range(MIN ; MAX)always true + 2 - output([t1.c1], [t1.c2], [t1.c3]), filter(nil), rowset=256 + access([t1.c1], [t1.c2], [t1.c3]), partitions(p0) + is_index_back=false, is_global_index=false, + range_key([t1.__pk_increment]), range(MIN ; MAX)always true +select * from t1,t3 where t1.c1 = t3.c2 and t3.c2 <> 20; ++------+------+------+------+------+ +| c1 | c2 | c3 | c1 | c2 | ++------+------+------+------+------+ +| 10 | a | NULL | 10 | 10 | +| 50 | ad | NULL | 50 | 50 | +| 100 | b | NULL | 100 | 100 | +| 150 | c | NULL | 150 | 150 | ++------+------+------+------+------+ + +test BETWEEN +### differnt types +EXPLAIN select t3.c1,t2.c1 from t3,t2 where t3.c2 = t2.c2 and t2.c2 between 10 and cast(100 as float); +Query Plan +=========================================== +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +------------------------------------------- +|0 |HASH JOIN | |1 |4 | +|1 | TABLE SCAN|t3 |1 |2 | +|2 | TABLE SCAN|t2 |1 |2 | +=========================================== +Outputs & filters: +------------------------------------- + 0 - output([t3.c1], [t2.c1]), filter(nil), rowset=256 + equal_conds([cast(t3.c2, DOUBLE(-1, -1)) = t2.c2]), other_conds(nil) + 1 - output([t3.c1], [cast(t3.c2, DOUBLE(-1, -1))]), filter([(T_OP_BTW, cast(t3.c2, DOUBLE(-1, -1)), cast(10, DOUBLE(-1, -1)), cast(cast(100, FLOAT(0, +-1)), DOUBLE(-1, -1)))]), rowset=256 + access([t3.c2], [t3.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t3.__pk_increment]), range(MIN ; MAX)always true + 2 - output([t2.c2], [t2.c1]), filter([(T_OP_BTW, t2.c2, cast(10, DOUBLE(-1, -1)), cast(cast(100, FLOAT(0, -1)), DOUBLE(-1, -1)))]), rowset=256 + access([t2.c2], [t2.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t2.__pk_increment]), range(MIN ; MAX)always true +select t3.c1,t2.c1 from t3,t2 where t3.c2 = t2.c2 and t2.c2 between 10 and cast(100 as float); ++------+------+ +| c1 | c1 | ++------+------+ +| 10 | 10 | +| 20 | 20 | +| 50 | 50 | +| 100 | 100 | ++------+------+ +EXPLAIN select t3.c1,t2.c1 from t3,t2 where t3.c2 = t2.c2 and t3.c2 between 10 and cast(100 as float); +Query Plan +=========================================== +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +------------------------------------------- +|0 |HASH JOIN | |1 |5 | +|1 | TABLE SCAN|t3 |1 |2 | +|2 | TABLE SCAN|t2 |5 |2 | +=========================================== +Outputs & filters: +------------------------------------- + 0 - output([t3.c1], [t2.c1]), filter(nil), rowset=256 + equal_conds([cast(t3.c2, DOUBLE(-1, -1)) = t2.c2]), other_conds(nil) + 1 - output([t3.c1], [cast(t3.c2, DOUBLE(-1, -1))]), filter([(T_OP_BTW, cast(t3.c2, DOUBLE(-1, -1)), cast(10, DOUBLE(-1, -1)), cast(cast(100, FLOAT(0, +-1)), DOUBLE(-1, -1)))]), rowset=256 + access([t3.c2], [t3.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t3.__pk_increment]), range(MIN ; MAX)always true + 2 - output([t2.c2], [t2.c1]), filter(nil), rowset=256 + access([t2.c2], [t2.c1]), partitions(p0) + is_index_back=false, is_global_index=false, + range_key([t2.__pk_increment]), range(MIN ; MAX)always true +select t3.c1,t2.c1 from t3,t2 where t3.c2 = t2.c2 and t3.c2 between 10 and cast(100 as float); ++------+------+ +| c1 | c1 | ++------+------+ +| 10 | 10 | +| 20 | 20 | +| 50 | 50 | +| 100 | 100 | ++------+------+ + +test LIKE +EXPLAIN select t1.c1,t2.c1 from t1,t2 where t1.c2 = t2.c3 and t2.c3 like 'a_'; +Query Plan +=========================================== +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +------------------------------------------- +|0 |HASH JOIN | |1 |5 | +|1 | TABLE SCAN|t1 |1 |2 | +|2 | TABLE SCAN|t2 |1 |2 | +=========================================== +Outputs & filters: +------------------------------------- + 0 - output([t1.c1], [t2.c1]), filter(nil), rowset=256 + equal_conds([t1.c2 = t2.c3]), other_conds(nil) + 1 - output([t1.c2], [t1.c1]), filter([(T_OP_LIKE, t1.c2, 'a_', '\\')]), rowset=256 + access([t1.c2], [t1.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t1.__pk_increment]), range(MIN ; MAX)always true + 2 - output([t2.c3], [t2.c1]), filter([(T_OP_LIKE, t2.c3, 'a_', '\\')]), rowset=256 + access([t2.c3], [t2.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t2.__pk_increment]), range(MIN ; MAX)always true +select t1.c1,t2.c1 from t1,t2 where t1.c2 = t2.c3 and t2.c3 like 'a_'; ++------+------+ +| c1 | c1 | ++------+------+ ++------+------+ +EXPLAIN select t1.c1,t2.c1 from t1,t2 where t1.c2 = t2.c3 and t1.c2 like 'a_'; +Query Plan +=========================================== +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +------------------------------------------- +|0 |HASH JOIN | |1 |5 | +|1 | TABLE SCAN|t1 |1 |2 | +|2 | TABLE SCAN|t2 |1 |2 | +=========================================== +Outputs & filters: +------------------------------------- + 0 - output([t1.c1], [t2.c1]), filter(nil), rowset=256 + equal_conds([t1.c2 = t2.c3]), other_conds(nil) + 1 - output([t1.c2], [t1.c1]), filter([(T_OP_LIKE, t1.c2, 'a_', '\\')]), rowset=256 + access([t1.c2], [t1.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t1.__pk_increment]), range(MIN ; MAX)always true + 2 - output([t2.c3], [t2.c1]), filter([(T_OP_LIKE, t2.c3, 'a_', '\\')]), rowset=256 + access([t2.c3], [t2.c1]), partitions(p0) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t2.__pk_increment]), range(MIN ; MAX)always true +select t1.c1,t2.c1 from t1,t2 where t1.c2 = t2.c3 and t1.c2 like 'a_'; ++------+------+ +| c1 | c1 | ++------+------+ ++------+------+ + +drop table t1; +drop table t2; +drop table t3; + USE DB_PREDICATE_DEDUCE; drop database DB_PREDICATE_DEDUCE; diff --git a/tools/deploy/mysql_test/test_suite/transformer/t/transformer_predicate_deduce.test b/tools/deploy/mysql_test/test_suite/transformer/t/transformer_predicate_deduce.test index ea5b90f952..88d6707332 100644 --- a/tools/deploy/mysql_test/test_suite/transformer/t/transformer_predicate_deduce.test +++ b/tools/deploy/mysql_test/test_suite/transformer/t/transformer_predicate_deduce.test @@ -432,5 +432,59 @@ drop table if exists tt1, tt2, tt3; drop table if exists cghldinf, puzdjypf, pujydypf; --enable_warnings +#Bugfix:https://work.aone.alibaba-inc.com/issue/47217185 +--disable_warnings +drop table if exists v0; +--enable_warnings +CREATE TABLE v0 ( v1 varchar(127)); +select * from v0 where v1 in (select -127 minus select _BINARY 'x'); +explain select * from v0 where v1 in (select -127 minus select _BINARY 'x'); +drop table if exists v0; + + +#Bugfix:https://work.aone.alibaba-inc.com/issue/47186369 +--explain_protocol 0 +--disable_warnings +drop table if exists t1; +drop table if exists t2; +drop table if exists t3; +--enable_warnings +create table t1(c1 decimal(10), c2 varchar(10), c3 varbinary(20)); +insert into t1(c1,c2) values(10,'a'),(20,'ab'),(50,'ad'),(100,'b'),(150,'c'); +create table t2(c1 decimal(20), c2 double, c3 varchar(20)); +insert into t2(c1,c2,c3) values(10,10,'a'),(20,20,'b'),(50,50,NULL),(100,100,NULL),(150,150,NULL); +create table t3(c1 decimal(16), c2 float); +insert into t3(c1,c2) values(10,10),(20,20),(50,50),(100,100),(150,150); +--explain_protocol 2 +--echo test IN pred +### different accuracy +select t1.c1,t2.c1 from t1,t2 where t1.c1 = t2.c1 and t2.c1 in (10,20,40); +select t1.c1,t2.c1 from t1,t2 where t1.c1 = t2.c1 and t1.c1 in (10,20,40); +select t1.c1,t2.c1 from t1,t2,t3 where t1.c1 = t3.c1 and t2.c1 = t3.c1 and t1.c1 in (10,20,40); +### different types +####preds are 'cast(t1.c1,double) = cast(t3.c2,double)' and 'cast(t3.c2,double) in (10,20,40)'. cast(t3.c2,double) is not column ref, so 't1.c1 in (10,20,40)' won't be deduced. +select * from t1,t3 where t1.c1 = t3.c2 and t3.c2 in (10,20,40); +####different collection type +select * from t1,t2 where t1.c3 = t2.c3 and t2.c3 in ('a','b','c'); +select * from t1,t2 where t1.c3 = t2.c3 and t1.c3 in ('a','b','c'); +--echo test NOT EQUAL +select t1.c1,t2.c1 from t1,t2 where t1.c1 = t2.c1 and t2.c1 <> 20; +select t1.c1,t2.c1 from t1,t2 where t1.c1 = t2.c1 and t1.c1 <> 20; +select t1.c1,t2.c1 from t1,t2,t3 where t1.c1 = t3.c1 and t2.c1 = t3.c1 and t1.c1 <>20; +select * from t1,t3 where t1.c1 = t3.c2 and t3.c2 <> 20; + +--echo test BETWEEN +### differnt types +select t3.c1,t2.c1 from t3,t2 where t3.c2 = t2.c2 and t2.c2 between 10 and cast(100 as float); +select t3.c1,t2.c1 from t3,t2 where t3.c2 = t2.c2 and t3.c2 between 10 and cast(100 as float); + +--echo test LIKE +select t1.c1,t2.c1 from t1,t2 where t1.c2 = t2.c3 and t2.c3 like 'a_'; +select t1.c1,t2.c1 from t1,t2 where t1.c2 = t2.c3 and t1.c2 like 'a_'; + +drop table t1; +drop table t2; +drop table t3; + USE DB_PREDICATE_DEDUCE; drop database DB_PREDICATE_DEDUCE;