From 0002ca3b941f21fa2243d959ecfbaa2603b6939a Mon Sep 17 00:00:00 2001 From: st0 Date: Mon, 28 Feb 2022 20:14:53 +0800 Subject: [PATCH] fix function convert_tz bug --- .../src/lib/timezone/ob_time_convert.cpp | 2 + deps/oblib/src/lib/timezone/ob_time_convert.h | 2 + src/share/object/ob_obj_cast.cpp | 20 +- src/sql/engine/expr/ob_datum_cast.cpp | 17 +- src/sql/engine/expr/ob_expr_convert_tz.cpp | 267 +++++++++--------- src/sql/engine/expr/ob_expr_convert_tz.h | 14 +- src/sql/engine/expr/ob_expr_least.cpp | 48 ++-- src/sql/engine/expr/ob_expr_least.h | 35 ++- .../expr/ob_expr_relational_result_type.map | 124 ++++---- .../test_optimizer_default_stat.result | 16 +- .../optimizer/test_optimizer_select.result | 14 +- 11 files changed, 318 insertions(+), 241 deletions(-) diff --git a/deps/oblib/src/lib/timezone/ob_time_convert.cpp b/deps/oblib/src/lib/timezone/ob_time_convert.cpp index 36cc60e34..5b02e86d2 100644 --- a/deps/oblib/src/lib/timezone/ob_time_convert.cpp +++ b/deps/oblib/src/lib/timezone/ob_time_convert.cpp @@ -5566,6 +5566,7 @@ int ObTimeConverter::apply_datetime_for_time_rule( return ret; } +// for convert utc time to local time, use get_timezone_offset and no gap/overlap time exist. OB_INLINE int ObTimeConverter::add_timezone_offset(const ObTimeZoneInfo* tz_info, int64_t& value) { int ret = OB_SUCCESS; @@ -5580,6 +5581,7 @@ OB_INLINE int ObTimeConverter::add_timezone_offset(const ObTimeZoneInfo* tz_info return ret; } +// for convert local time to utc time, gap/overlap time may exist. OB_INLINE int ObTimeConverter::sub_timezone_offset(const ObTimeZoneInfo* tz_info, bool is_timestamp, const ObString& tz_abbr_str, int64_t& value, const bool is_oracle_mode) { diff --git a/deps/oblib/src/lib/timezone/ob_time_convert.h b/deps/oblib/src/lib/timezone/ob_time_convert.h index 507d6643d..e3ff8df0b 100644 --- a/deps/oblib/src/lib/timezone/ob_time_convert.h +++ b/deps/oblib/src/lib/timezone/ob_time_convert.h @@ -144,6 +144,8 @@ extern const int64_t USECS_PER_MIN; #define DATETIME_MAX_VAL 253402300799999999 #define DATE_MAX_VAL 2932896 #define DATETIME_MIN_VAL -62167132800000000 +#define MYSQL_TIMESTAMP_MAX_VAL 253402214399999999 +#define MYSQL_TIMESTAMP_MIN_VAL -62167046400000000 #define ORACLE_DATETIME_MIN_VAL -62135596800000000 // start from '0001-1-1 00:00:00' #define TIME_MAX_HOUR 838 diff --git a/src/share/object/ob_obj_cast.cpp b/src/share/object/ob_obj_cast.cpp index 56cbcc03d..e2c833bad 100644 --- a/src/share/object/ob_obj_cast.cpp +++ b/src/share/object/ob_obj_cast.cpp @@ -3661,6 +3661,24 @@ static int year_number( return ret; } +static int year_datetime( + const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) +{ + int ret = OB_SUCCESS; + int64_t int_value = 0; + ObObj int64; + if (OB_UNLIKELY(ObYearTC != in.get_type_class() || ObDateTimeTC != ob_obj_type_class(expect_type))) { + ret = OB_ERR_UNEXPECTED; + LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); + } else if (OB_FAIL(ObTimeConverter::year_to_int(in.get_year(), int_value))) { + LOG_WARN("year to int failed", K(ret)); + } else if (FALSE_IT(int64.set_int(int_value))) { + } else if (OB_FAIL(int_datetime(expect_type, params, int64, out, cast_mode))) { + LOG_WARN("int_datetime failed", K(ret)); + } + return ret; +} + static int year_date( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { @@ -6824,7 +6842,7 @@ ObObjCastFunc OB_OBJ_CAST[ObMaxTC][ObMaxTC] = { year_float, /*float*/ year_double, /*double*/ year_number, /*number*/ - cast_not_support, /*datetime*/ + year_datetime, /*datetime*/ year_date, /*date*/ cast_not_support, /*time*/ cast_identity, /*year*/ diff --git a/src/sql/engine/expr/ob_datum_cast.cpp b/src/sql/engine/expr/ob_datum_cast.cpp index 265ce0572..8583e4496 100644 --- a/src/sql/engine/expr/ob_datum_cast.cpp +++ b/src/sql/engine/expr/ob_datum_cast.cpp @@ -3565,6 +3565,21 @@ CAST_FUNC_NAME(year, string) return ret; } +CAST_FUNC_NAME(year, datetime) +{ + EVAL_ARG() + { + uint8_t in_val = child_res->get_uint8(); + int64_t val_int = 0; + if (OB_FAIL(common_year_int(expr, ObIntType, in_val, val_int))) { + LOG_WARN("common_year_int failed", K(ret), K(in_val)); + } else if (OB_FAIL(common_int_datetime(expr, val_int, ctx, res_datum))) { + LOG_WARN("common_int_datetime failed", K(ret), K(val_int)); + } + } + return ret; +} + CAST_FUNC_NAME(year, date) { EVAL_ARG() @@ -8045,7 +8060,7 @@ ObExpr::EvalFunc OB_DATUM_CAST_MYSQL_IMPLICIT[ObMaxTC][ObMaxTC] = { year_float, /*float*/ year_double, /*double*/ year_number, /*number*/ - cast_not_support, /*datetime*/ + year_datetime, /*datetime*/ year_date, /*date*/ cast_not_support, /*time*/ cast_eval_arg, /*year*/ diff --git a/src/sql/engine/expr/ob_expr_convert_tz.cpp b/src/sql/engine/expr/ob_expr_convert_tz.cpp index 2d5879eb8..6cdf585d8 100644 --- a/src/sql/engine/expr/ob_expr_convert_tz.cpp +++ b/src/sql/engine/expr/ob_expr_convert_tz.cpp @@ -26,6 +26,142 @@ ObExprConvertTZ::ObExprConvertTZ(common::ObIAllocator &alloc) : ObFuncExprOperator(alloc, T_FUN_SYS_CONVERT_TZ, "convert_TZ", 3, NOT_ROW_DIMENSION) {} +int ObExprConvertTZ::calc_result_type3(ObExprResType &type, ObExprResType &input1, ObExprResType &input2, + ObExprResType &input3, common::ObExprTypeCtx &type_ctx) const +{ + UNUSED(type_ctx); + int ret = OB_SUCCESS; + const ObSQLSessionInfo *session = NULL; + if (OB_ISNULL(session = type_ctx.get_session())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("session is null", K(ret)); + } else { + int16_t scale1 = MIN(input1.get_scale(), MAX_SCALE_FOR_TEMPORAL); + scale1 = (SCALE_UNKNOWN_YET == scale1) ? MAX_SCALE_FOR_TEMPORAL : scale1; + type.set_scale(scale1); + type.set_datetime(); + input1.set_calc_type(ObDateTimeType); + input2.set_calc_type(ObVarcharType); + input3.set_calc_type(ObVarcharType); + input2.set_calc_collation_type(session->get_nls_collation()); + input3.set_calc_collation_type(session->get_nls_collation()); + } + return ret; +} + +int ObExprConvertTZ::calc_result3(common::ObObj &result, const common::ObObj &input1, const common::ObObj &input2, + const common::ObObj &input3, common::ObExprCtx &expr_ctx) const +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(input1.is_null() || input2.is_null() || input3.is_null())) { + result.set_null(); + } else { + int64_t timestamp_data = input1.get_datetime(); + if (OB_FAIL( + calc_convert_tz(timestamp_data, input2.get_string(), input3.get_string(), expr_ctx.my_session_, result))) { + LOG_WARN("convert time zone failed", K(ret)); + } + } + return ret; +} + +template +int ObExprConvertTZ::calc_convert_tz(int64_t timestamp_data, + const ObString &tz_str_s, // source time zone (input2) + const ObString &tz_str_d, // destination time zone (input3) + ObSQLSessionInfo *session, T &result) +{ + int ret = OB_SUCCESS; + int32_t offset_s = 0; + int32_t offset_d = 0; + if (OB_FAIL(ObExprConvertTZ::parse_string(timestamp_data, tz_str_s, session, false))) { + LOG_WARN("source time zone parse failed", K(ret), K(tz_str_s)); + } else if (OB_FAIL(ObExprConvertTZ::parse_string(timestamp_data, tz_str_d, session, true))) { + LOG_WARN("source time zone parse failed", K(ret), K(tz_str_d)); + } + if (OB_FAIL(ret)) { + ret = OB_SUCCESS; + result.set_null(); + } else { + int64_t res_value = timestamp_data + (static_cast(offset_d - offset_s)) * 1000000; + if (OB_UNLIKELY(res_value < MYSQL_TIMESTAMP_MIN_VAL || res_value > MYSQL_TIMESTAMP_MAX_VAL)) { + result.set_null(); + } else { + result.set_datetime(res_value); + } + } + return ret; +} + +int ObExprConvertTZ::parse_string( + int64_t ×tamp_data, const ObString &tz_str, ObSQLSessionInfo *session, const bool input_utc_time) +{ + int ret = OB_SUCCESS; + int ret_more = 0; + int32_t offset = 0; + if (OB_FAIL(ObTimeConverter::str_to_offset( + tz_str, offset, ret_more, false /* oracle_mode */, true /* need_check_valid */))) { + LOG_WARN("direct str_to_offset failed"); + if (OB_LIKELY(OB_ERR_UNKNOWN_TIME_ZONE == ret)) { + const ObTimeZoneInfo *tz_info = NULL; + ObTimeZoneInfoPos *target_tz_pos = NULL; + if (OB_ISNULL(tz_info = TZ_INFO(session))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("tz info is null", K(ret), K(session)); + } else if (OB_FAIL(find_time_zone_pos(tz_str, *tz_info, target_tz_pos))) { + LOG_WARN("find time zone position failed", K(ret), K(ret_more)); + if (OB_ERR_UNKNOWN_TIME_ZONE == ret && OB_SUCCESS != ret_more) { + ret = ret_more; + } + } else if (OB_FAIL(calc(timestamp_data, *target_tz_pos, input_utc_time))) { + LOG_WARN("calc failed", K(ret), K(timestamp_data)); + } + } else { + LOG_WARN("str to offset failed", K(ret)); + } + } else { + timestamp_data += (input_utc_time ? 1 : -1) * offset * USECS_PER_SEC; + LOG_DEBUG("str to offset succeed", K(tz_str), K(offset)); + } + return ret; +} + +int ObExprConvertTZ::find_time_zone_pos( + const ObString &tz_name, const ObTimeZoneInfo &tz_info, ObTimeZoneInfoPos *&tz_info_pos) +{ + int ret = OB_SUCCESS; + tz_info_pos = NULL; + ObTZInfoMap *tz_info_map = NULL; + if (OB_ISNULL(tz_info_map = const_cast(tz_info.get_tz_info_map()))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("tz_info_map is NULL", K(ret)); + } else if (OB_FAIL(tz_info_map->get_tz_info_by_name(tz_name, tz_info_pos))) { + LOG_WARN("fail to get_tz_info_by_name", K(tz_name), K(ret)); + tz_info_map->id_map_.revert(tz_info_pos); + tz_info_pos = NULL; + } else { + tz_info_pos->set_error_on_overlap_time(tz_info.is_error_on_overlap_time()); + } + return ret; +} + +int ObExprConvertTZ::calc(int64_t ×tamp_data, const ObTimeZoneInfoPos &tz_info_pos, const bool input_utc_time) +{ + int ret = OB_SUCCESS; + const int64_t input_value = timestamp_data; + if (input_utc_time) { + if (OB_FAIL(ObTimeConverter::timestamp_to_datetime(input_value, &tz_info_pos, timestamp_data))) { + LOG_WARN("add timezone offset to utc time failed", K(ret), K(timestamp_data)); + } + } else { + if (OB_FAIL(ObTimeConverter::datetime_to_timestamp(input_value, &tz_info_pos, timestamp_data))) { + LOG_WARN("sub timezone offset fail", K(ret)); + } + } + LOG_DEBUG("convert tz calc", K(timestamp_data), K(input_utc_time)); + return ret; +} + int ObExprConvertTZ::cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &expr) const { int ret = OB_SUCCESS; @@ -53,137 +189,16 @@ int ObExprConvertTZ::eval_convert_tz(const ObExpr &expr, ObEvalCtx &ctx, ObDatum res.set_null(); } else { int64_t timestamp_data = timestamp->get_datetime(); - if (OB_FAIL(calc_convert_tz( - timestamp_data, time_zone_s->get_string(), time_zone_d->get_string(), ctx.exec_ctx_.get_my_session()))) { + if (OB_FAIL(calc_convert_tz(timestamp_data, + time_zone_s->get_string(), + time_zone_d->get_string(), + ctx.exec_ctx_.get_my_session(), + res))) { LOG_WARN("calc convert tz zone failed", K(ret)); - } else { - res.set_datetime(timestamp_data); } } return ret; } -int ObExprConvertTZ::calc_result_type3(ObExprResType &type, ObExprResType &input1, ObExprResType &input2, - ObExprResType &input3, common::ObExprTypeCtx &type_ctx) const -{ - UNUSED(type_ctx); - int ret = OB_SUCCESS; - const ObSQLSessionInfo *session = NULL; - if (OB_ISNULL(session = type_ctx.get_session())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("session is null", K(ret)); - } else { - type.set_datetime(); - input1.set_calc_type(ObDateTimeType); - input2.set_calc_type(ObVarcharType); - input3.set_calc_type(ObVarcharType); - input2.set_calc_collation_type(session->get_nls_collation()); - input3.set_calc_collation_type(session->get_nls_collation()); - } - return ret; -} - -int ObExprConvertTZ::calc_result3(common::ObObj &result, const common::ObObj &input1, const common::ObObj &input2, - const common::ObObj &input3, common::ObExprCtx &expr_ctx) const -{ - int ret = OB_SUCCESS; - if (OB_UNLIKELY(input1.is_null() || input2.is_null() || input3.is_null())) { - result.set_null(); - } else { - int64_t timestamp_data = input1.get_datetime(); - if (OB_FAIL(calc_convert_tz(timestamp_data, input2.get_string(), input3.get_string(), expr_ctx.my_session_))) { - LOG_WARN("convert time zone failed", K(ret)); - } else { - result.set_datetime(timestamp_data); - } - } - return ret; -} - -int ObExprConvertTZ::find_time_zone_pos( - const ObString &tz_name, const ObTimeZoneInfo &tz_info, ObTimeZoneInfoPos *&tz_info_pos) -{ - int ret = OB_SUCCESS; - tz_info_pos = NULL; - ObTZInfoMap *tz_info_map = NULL; - if (OB_ISNULL(tz_info_map = const_cast(tz_info.get_tz_info_map()))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("tz_info_map is NULL", K(ret)); - } else if (OB_FAIL(tz_info_map->get_tz_info_by_name(tz_name, tz_info_pos))) { - LOG_WARN("fail to get_tz_info_by_name", K(tz_name), K(ret)); - tz_info_map->id_map_.revert(tz_info_pos); - tz_info_pos = NULL; - } else { - tz_info_pos->set_error_on_overlap_time(tz_info.is_error_on_overlap_time()); - // need to test overlap time - } - return ret; -} - -int ObExprConvertTZ::parse_string( - int64_t ×tamp_data, const ObString &tz_str, ObSQLSessionInfo *session, int32_t &offset) -{ - int ret = OB_SUCCESS; - int ret_more = 0; - if (OB_FAIL(ObTimeConverter::str_to_offset( - tz_str, offset, ret_more, false /* oracle_mode */, true /* need_check_valid */))) { - LOG_WARN("direct str_to_offset failed"); - if (OB_LIKELY(OB_ERR_UNKNOWN_TIME_ZONE == ret)) { - const ObTimeZoneInfo *tz_info = NULL; - ObTimeZoneInfoPos *target_tz_pos = NULL; - if (OB_ISNULL(tz_info = TZ_INFO(session))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("tz info is null", K(ret), K(session)); - } else if (OB_FAIL(find_time_zone_pos(tz_str, *tz_info, target_tz_pos))) { - LOG_WARN("find time zone position failed", K(ret), K(ret_more)); - if (OB_ERR_UNKNOWN_TIME_ZONE == ret && OB_SUCCESS != ret_more) { - ret = ret_more; - } - } else if (OB_FAIL(calc(timestamp_data, *target_tz_pos, offset))) { - LOG_WARN("calc failed", K(ret), K(timestamp_data)); - } - } else { - LOG_WARN("str to offset failed", K(ret)); - } - } else { - LOG_DEBUG("str to offset succeed", K(tz_str), K(offset)); - } - return ret; -} - -int ObExprConvertTZ::calc_convert_tz(int64_t ×tamp_data, - const ObString &tz_str_s, // source time zone (input2) - const ObString &tz_str_d, // destination time zone (input3) - ObSQLSessionInfo *session) -{ - int ret = OB_SUCCESS; - int32_t offset_s = 0; - int32_t offset_d = 0; - if (OB_FAIL(ObExprConvertTZ::parse_string(timestamp_data, tz_str_s, session, offset_s))) { - LOG_WARN("source time zone parse failed", K(tz_str_s)); - } else if (OB_FAIL(ObExprConvertTZ::parse_string(timestamp_data, tz_str_d, session, offset_d))) { - LOG_WARN("source time zone parse failed", K(tz_str_d)); - } else { - timestamp_data = timestamp_data + (static_cast(offset_d - offset_s)) * 1000000; - } - return ret; -} - -int ObExprConvertTZ::calc(int64_t ×tamp_data, const ObTimeZoneInfoPos &tz_info_pos, int32_t &offset_sec) -{ - int ret = OB_SUCCESS; - offset_sec = 0; - int32_t tz_id = tz_info_pos.get_tz_id(); - int32_t tran_type_id = 0; - ObString tz_abbr_str; - if (OB_FAIL(tz_info_pos.get_timezone_offset( - timestamp_data, offset_sec, tz_abbr_str, tran_type_id))) { // the result value is in offset_sec - LOG_WARN("get timezone sub offset failed", K(ret)); - } else { - LOG_DEBUG("at time zone base calc", K(timestamp_data), K(tz_id), K(tran_type_id)); - } - return ret; -} - } // namespace sql } // namespace oceanbase \ No newline at end of file diff --git a/src/sql/engine/expr/ob_expr_convert_tz.h b/src/sql/engine/expr/ob_expr_convert_tz.h index ae1338bd0..7a86fdd89 100644 --- a/src/sql/engine/expr/ob_expr_convert_tz.h +++ b/src/sql/engine/expr/ob_expr_convert_tz.h @@ -37,12 +37,16 @@ public: static int find_time_zone_pos(const ObString &tz_name, const ObTimeZoneInfo &tz_info, ObTimeZoneInfoPos *&tz_info_pos); - static int calc_convert_tz(int64_t ×tamp_data, const ObString &tz_str_s,//source time zone (input2) + template + static int calc_convert_tz(int64_t timestamp_data, const ObString &tz_str_s,//source time zone (input2) const ObString &tz_str_d,//destination time zone (input3) - ObSQLSessionInfo *session); - static int calc(int64_t ×tamp_data, const ObTimeZoneInfoPos &tz_info_pos, int32_t &offset_sec); - static int parse_string(int64_t ×tamp_data, const ObString &tz_str, ObSQLSessionInfo *session, int32_t &offset); - + ObSQLSessionInfo *session, + T &result); + static int calc(int64_t ×tamp_data, const ObTimeZoneInfoPos &tz_info_pos, + const bool input_utc_time); + static int parse_string(int64_t ×tamp_data, const ObString &tz_str, + ObSQLSessionInfo *session, const bool input_utc_time); + private: // disallow copy DISALLOW_COPY_AND_ASSIGN(ObExprConvertTZ); diff --git a/src/sql/engine/expr/ob_expr_least.cpp b/src/sql/engine/expr/ob_expr_least.cpp index ec7d884ec..55b29d059 100644 --- a/src/sql/engine/expr/ob_expr_least.cpp +++ b/src/sql/engine/expr/ob_expr_least.cpp @@ -139,30 +139,19 @@ int ObExprBaseLeastGreatest::calc_result_typeN_mysql( ObExprOperator::calc_result_flagN(type, types, real_param_num); // don't cast parameter is all parameters are IntTC or UIntTC. bool all_integer = true; - bool big_int_result = false; for (int i = 0; i < real_param_num && all_integer; ++i) { ObObjType type = types[i].get_type(); - if (!ob_is_integer_type(type)) { + if (!ob_is_integer_type(type) && ObNullType != type) { all_integer = false; - } else if (ObIntType == type || ObUInt64Type == type || ObUInt32Type == type) { - big_int_result = true; } } - if (all_integer) { - if (big_int_result) { - type.set_type(ObIntType); - } else { - type.set_type(ObInt32Type); - } - } else { - const ObLengthSemantics default_length_semantics = - (OB_NOT_NULL(type_ctx.get_session()) ? type_ctx.get_session()->get_actual_nls_length_semantics() : LS_BYTE); - if (OB_FAIL(calc_result_meta_for_comparison( - type, types, real_param_num, type_ctx.get_coll_type(), default_length_semantics))) { - LOG_WARN("calc result meta for comparison failed"); - } + const ObLengthSemantics default_length_semantics = + (OB_NOT_NULL(type_ctx.get_session()) ? type_ctx.get_session()->get_actual_nls_length_semantics() : LS_BYTE); + if (OB_FAIL(calc_result_meta_for_comparison( + type, types, real_param_num, type_ctx.get_coll_type(), default_length_semantics))) { + LOG_WARN("calc result meta for comparison failed"); } - if (!all_integer) { + if (!all_integer || !type.is_integer_type()) { // compatible with MySQL. compare type and result type may be different. // resolver makes two copies of parameters. First for comparison and second for output result. for (int64_t i = 0; i < real_param_num; i++) { @@ -215,14 +204,25 @@ int ObExprBaseLeastGreatest::calc(const ObExpr& expr, ObEvalCtx& ctx, ObDatum& e } // compare all params. if (all_integer) { - int64_t minmax_int = expr.locate_param_datum(ctx, cmp_param_start).get_int(); - for (int i = cmp_param_start + 1; i <= cmp_param_end; ++i) { - int64_t cur_int = expr.locate_param_datum(ctx, i).get_int(); - if ((!least && minmax_int < cur_int) || (least && minmax_int > cur_int)) { - minmax_int = cur_int; + if (ob_is_int_tc(expr.datum_meta_.type_)) { + int64_t minmax_value = expr.locate_param_datum(ctx, cmp_param_start).get_int(); + for (int i = cmp_param_start + 1; i <= cmp_param_end; ++i) { + int64_t new_value = expr.locate_param_datum(ctx, i).get_int(); + if (least != (minmax_value < new_value)) { + minmax_value = new_value; + } } + expr_datum.set_int(minmax_value); + } else { + uint64_t minmax_value = expr.locate_param_datum(ctx, cmp_param_start).get_uint(); + for (int i = cmp_param_start + 1; i <= cmp_param_end; ++i) { + uint64_t new_value = expr.locate_param_datum(ctx, i).get_uint(); + if (least != (minmax_value < new_value)) { + minmax_value = new_value; + } + } + expr_datum.set_uint(minmax_value); } - expr_datum.set_int(minmax_int); } else { int res_idx = cmp_param_start; ObDatum* minmax_param = static_cast(&expr.locate_param_datum(ctx, res_idx)); diff --git a/src/sql/engine/expr/ob_expr_least.h b/src/sql/engine/expr/ob_expr_least.h index 801330db9..deaf2f747 100644 --- a/src/sql/engine/expr/ob_expr_least.h +++ b/src/sql/engine/expr/ob_expr_least.h @@ -22,13 +22,34 @@ public: explicit ObExprBaseLeastGreatest( common::ObIAllocator& alloc, ObExprOperatorType type, const char* name, int32_t param_num); virtual ~ObExprBaseLeastGreatest(); - int calc_result_typeN_oracle( - ObExprResType& type, ObExprResType* types_stack, int64_t param_num, common::ObExprTypeCtx& type_ctx) const; - int calc_result_typeN_mysql( - ObExprResType& type, ObExprResType* types_stack, int64_t param_num, common::ObExprTypeCtx& type_ctx) const; - void set_param_type(const ObExprResType& type, ObExprResType* types, int64_t param_num) const; - static int calc(const ObExpr& expr, ObEvalCtx& ctx, ObDatum& expr_datum, bool least); - + int calc_result_typeN_oracle(ObExprResType &type, + ObExprResType *types_stack, + int64_t param_num, + common::ObExprTypeCtx &type_ctx) const; + int calc_result_typeN_mysql(ObExprResType &type, + ObExprResType *types_stack, + int64_t param_num, + common::ObExprTypeCtx &type_ctx) const; + void set_param_type(const ObExprResType &type, + ObExprResType *types, + int64_t param_num) const; + static int calc(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum, bool least); + // left < right: return true, else return false. + static inline bool cmp_integer(const ObDatum &l_datum, const bool l_is_int, + const ObDatum &r_datum, const bool r_is_int) + { + bool ret_bool = true; + if (l_is_int && r_is_int) { + ret_bool = l_datum.get_int() < r_datum.get_int(); + } else if (!l_is_int && !r_is_int) { + ret_bool = l_datum.get_uint() < r_datum.get_uint(); + } else if (l_is_int && !r_is_int) { + ret_bool = l_datum.get_int() < r_datum.get_uint(); + } else { + ret_bool = l_datum.get_uint() < r_datum.get_int(); + } + return ret_bool; + } private: // disallow copy DISALLOW_COPY_AND_ASSIGN(ObExprBaseLeastGreatest); diff --git a/src/sql/engine/expr/ob_expr_relational_result_type.map b/src/sql/engine/expr/ob_expr_relational_result_type.map index 14e10c142..3cc77b4f0 100644 --- a/src/sql/engine/expr/ob_expr_relational_result_type.map +++ b/src/sql/engine/expr/ob_expr_relational_result_type.map @@ -57,13 +57,13 @@ static ObObjType RELATIONAL_RESULT_TYPE[ObMaxType][ObMaxType] = ObInt32Type, /* TinyIntType */ ObInt32Type, /* SmallIntType */ ObInt32Type, /* MediumIntType */ - ObInt32Type, /* Int32Type */ + ObIntType, /* Int32Type */ ObIntType, /* IntType */ ObInt32Type, /* UTinyIntType */ ObInt32Type, /* USmallIntType */ ObInt32Type, /* UMediumIntType */ - ObInt32Type, /* UInt32Type */ - ObIntType, /* UIntType */ + ObIntType, /* UInt32Type */ + ObNumberType, /* UIntType */ ObDoubleType, /* FloatType */ ObDoubleType, /* DoubleType */ ObDoubleType, /* UFloatType */ @@ -109,13 +109,13 @@ static ObObjType RELATIONAL_RESULT_TYPE[ObMaxType][ObMaxType] = ObInt32Type, /* TinyIntType */ ObInt32Type, /* SmallIntType */ ObInt32Type, /* MediumIntType */ - ObInt32Type, /* Int32Type */ + ObIntType, /* Int32Type */ ObIntType, /* IntType */ ObInt32Type, /* UTinyIntType */ ObInt32Type, /* USmallIntType */ ObInt32Type, /* UMediumIntType */ - ObInt32Type, /* UInt32Type */ - ObIntType, /* UIntType */ + ObIntType, /* UInt32Type */ + ObNumberType, /* UIntType */ ObDoubleType, /* FloatType */ ObDoubleType, /* DoubleType */ ObDoubleType, /* UFloatType */ @@ -161,13 +161,13 @@ static ObObjType RELATIONAL_RESULT_TYPE[ObMaxType][ObMaxType] = ObInt32Type, /* TinyIntType */ ObInt32Type, /* SmallIntType */ ObInt32Type, /* MediumIntType */ - ObInt32Type, /* Int32Type */ + ObIntType, /* Int32Type */ ObIntType, /* IntType */ ObInt32Type, /* UTinyIntType */ ObInt32Type, /* USmallIntType */ ObInt32Type, /* UMediumIntType */ - ObInt32Type, /* UInt32Type */ - ObIntType, /* UIntType */ + ObIntType, /* UInt32Type */ + ObNumberType, /* UIntType */ ObDoubleType, /* FloatType */ ObDoubleType, /* DoubleType */ ObDoubleType, /* UFloatType */ @@ -210,16 +210,16 @@ static ObObjType RELATIONAL_RESULT_TYPE[ObMaxType][ObMaxType] = /*Int32Type*/ { ObDoubleType, /* NullType */ - ObInt32Type, /* TinyIntType */ - ObInt32Type, /* SmallIntType */ - ObInt32Type, /* MediumIntType */ - ObInt32Type, /* Int32Type */ + ObIntType, /* TinyIntType */ + ObIntType, /* SmallIntType */ + ObIntType, /* MediumIntType */ + ObIntType, /* Int32Type */ ObIntType, /* IntType */ - ObInt32Type, /* UTinyIntType */ - ObInt32Type, /* USmallIntType */ - ObInt32Type, /* UMediumIntType */ - ObInt32Type, /* UInt32Type */ - ObIntType, /* UIntType */ + ObIntType, /* UTinyIntType */ + ObIntType, /* USmallIntType */ + ObIntType, /* UMediumIntType */ + ObIntType, /* UInt32Type */ + ObNumberType, /* UIntType */ ObDoubleType, /* FloatType */ ObDoubleType, /* DoubleType */ ObDoubleType, /* UFloatType */ @@ -262,16 +262,16 @@ static ObObjType RELATIONAL_RESULT_TYPE[ObMaxType][ObMaxType] = /*IntType*/ { ObDoubleType, /* NullType */ - ObIntType, /* TinyIntType */ - ObIntType, /* SmallIntType */ - ObIntType, /* MediumIntType */ + ObIntType, /* TinyIntType */ + ObIntType, /* SmallIntType */ + ObIntType, /* MediumIntType */ ObIntType, /* Int32Type */ ObIntType, /* IntType */ - ObIntType, /* UTinyIntType */ - ObIntType, /* USmallIntType */ - ObIntType, /* UMediumIntType */ + ObIntType, /* UTinyIntType */ + ObIntType, /* USmallIntType */ + ObIntType, /* UMediumIntType */ ObIntType, /* UInt32Type */ - ObIntType, /* UIntType */ + ObNumberType, /* UIntType */ ObDoubleType, /* FloatType */ ObDoubleType, /* DoubleType */ ObDoubleType, /* UFloatType */ @@ -317,13 +317,13 @@ static ObObjType RELATIONAL_RESULT_TYPE[ObMaxType][ObMaxType] = ObInt32Type, /* TinyIntType */ ObInt32Type, /* SmallIntType */ ObInt32Type, /* MediumIntType */ - ObInt32Type, /* Int32Type */ + ObIntType, /* Int32Type */ ObIntType, /* IntType */ - ObInt32Type, /* UTinyIntType */ - ObInt32Type, /* USmallIntType */ - ObInt32Type, /* UMediumIntType */ - ObInt32Type, /* UInt32Type */ - ObIntType, /* UIntType */ + ObUInt32Type, /* UTinyIntType */ + ObUInt32Type, /* USmallIntType */ + ObUInt32Type, /* UMediumIntType */ + ObUInt64Type, /* UInt32Type */ + ObUInt64Type, /* UIntType */ ObDoubleType, /* FloatType */ ObDoubleType, /* DoubleType */ ObDoubleType, /* UFloatType */ @@ -369,13 +369,13 @@ static ObObjType RELATIONAL_RESULT_TYPE[ObMaxType][ObMaxType] = ObInt32Type, /* TinyIntType */ ObInt32Type, /* SmallIntType */ ObInt32Type, /* MediumIntType */ - ObInt32Type, /* Int32Type */ + ObIntType, /* Int32Type */ ObIntType, /* IntType */ - ObInt32Type, /* UTinyIntType */ - ObInt32Type, /* USmallIntType */ - ObInt32Type, /* UMediumIntType */ - ObInt32Type, /* UInt32Type */ - ObIntType, /* UIntType */ + ObUInt32Type, /* UTinyIntType */ + ObUInt32Type, /* USmallIntType */ + ObUInt32Type, /* UMediumIntType */ + ObUInt64Type, /* UInt32Type */ + ObUInt64Type, /* UIntType */ ObDoubleType, /* FloatType */ ObDoubleType, /* DoubleType */ ObDoubleType, /* UFloatType */ @@ -421,13 +421,13 @@ static ObObjType RELATIONAL_RESULT_TYPE[ObMaxType][ObMaxType] = ObInt32Type, /* TinyIntType */ ObInt32Type, /* SmallIntType */ ObInt32Type, /* MediumIntType */ - ObInt32Type, /* Int32Type */ + ObIntType, /* Int32Type */ ObIntType, /* IntType */ - ObInt32Type, /* UTinyIntType */ - ObInt32Type, /* USmallIntType */ - ObInt32Type, /* UMediumIntType */ - ObInt32Type, /* UInt32Type */ - ObIntType, /* UIntType */ + ObUInt32Type, /* UTinyIntType */ + ObUInt32Type, /* USmallIntType */ + ObUInt32Type, /* UMediumIntType */ + ObUInt64Type, /* UInt32Type */ + ObUInt64Type, /* UIntType */ ObDoubleType, /* FloatType */ ObDoubleType, /* DoubleType */ ObDoubleType, /* UFloatType */ @@ -470,16 +470,16 @@ static ObObjType RELATIONAL_RESULT_TYPE[ObMaxType][ObMaxType] = /*UInt32Type*/ { ObDoubleType, /* NullType */ - ObInt32Type, /* TinyIntType */ - ObInt32Type, /* SmallIntType */ - ObInt32Type, /* MediumIntType */ - ObInt32Type, /* Int32Type */ + ObIntType, /* TinyIntType */ + ObIntType, /* SmallIntType */ + ObIntType, /* MediumIntType */ + ObIntType, /* Int32Type */ ObIntType, /* IntType */ - ObInt32Type, /* UTinyIntType */ - ObInt32Type, /* USmallIntType */ - ObInt32Type, /* UMediumIntType */ - ObInt32Type, /* UInt32Type */ - ObIntType, /* UIntType */ + ObUInt64Type, /* UTinyIntType */ + ObUInt64Type, /* USmallIntType */ + ObUInt64Type, /* UMediumIntType */ + ObUInt64Type, /* UInt32Type */ + ObUInt64Type, /* UIntType */ ObDoubleType, /* FloatType */ ObDoubleType, /* DoubleType */ ObDoubleType, /* UFloatType */ @@ -522,16 +522,16 @@ static ObObjType RELATIONAL_RESULT_TYPE[ObMaxType][ObMaxType] = /*UIntType*/ { ObDoubleType, /* NullType */ - ObIntType, /* TinyIntType */ - ObIntType, /* SmallIntType */ - ObIntType, /* MediumIntType */ - ObIntType, /* Int32Type */ - ObIntType, /* IntType */ - ObIntType, /* UTinyIntType */ - ObIntType, /* USmallIntType */ - ObIntType, /* UMediumIntType */ - ObIntType, /* UInt32Type */ - ObIntType, /* UIntType */ + ObNumberType, /* TinyIntType */ + ObNumberType, /* SmallIntType */ + ObNumberType, /* MediumIntType */ + ObNumberType, /* Int32Type */ + ObNumberType, /* IntType */ + ObUInt64Type, /* UTinyIntType */ + ObUInt64Type, /* USmallIntType */ + ObUInt64Type, /* UMediumIntType */ + ObUInt64Type, /* UInt32Type */ + ObUInt64Type, /* UIntType */ ObDoubleType, /* FloatType */ ObDoubleType, /* DoubleType */ ObDoubleType, /* UFloatType */ diff --git a/unittest/sql/optimizer/test_optimizer_default_stat.result b/unittest/sql/optimizer/test_optimizer_default_stat.result index 8fcf02885..5914fa833 100644 --- a/unittest/sql/optimizer/test_optimizer_default_stat.result +++ b/unittest/sql/optimizer/test_optimizer_default_stat.result @@ -9946,9 +9946,9 @@ SQL: select a1.c2 from t1 left join t2 a1 on (a1.c1= t1.c1) where least(t1.c2, a =============================================================== |ID|OPERATOR |NAME |EST. ROWS|COST | --------------------------------------------------------------- -|0 |PX COORDINATOR | |100000 |1928520| -|1 | EXCHANGE OUT DISTR |:EX10001|100000 |1909588| -|2 | MERGE JOIN | |100000 |1909588| +|0 |PX COORDINATOR | |100000 |1903402| +|1 | EXCHANGE OUT DISTR |:EX10001|100000 |1884470| +|2 | MERGE JOIN | |100000 |1884470| |3 | SORT | |500000 |1458906| |4 | PX PARTITION ITERATOR | |500000 |309262 | |5 | TABLE SCAN |t1 |500000 |309262 | @@ -10032,7 +10032,7 @@ SQL: select a2.c2, t1.c2, a1.c2 from t1 left join t2 a1 on (a1.c1 = t1.c1), t2 ================================================================== |ID|OPERATOR |NAME |EST. ROWS|COST | ------------------------------------------------------------------ -|0 |HASH JOIN | |450000000|269601090| +|0 |HASH JOIN | |450000000|307293132| |1 | PX COORDINATOR | |300000 |213977 | |2 | EXCHANGE OUT DISTR |:EX10000|300000 |185579 | |3 | PX PARTITION ITERATOR | |300000 |185579 | @@ -10090,7 +10090,7 @@ SQL: select f_acc.c2, a1.c2, a2.c2 from t2 left join t2 f1 on (f1.c1 = 1 and t2. =========================================================== |ID|OPERATOR |NAME |EST. ROWS|COST | ----------------------------------------------------------- -|0 |HASH JOIN | |29403 |666559| +|0 |HASH JOIN | |29403 |674223| |1 | NESTED-LOOP JOIN CARTESIAN | |30 |440690| |2 | PX COORDINATOR | |1 |53 | |3 | EXCHANGE OUT DISTR |:EX10000|1 |52 | @@ -10179,7 +10179,7 @@ SQL: select f_acc.c2, a1.c2, a2.c2 from t2 left join t2 f1 on (f1.c1 =1 and f1.c ========================================================== |ID|OPERATOR |NAME |EST. ROWS|COST | ---------------------------------------------------------- -|0 |NESTED-LOOP JOIN CARTESIAN| |2970000 |2823104| +|0 |NESTED-LOOP JOIN CARTESIAN| |2970000 |2839849| |1 | NESTED-LOOP JOIN | |2970 |440056 | |2 | PX COORDINATOR | |1 |53 | |3 | EXCHANGE OUT DISTR |:EX10000|1 |52 | @@ -10188,8 +10188,8 @@ SQL: select f_acc.c2, a1.c2, a2.c2 from t2 left join t2 f1 on (f1.c1 =1 and f1.c |6 | EXCHANGE OUT DISTR |:EX20000|300000 |185579 | |7 | PX PARTITION ITERATOR | |300000 |185579 | |8 | TABLE SCAN |t2 |300000 |185579 | -|9 | MATERIAL | |1000 |188297 | -|10| NESTED-LOOP JOIN | |1000 |187562 | +|9 | MATERIAL | |1000 |205042 | +|10| NESTED-LOOP JOIN | |1000 |204307 | |11| PX COORDINATOR | |1 |53 | |12| EXCHANGE OUT DISTR |:EX30000|1 |52 | |13| TABLE GET |a1 |1 |52 | diff --git a/unittest/sql/optimizer/test_optimizer_select.result b/unittest/sql/optimizer/test_optimizer_select.result index c30c6805b..579701d01 100644 --- a/unittest/sql/optimizer/test_optimizer_select.result +++ b/unittest/sql/optimizer/test_optimizer_select.result @@ -11222,9 +11222,9 @@ SQL: select a1.c2 from t1 left join t2 a1 on (a1.c1= t1.c1) where least(t1.c2, a ============================================================ |ID|OPERATOR |NAME |EST. ROWS|COST| ------------------------------------------------------------ -|0 |PX COORDINATOR | |100 |1556| -|1 | EXCHANGE OUT DISTR |:EX10001|100 |1537| -|2 | MERGE JOIN | |100 |1537| +|0 |PX COORDINATOR | |100 |1531| +|1 | EXCHANGE OUT DISTR |:EX10001|100 |1512| +|2 | MERGE JOIN | |100 |1512| |3 | SORT | |500 |1074| |4 | PX PARTITION ITERATOR | |500 |342 | |5 | TABLE SCAN |t1 |500 |342 | @@ -11308,7 +11308,7 @@ SQL: select a2.c2, t1.c2, a1.c2 from t1 left join t2 a1 on (a1.c1 = t1.c1), t2 ============================================================= |ID|OPERATOR |NAME |EST. ROWS|COST| ------------------------------------------------------------- -|0 |HASH JOIN | |450 |2621| +|0 |HASH JOIN | |450 |2674| |1 | PX COORDINATOR | |300 |227 | |2 | EXCHANGE OUT DISTR |:EX10000|300 |198 | |3 | PX PARTITION ITERATOR | |300 |198 | @@ -11457,7 +11457,7 @@ SQL: select f_acc.c2, a1.c2, a2.c2 from t2 left join t2 f1 on (f1.c1 =1 and f1.c ======================================================= |ID|OPERATOR |NAME |EST. ROWS|COST| ------------------------------------------------------- -|0 |NESTED-LOOP JOIN CARTESIAN| |3 |767 | +|0 |NESTED-LOOP JOIN CARTESIAN| |3 |784 | |1 | NESTED-LOOP JOIN | |3 |505 | |2 | PX COORDINATOR | |1 |53 | |3 | EXCHANGE OUT DISTR |:EX10000|1 |52 | @@ -11466,8 +11466,8 @@ SQL: select f_acc.c2, a1.c2, a2.c2 from t2 left join t2 f1 on (f1.c1 =1 and f1.c |6 | EXCHANGE OUT DISTR |:EX20000|300 |198 | |7 | PX PARTITION ITERATOR | |300 |198 | |8 | TABLE SCAN |t2 |300 |198 | -|9 | MATERIAL | |1 |261 | -|10| NESTED-LOOP JOIN | |1 |260 | +|9 | MATERIAL | |1 |278 | +|10| NESTED-LOOP JOIN | |1 |277 | |11| PX COORDINATOR | |1 |53 | |12| EXCHANGE OUT DISTR |:EX30000|1 |52 | |13| TABLE GET |a1 |1 |52 |