diff --git a/src/share/ob_i_sql_expression.h b/src/share/ob_i_sql_expression.h index 20eb29f3ea..aad57ee352 100644 --- a/src/share/ob_i_sql_expression.h +++ b/src/share/ob_i_sql_expression.h @@ -148,7 +148,8 @@ public: session_(NULL), udf_meta_(NULL), cast_mode_(CM_NONE), - raw_expr_(NULL) + raw_expr_(NULL), + cur_row_idx_(0) {} inline ObCollationType get_coll_type() const { @@ -196,6 +197,9 @@ public: void set_raw_expr(sql::ObRawExpr *expr) { raw_expr_ = expr; } sql::ObRawExpr *get_raw_expr() { return raw_expr_; } + inline void set_cur_row_idx(int64_t cur_row_idx) { cur_row_idx_ = cur_row_idx; } + inline int64_t get_cur_row_idx() { return cur_row_idx_; } + TO_STRING_KV(K_(coll_type), K_(div_precision_increment), K_(ob_max_allowed_packet), @@ -215,6 +219,8 @@ private: // Usually need to override get_cast_mode() of ObExprOperator which works for non_static engine common::ObCastMode cast_mode_; sql::ObRawExpr *raw_expr_; + //used to switch params in subquery comparison operators + int64_t cur_row_idx_; }; class ObISqlExpression diff --git a/src/sql/engine/expr/ob_expr_operator.cpp b/src/sql/engine/expr/ob_expr_operator.cpp index d8fc07b3d8..bb7fddc838 100644 --- a/src/sql/engine/expr/ob_expr_operator.cpp +++ b/src/sql/engine/expr/ob_expr_operator.cpp @@ -31,6 +31,7 @@ #include "sql/engine/expr/ob_expr_util.h" #include "sql/engine/subquery/ob_subplan_filter_op.h" #include "lib/timezone/ob_oracle_format_models.h" +#include "sql/resolver/dml/ob_select_stmt.h" namespace oceanbase { @@ -2127,29 +2128,55 @@ int ObRelationalExprOperator::deduce_cmp_type(const ObExprOperator &expr, const ObRawExpr* other_expr = cmp_expr->get_param_expr(1); ObObjType other_expr_type = ObMaxType; bool is_date_op_other = false; - if (OB_ISNULL(cmp_expr) || OB_ISNULL(date_expr) || OB_ISNULL(other_expr)) { + if (OB_ISNULL(cmp_expr) || OB_ISNULL(date_expr) || OB_ISNULL(other_expr) ) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null", K(ret), K(cmp_expr)); - } else if (date_expr->get_result_type().get_type() == ObDateType || - date_expr->get_result_type().get_type() == ObDateTimeType) { - other_expr_type = other_expr->get_result_type().get_type(); - is_date_op_other = true; - } else if (other_expr->get_result_type().get_type() == ObDateType || - other_expr->get_result_type().get_type() == ObDateTimeType) { - const ObRawExpr *tmp_expr = date_expr; - date_expr = other_expr; - other_expr = tmp_expr; - other_expr_type = other_expr->get_result_type().get_type(); - is_date_op_other = true; + LOG_WARN("unexpected null", K(ret), K(cmp_expr), K(date_expr), K(other_expr)); } else { - //do nothing + if (T_REF_QUERY == other_expr->get_expr_type()) { + const ObQueryRefRawExpr *ref_expr = static_cast(other_expr); + if (OB_ISNULL(ref_expr->get_ref_stmt())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else { + other_expr = ref_expr->get_ref_stmt()->get_select_item(type_ctx.get_cur_row_idx()).expr_; + } + } else if (T_OP_ROW == other_expr->get_expr_type()) { + other_expr = other_expr->get_param_expr(type_ctx.get_cur_row_idx()); + } + if (OB_FAIL(ret)) { + } else if (T_REF_QUERY == date_expr->get_expr_type()) { + const ObQueryRefRawExpr *ref_expr = static_cast(date_expr); + if (OB_ISNULL(ref_expr->get_ref_stmt())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else { + date_expr = ref_expr->get_ref_stmt()->get_select_item(type_ctx.get_cur_row_idx()).expr_; + } + } else if (T_OP_ROW == date_expr->get_expr_type()) { + date_expr = date_expr->get_param_expr(type_ctx.get_cur_row_idx()); + } + if (OB_FAIL(ret)) { + } else if (OB_ISNULL(date_expr) || OB_ISNULL(other_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), K(date_expr), K(other_expr)); + } else if (date_expr->get_result_type().get_type() == ObDateType || + date_expr->get_result_type().get_type() == ObDateTimeType) { + other_expr_type = other_expr->get_result_type().get_type(); + is_date_op_other = true; + } else if (other_expr->get_result_type().get_type() == ObDateType || + other_expr->get_result_type().get_type() == ObDateTimeType) { + const ObRawExpr *tmp_expr = date_expr; + date_expr = other_expr; + other_expr = tmp_expr; + other_expr_type = other_expr->get_result_type().get_type(); + is_date_op_other = true; + } else { + //do nothing + } } - - if (OB_SUCC(ret) && - is_mysql_mode() && - is_date_op_other && + if (OB_SUCC(ret) && is_mysql_mode() && is_date_op_other && (ob_is_accurate_numeric_type(other_expr_type) || ob_is_real_type(other_expr_type)) && - !(other_expr->is_const_expr() && !date_expr->is_const_expr())) { + !(other_expr->is_const_expr() && !date_expr->is_const_expr()) && !other_expr->has_flag(IS_USER_VARIABLE)) { cmp_type.set_calc_type(ObDoubleType); type.set_calc_collation(cmp_type); type.set_calc_type(cmp_type.get_calc_type()); @@ -2225,6 +2252,7 @@ int ObRelationalExprOperator::calc_result_typeN(ObExprResType &type, // 1和'1.00x'会转为int然后比较,'1.00000'和'1.000000'会直接做字符串比较 ObExprResType tmp_res_type; for (int64_t i = 0; OB_SUCC(ret) && i < row_dimension_; ++i) { + type_ctx.set_cur_row_idx(i); if (OB_FAIL(ObRelationalExprOperator::calc_result_type2(tmp_res_type, types[i], types[i + row_dimension_], @@ -2751,6 +2779,7 @@ int ObSubQueryRelationalExpr::calc_result_typeN(ObExprResType &type, if (OB_SUCC(ret)) { for (int64_t i = 0; OB_SUCC(ret) && i < row_dimension_; i++) { ObExprResType tmp_res_type; + type_ctx.set_cur_row_idx(i); OZ(ObRelationalExprOperator::deduce_cmp_type( *this, tmp_res_type, types[i], types[i + row_dimension_], type_ctx)); OZ(type.get_row_calc_cmp_types().push_back(tmp_res_type.get_calc_meta())); 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 70e16b77e2..88efc66029 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 @@ -1408,7 +1408,7 @@ Query Plan Outputs & filters: ------------------------------------- - 0 - output([t3.c1], [t3.c2], [t3.c3]), filter([cast(t3.c1, DATETIME(-1, -1)) = cast('2010-10-10 00:00:00', DATETIME(0, 0))], [cast(t3.c1, DECIMAL(20, 0)) = cast(t3.c2, DECIMAL(-1, -1))]), rowset=256, + 0 - output([t3.c1], [t3.c2], [t3.c3]), filter([cast(t3.c1, DOUBLE(-1, -1)) = cast(cast('2010-10-10 00:00:00', DATETIME(0, 0)), DOUBLE(-1, -1))], [cast(t3.c1, DECIMAL(20, 0)) = cast(t3.c2, DECIMAL(-1, -1))]), rowset=256, access([t3.c1], [t3.c2], [t3.c3]), partitions(p0) select /*+no_rewrite*/* from t3 where c1=c2 and c1=cast('2010-10-10 00:00:00' as datetime); @@ -1427,7 +1427,7 @@ Query Plan Outputs & filters: ------------------------------------- - 0 - output([t3.c1], [t3.c2], [t3.c3]), filter([cast(t3.c1, DATETIME(-1, -1)) = cast('2010-10-10 00:00:00', DATETIME(0, 0))], [cast(t3.c1, DECIMAL(20, 0)) = cast(t3.c2, DECIMAL(-1, -1))]), rowset=256, + 0 - output([t3.c1], [t3.c2], [t3.c3]), filter([cast(t3.c1, DOUBLE(-1, -1)) = cast(cast('2010-10-10 00:00:00', DATETIME(0, 0)), DOUBLE(-1, -1))], [cast(t3.c1, DECIMAL(20, 0)) = cast(t3.c2, DECIMAL(-1, -1))]), rowset=256, access([t3.c1], [t3.c2], [t3.c3]), partitions(p0) select * from t3 where c1=c2 and c1=cast('2010-10-10 00:00:00' as datetime); @@ -1450,7 +1450,7 @@ Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil), table_columns([{t3: ({t3: (t3.__pk_increment, t3.c1, t3.c2, t3.c3)})}]), update([t3.c1=column_conv(BIGINT,PS:(20,0),NULL,1)]) - 1 - output([t3.__pk_increment], [t3.c1], [t3.c2], [t3.c3]), filter([cast(t3.c1, DATETIME(-1, -1)) = cast('2010-10-10 00:00:00', DATETIME(0, 0))], [cast(t3.c1, DECIMAL(20, 0)) = cast(t3.c2, DECIMAL(-1, -1))]), rowset=256, + 1 - output([t3.__pk_increment], [t3.c1], [t3.c2], [t3.c3]), filter([cast(t3.c1, DOUBLE(-1, -1)) = cast(cast('2010-10-10 00:00:00', DATETIME(0, 0)), DOUBLE(-1, -1))], [cast(t3.c1, DECIMAL(20, 0)) = cast(t3.c2, DECIMAL(-1, -1))]), rowset=256, access([t3.__pk_increment], [t3.c1], [t3.c2], [t3.c3]), partitions(p0) update t3 set c1 = 1 where c1=c2 and c1=cast('2010-10-10 00:00:00' as datetime);