diff --git a/src/sql/CMakeLists.txt b/src/sql/CMakeLists.txt index 23a666f3aff3449a198766b8912004b402ec1c08..47ee3a836ba5096a5777f542d513f6d6bf54d915 100644 --- a/src/sql/CMakeLists.txt +++ b/src/sql/CMakeLists.txt @@ -307,6 +307,7 @@ ob_set_subtarget(ob_sql engine engine/expr/ob_expr_neg.cpp engine/expr/ob_expr_autoinc_nextval.cpp engine/expr/ob_expr_not.cpp + engine/expr/ob_expr_convert_tz.cpp engine/expr/ob_expr_not_between.cpp engine/expr/ob_expr_not_equal.cpp engine/expr/ob_expr_not_exists.cpp diff --git a/src/sql/engine/expr/ob_expr_convert_tz.cpp b/src/sql/engine/expr/ob_expr_convert_tz.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2d5879eb884e383a12887a9a955511ad76fcb18c --- /dev/null +++ b/src/sql/engine/expr/ob_expr_convert_tz.cpp @@ -0,0 +1,189 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#define USING_LOG_PREFIX SQL_ENG +#include "sql/engine/expr/ob_expr_convert_tz.h" +#include "lib/timezone/ob_time_convert.h" +#include "lib/timezone/ob_timezone_info.h" +#include "lib/ob_name_def.h" +#include "sql/session/ob_sql_session_info.h" +#include "sql/engine/ob_exec_context.h" + +namespace oceanbase { +using namespace common; +namespace sql { + +ObExprConvertTZ::ObExprConvertTZ(common::ObIAllocator &alloc) + : ObFuncExprOperator(alloc, T_FUN_SYS_CONVERT_TZ, "convert_TZ", 3, NOT_ROW_DIMENSION) +{} + +int ObExprConvertTZ::cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &expr) const +{ + int ret = OB_SUCCESS; + UNUSED(expr_cg_ctx); + UNUSED(raw_expr); + CK(3 == expr.arg_cnt_); + CK(OB_NOT_NULL(expr.args_) && OB_NOT_NULL(expr.args_[0]) && OB_NOT_NULL(expr.args_[1]) && OB_NOT_NULL(expr.args_[2])); + CK(ObDateTimeType == expr.args_[0]->datum_meta_.type_); + CK(ObDateTimeType == expr.datum_meta_.type_); + CK(ObVarcharType == expr.args_[1]->datum_meta_.type_); + CK(ObVarcharType == expr.args_[2]->datum_meta_.type_); + OX(expr.eval_func_ = ObExprConvertTZ::eval_convert_tz); + return ret; +} + +int ObExprConvertTZ::eval_convert_tz(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res) +{ + int ret = OB_SUCCESS; + ObDatum *timestamp = NULL; + ObDatum *time_zone_s = NULL; + ObDatum *time_zone_d = NULL; + if (OB_FAIL(expr.eval_param_value(ctx, timestamp, time_zone_s, time_zone_d))) { + LOG_WARN("calc param value failed", K(ret)); + } else if (OB_UNLIKELY(timestamp->is_null() || time_zone_s->is_null() || time_zone_d->is_null())) { + 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()))) { + 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 new file mode 100644 index 0000000000000000000000000000000000000000..ae1338bd0d7baceada5a11583d439465f3289e7b --- /dev/null +++ b/src/sql/engine/expr/ob_expr_convert_tz.h @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef OCEANBASE_SQL_OB_EXPR_CONVERT_TZ_H_ +#define OCEANBASE_SQL_OB_EXPR_CONVERT_TZ_H_ +#include "sql/engine/expr/ob_expr_operator.h" +namespace oceanbase +{ +namespace sql +{ +class ObExprConvertTZ : public ObFuncExprOperator{ +public: + explicit ObExprConvertTZ(common::ObIAllocator &alloc); + virtual ~ObExprConvertTZ(){} + virtual int calc_result_type3(ObExprResType &type, + ObExprResType &input1, + ObExprResType &input2, + ObExprResType &input3, + common::ObExprTypeCtx &type_ctx)const; + virtual int calc_result3(common::ObObj &result, + const common::ObObj &input1, + const common::ObObj &input2, + const common::ObObj &input3, + common::ObExprCtx &expr_ctx) const; + virtual int cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, + ObExpr &expr) const override; + static int eval_convert_tz(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res); + 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) + 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); + +private: + // disallow copy + DISALLOW_COPY_AND_ASSIGN(ObExprConvertTZ); + +}; + + +} //sql +} //oceanbasel +#endif //OCEANBASE_SQL_OB_EXPR_CONVERT_TZ_H_ \ No newline at end of file diff --git a/src/sql/engine/expr/ob_expr_eval_functions.cpp b/src/sql/engine/expr/ob_expr_eval_functions.cpp index 39fd9fd6a23be78d521e23b2cae7275eaaf3b274..74f66be4a03dafeb599428bb3a0ba9eae9a40b6b 100644 --- a/src/sql/engine/expr/ob_expr_eval_functions.cpp +++ b/src/sql/engine/expr/ob_expr_eval_functions.cpp @@ -181,6 +181,7 @@ #include "ob_expr_bit_length.h" #include "ob_expr_to_single_byte.h" #include "ob_expr_to_multi_byte.h" +#include "ob_expr_convert_tz.h" namespace oceanbase { using namespace common; @@ -655,7 +656,7 @@ static ObExpr::EvalFunc g_expr_eval_functions[] = { NULL, // ObExprDllUdf::eval_dll_udf, /* 398 */ NULL, // ObExprRawtonhex::calc_rawtonhex_expr, /* 399 */ ObExprPi::eval_pi, /* 400 */ - NULL, //eval_question_mark_func, /* 401 */ + ObExprConvertTZ::eval_convert_tz, /* 401 */ ObExprUtcTime::eval_utc_time, /* 402 */ ObExprUtcDate::eval_utc_date, /* 403 */ ObExprGetFormat::calc_get_format, /* 404 */ @@ -664,7 +665,8 @@ static ObExpr::EvalFunc g_expr_eval_functions[] = { ObExprTimeFormat::calc_time_format, /* 407 */ ObExprMakedate::calc_makedate, /* 408 */ ObExprPeriodAdd::calc_periodadd, /* 409 */ - ObExprExportSet::eval_export_set, /* 401 */ + ObExprExportSet::eval_export_set, /* 410 */ + ObExprConvertTZ::eval_convert_tz /* 411 */ }; REG_SER_FUNC_ARRAY(OB_SFA_SQL_EXPR_EVAL, g_expr_eval_functions, ARRAYSIZEOF(g_expr_eval_functions)); diff --git a/src/sql/engine/expr/ob_expr_operator_factory.cpp b/src/sql/engine/expr/ob_expr_operator_factory.cpp index e4b1ed8632f438ef76089ece6efabdf29865c9d5..fbfa2e665edc8acd595c76d1e78860f09de372ec 100644 --- a/src/sql/engine/expr/ob_expr_operator_factory.cpp +++ b/src/sql/engine/expr/ob_expr_operator_factory.cpp @@ -265,6 +265,7 @@ #include "sql/engine/expr/ob_expr_format.h" #include "sql/engine/expr/ob_expr_quarter.h" #include "sql/engine/expr/ob_expr_bit_length.h" +#include "sql/engine/expr/ob_expr_convert_tz.h" using namespace oceanbase::common; namespace oceanbase { @@ -556,6 +557,7 @@ void ObExprOperatorFactory::register_expr_operators() REG_OP(ObExprCharset); REG_OP(ObExprCollation); REG_OP(ObExprCoercibility); + REG_OP(ObExprConvertTZ); REG_OP(ObExprSetCollation); REG_OP(ObExprReverse); REG_OP(ObExprRight); diff --git a/src/sql/parser/ob_item_type.h b/src/sql/parser/ob_item_type.h index bf68f8b9be3d2fadd46c3b2dc96af0c51631d483..af27fcf2643195ff098f2806cfb7fdb7ee2bb724 100644 --- a/src/sql/parser/ob_item_type.h +++ b/src/sql/parser/ob_item_type.h @@ -580,7 +580,7 @@ typedef enum ObItemType { T_FUN_SYS_UTC_DATE = 1594, T_FUN_SYS_TIME_FORMAT = 1595, ///< @note add new oracle only function type before this line - + T_FUN_SYS_CONVERT_TZ = 1596, T_FUN_SYS_END = 2000, T_MAX_OP = 3000, diff --git a/src/sql/parser/type_name.c b/src/sql/parser/type_name.c index a3c5b5e49bb20aca5992b3bfe1ea4e55bd32954c..218e47302ff33ef876d1ad5c5854506e428271b3 100644 --- a/src/sql/parser/type_name.c +++ b/src/sql/parser/type_name.c @@ -320,6 +320,7 @@ const char* get_type_name(int type) case T_FUN_SYS_TIME_TO_SEC : return "T_FUN_SYS_TIME_TO_SEC"; case T_FUN_SYS_SEC_TO_TIME : return "T_FUN_SYS_SEC_TO_TIME"; case T_FUN_SYS_INTERVAL : return "T_FUN_SYS_INTERVAL"; + case T_FUN_SYS_CONVERT_TZ : return "T_FUN_SYS_CONVERT_TZ"; case T_FUN_UDF : return "T_FUN_UDF"; case T_FUN_SYS_SUBTIME : return "T_FUN_SYS_SUBTIME"; case T_FUN_SYS_SQRT : return "T_FUN_SYS_SQRT"; diff --git a/test/mysql_test/test_suite/expr/r/mysql/expr_convert_tz.result b/test/mysql_test/test_suite/expr/r/mysql/expr_convert_tz.result new file mode 100644 index 0000000000000000000000000000000000000000..db5dfef96596eb60d45ff58800d3be72385e8dc2 --- /dev/null +++ b/test/mysql_test/test_suite/expr/r/mysql/expr_convert_tz.result @@ -0,0 +1,361 @@ +================ expression convert_tz ================ +SELECT CONVERT_TZ('2021-01-01 12:00:00','+00:00','+08:00'); ++-----------------------------------------------------+ +| CONVERT_TZ('2021-01-01 12:00:00','+00:00','+08:00') | ++-----------------------------------------------------+ +| 2021-01-01 20:00:00 | ++-----------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 12:00:00','+01:00','+08:00'); ++-----------------------------------------------------+ +| CONVERT_TZ('2021-01-01 12:00:00','+01:00','+08:00') | ++-----------------------------------------------------+ +| 2021-01-01 19:00:00 | ++-----------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 12:00:00','+01:00','+06:30'); ++-----------------------------------------------------+ +| CONVERT_TZ('2021-01-01 12:00:00','+01:00','+06:30') | ++-----------------------------------------------------+ +| 2021-01-01 17:30:00 | ++-----------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 12:00:00','+01:00','+10:10'); ++-----------------------------------------------------+ +| CONVERT_TZ('2021-01-01 12:00:00','+01:00','+10:10') | ++-----------------------------------------------------+ +| 2021-01-01 21:10:00 | ++-----------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 12:00:00','+01:30','+13:00'); ++-----------------------------------------------------+ +| CONVERT_TZ('2021-01-01 12:00:00','+01:30','+13:00') | ++-----------------------------------------------------+ +| 2021-01-01 23:30:00 | ++-----------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 12:00:00','-11:30','+13:00'); ++-----------------------------------------------------+ +| CONVERT_TZ('2021-01-01 12:00:00','-11:30','+13:00') | ++-----------------------------------------------------+ +| 2021-01-02 12:30:00 | ++-----------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 12:00:00','-12:00','+13:00'); ++-----------------------------------------------------+ +| CONVERT_TZ('2021-01-01 12:00:00','-12:00','+13:00') | ++-----------------------------------------------------+ +| 2021-01-02 13:00:00 | ++-----------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 00:00:00','-12:00','+13:00'); ++-----------------------------------------------------+ +| CONVERT_TZ('2021-01-01 00:00:00','-12:00','+13:00') | ++-----------------------------------------------------+ +| 2021-01-02 01:00:00 | ++-----------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 23:59:59','-12:00','+13:00'); ++-----------------------------------------------------+ +| CONVERT_TZ('2021-01-01 23:59:59','-12:00','+13:00') | ++-----------------------------------------------------+ +| 2021-01-03 00:59:59 | ++-----------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 13:19:38','-10:38','+10:12'); ++-----------------------------------------------------+ +| CONVERT_TZ('2021-01-01 13:19:38','-10:38','+10:12') | ++-----------------------------------------------------+ +| 2021-01-02 10:09:38 | ++-----------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 12:23:35','-09:23','-11:11'); ++-----------------------------------------------------+ +| CONVERT_TZ('2021-01-01 12:23:35','-09:23','-11:11') | ++-----------------------------------------------------+ +| 2021-01-01 10:35:35 | ++-----------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 00:01:00','+10:00','-11:00'); ++-----------------------------------------------------+ +| CONVERT_TZ('2021-01-01 00:01:00','+10:00','-11:00') | ++-----------------------------------------------------+ +| 2020-12-31 03:01:00 | ++-----------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 00:11:00','+00:00','-11:00'); ++-----------------------------------------------------+ +| CONVERT_TZ('2021-01-01 00:11:00','+00:00','-11:00') | ++-----------------------------------------------------+ +| 2020-12-31 13:11:00 | ++-----------------------------------------------------+ + +SELECT CONVERT_TZ('2021-03-01 00:11:00','+00:00','-11:00'); ++-----------------------------------------------------+ +| CONVERT_TZ('2021-03-01 00:11:00','+00:00','-11:00') | ++-----------------------------------------------------+ +| 2021-02-28 13:11:00 | ++-----------------------------------------------------+ + +SELECT CONVERT_TZ('2021-06-01 00:11:00','+00:00','-11:00'); ++-----------------------------------------------------+ +| CONVERT_TZ('2021-06-01 00:11:00','+00:00','-11:00') | ++-----------------------------------------------------+ +| 2021-05-31 13:11:00 | ++-----------------------------------------------------+ + +SELECT CONVERT_TZ('2020-03-01 00:11:00','+00:00','-11:00'); ++-----------------------------------------------------+ +| CONVERT_TZ('2020-03-01 00:11:00','+00:00','-11:00') | ++-----------------------------------------------------+ +| 2020-02-29 13:11:00 | ++-----------------------------------------------------+ + +SELECT CONVERT_TZ('2020-02-28 23:11:00','-00:00','+11:00'); ++-----------------------------------------------------+ +| CONVERT_TZ('2020-02-28 23:11:00','-00:00','+11:00') | ++-----------------------------------------------------+ +| 2020-02-29 10:11:00 | ++-----------------------------------------------------+ + +SELECT CONVERT_TZ('2020-12-31 23:11:00','-05:00','+11:00'); ++-----------------------------------------------------+ +| CONVERT_TZ('2020-12-31 23:11:00','-05:00','+11:00') | ++-----------------------------------------------------+ +| 2021-01-01 15:11:00 | ++-----------------------------------------------------+ + + + +SELECT CONVERT_TZ('2020-12-31 23:11:00',null,'+11:00'); ++-------------------------------------------------+ +| CONVERT_TZ('2020-12-31 23:11:00',null,'+11:00') | ++-------------------------------------------------+ +| NULL | ++-------------------------------------------------+ + +SELECT CONVERT_TZ('2020-12-31 23:11:00','+11:00', null); ++--------------------------------------------------+ +| CONVERT_TZ('2020-12-31 23:11:00','+11:00', null) | ++--------------------------------------------------+ +| NULL | ++--------------------------------------------------+ + +SELECT CONVERT_TZ(null,'-13:00','+11:00'); ++------------------------------------+ +| CONVERT_TZ(null,'-13:00','+11:00') | ++------------------------------------+ +| NULL | ++------------------------------------+ + +SELECT CONVERT_TZ(null, null,'+11:00'); ++---------------------------------+ +| CONVERT_TZ(null, null,'+11:00') | ++---------------------------------+ +| NULL | ++---------------------------------+ + +SELECT CONVERT_TZ(null, null, null); ++------------------------------+ +| CONVERT_TZ(null, null, null) | ++------------------------------+ +| NULL | ++------------------------------+ + +SELECT CONVERT_TZ('2020-12-31 23:11:00','America/Merida','Asia/Tokyo'); ++-----------------------------------------------------------------+ +| CONVERT_TZ('2020-12-31 23:11:00','America/Merida','Asia/Tokyo') | ++-----------------------------------------------------------------+ +| 2021-01-01 14:11:00 | ++-----------------------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 00:11:00','America/Merida','Australia/Darwin'); ++-----------------------------------------------------------------------+ +| CONVERT_TZ('2021-01-01 00:11:00','America/Merida','Australia/Darwin') | ++-----------------------------------------------------------------------+ +| 2021-01-01 15:41:00 | ++-----------------------------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 00:11:00','America/Merida','Europe/Amsterdam'); ++-----------------------------------------------------------------------+ +| CONVERT_TZ('2021-01-01 00:11:00','America/Merida','Europe/Amsterdam') | ++-----------------------------------------------------------------------+ +| 2021-01-01 07:11:00 | ++-----------------------------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 07:11:00','Europe/Amsterdam','America/Merida'); ++-----------------------------------------------------------------------+ +| CONVERT_TZ('2021-01-01 07:11:00','Europe/Amsterdam','America/Merida') | ++-----------------------------------------------------------------------+ +| 2021-01-01 00:11:00 | ++-----------------------------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 07:11:00','Europe/Amsterdam','Libya'); ++--------------------------------------------------------------+ +| CONVERT_TZ('2021-01-01 07:11:00','Europe/Amsterdam','Libya') | ++--------------------------------------------------------------+ +| 2021-01-01 08:11:00 | ++--------------------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 07:11:00','MET','Libya'); ++-------------------------------------------------+ +| CONVERT_TZ('2021-01-01 07:11:00','MET','Libya') | ++-------------------------------------------------+ +| 2021-01-01 08:11:00 | ++-------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 07:11:00','MET','MST'); ++-----------------------------------------------+ +| CONVERT_TZ('2021-01-01 07:11:00','MET','MST') | ++-----------------------------------------------+ +| 2020-12-31 23:11:00 | ++-----------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 07:11:00','PRC','MST'); ++-----------------------------------------------+ +| CONVERT_TZ('2021-01-01 07:11:00','PRC','MST') | ++-----------------------------------------------+ +| 2020-12-31 16:11:00 | ++-----------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 07:11:00','PRC','ROC'); ++-----------------------------------------------+ +| CONVERT_TZ('2021-01-01 07:11:00','PRC','ROC') | ++-----------------------------------------------+ +| 2021-01-01 07:11:00 | ++-----------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 07:11:00','UCT','ROC'); ++-----------------------------------------------+ +| CONVERT_TZ('2021-01-01 07:11:00','UCT','ROC') | ++-----------------------------------------------+ +| 2021-01-01 15:11:00 | ++-----------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 07:11:00','Universal','ROC'); ++-----------------------------------------------------+ +| CONVERT_TZ('2021-01-01 07:11:00','Universal','ROC') | ++-----------------------------------------------------+ +| 2021-01-01 15:11:00 | ++-----------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 07:11:00','Pacific/Marquesas','ROC'); ++-------------------------------------------------------------+ +| CONVERT_TZ('2021-01-01 07:11:00','Pacific/Marquesas','ROC') | ++-------------------------------------------------------------+ +| 2021-01-02 00:41:00 | ++-------------------------------------------------------------+ + +SELECT CONVERT_TZ('2021-02-28 17:11:00','GMT+0','ROC'); ++-------------------------------------------------+ +| CONVERT_TZ('2021-02-28 17:11:00','GMT+0','ROC') | ++-------------------------------------------------+ +| 2021-03-01 01:11:00 | ++-------------------------------------------------+ + +SELECT CONVERT_TZ('2021-02-28 17:11:00','GMT+0','Singapore'); ++-------------------------------------------------------+ +| CONVERT_TZ('2021-02-28 17:11:00','GMT+0','Singapore') | ++-------------------------------------------------------+ +| 2021-03-01 01:11:00 | ++-------------------------------------------------------+ + +SELECT CONVERT_TZ('2021-02-28 17:11:00','US/Michigan','ROC'); ++-------------------------------------------------------+ +| CONVERT_TZ('2021-02-28 17:11:00','US/Michigan','ROC') | ++-------------------------------------------------------+ +| 2021-03-01 06:11:00 | ++-------------------------------------------------------+ + + + +SELECT CONVERT_TZ('2021-02-28 17:11:00', null,'ROC'); ++-----------------------------------------------+ +| CONVERT_TZ('2021-02-28 17:11:00', null,'ROC') | ++-----------------------------------------------+ +| NULL | ++-----------------------------------------------+ + +SELECT CONVERT_TZ('2021-02-28 17:11:00','US/Michigan', null); ++-------------------------------------------------------+ +| CONVERT_TZ('2021-02-28 17:11:00','US/Michigan', null) | ++-------------------------------------------------------+ +| NULL | ++-------------------------------------------------------+ + +SELECT CONVERT_TZ('2021-02-28 17:11:00', null, null); ++-----------------------------------------------+ +| CONVERT_TZ('2021-02-28 17:11:00', null, null) | ++-----------------------------------------------+ +| NULL | ++-----------------------------------------------+ + +SELECT CONVERT_TZ('2021-02-28 17:11:00', '+00:00','ROC'); ++---------------------------------------------------+ +| CONVERT_TZ('2021-02-28 17:11:00', '+00:00','ROC') | ++---------------------------------------------------+ +| 2021-03-01 01:11:00 | ++---------------------------------------------------+ + +SELECT CONVERT_TZ('2021-02-28 17:11:00', '+00:00','US/Michigan'); ++-----------------------------------------------------------+ +| CONVERT_TZ('2021-02-28 17:11:00', '+00:00','US/Michigan') | ++-----------------------------------------------------------+ +| 2021-02-28 12:11:00 | ++-----------------------------------------------------------+ + +SELECT CONVERT_TZ('2021-02-28 17:11:00', 'ROC','+00:00'); ++---------------------------------------------------+ +| CONVERT_TZ('2021-02-28 17:11:00', 'ROC','+00:00') | ++---------------------------------------------------+ +| 2021-02-28 09:11:00 | ++---------------------------------------------------+ + +SELECT CONVERT_TZ('2021-02-28 17:11:00','US/Michigan', '+00:00'); ++-----------------------------------------------------------+ +| CONVERT_TZ('2021-02-28 17:11:00','US/Michigan', '+00:00') | ++-----------------------------------------------------------+ +| 2021-02-28 22:11:00 | ++-----------------------------------------------------------+ + +SELECT CONVERT_TZ('2021-02-28 17:11:00', 'ROC','+12:58'); ++---------------------------------------------------+ +| CONVERT_TZ('2021-02-28 17:11:00', 'ROC','+12:58') | ++---------------------------------------------------+ +| 2021-02-28 22:09:00 | ++---------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 07:11:00', '-12:58','UCT'); ++---------------------------------------------------+ +| CONVERT_TZ('2021-01-01 07:11:00', '-12:58','UCT') | ++---------------------------------------------------+ +| 2021-01-01 20:09:00 | ++---------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 07:11:00', '-12:58','US/Michigan'); ++-----------------------------------------------------------+ +| CONVERT_TZ('2021-01-01 07:11:00', '-12:58','US/Michigan') | ++-----------------------------------------------------------+ +| 2021-01-01 15:09:00 | ++-----------------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 07:11:00', '+05:12','MET'); ++---------------------------------------------------+ +| CONVERT_TZ('2021-01-01 07:11:00', '+05:12','MET') | ++---------------------------------------------------+ +| 2021-01-01 02:59:00 | ++---------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 07:11:00', '+03:32','PRC'); ++---------------------------------------------------+ +| CONVERT_TZ('2021-01-01 07:11:00', '+03:32','PRC') | ++---------------------------------------------------+ +| 2021-01-01 11:39:00 | ++---------------------------------------------------+ + +SELECT CONVERT_TZ('2021-01-01 07:11:00', '+11:32','PRC'); ++---------------------------------------------------+ +| CONVERT_TZ('2021-01-01 07:11:00', '+11:32','PRC') | ++---------------------------------------------------+ +| 2021-01-01 03:39:00 | ++---------------------------------------------------+ \ No newline at end of file diff --git a/test/mysql_test/test_suite/expr/t/expr_convert_tz.test b/test/mysql_test/test_suite/expr/t/expr_convert_tz.test new file mode 100644 index 0000000000000000000000000000000000000000..97b6190d7d50ed60ed260dda9578a7809620d2d1 --- /dev/null +++ b/test/mysql_test/test_suite/expr/t/expr_convert_tz.test @@ -0,0 +1,66 @@ +--disable_query_log +set @@session.explicit_defaults_for_timestamp=off; +--enable_query_log +--enable_abort_on_error +--echo ================ expression convert_tz ================ + +# 直接时刻类型 +SELECT CONVERT_TZ('2021-01-01 12:00:00','+00:00','+08:00'); +SELECT CONVERT_TZ('2021-01-01 12:00:00','+01:00','+08:00'); +SELECT CONVERT_TZ('2021-01-01 12:00:00','+01:00','+06:30'); +SELECT CONVERT_TZ('2021-01-01 12:00:00','+01:00','+10:10'); +SELECT CONVERT_TZ('2021-01-01 12:00:00','+01:30','+13:00'); +SELECT CONVERT_TZ('2021-01-01 12:00:00','-11:30','+13:00'); +SELECT CONVERT_TZ('2021-01-01 12:00:00','-12:00','+13:00'); +SELECT CONVERT_TZ('2021-01-01 00:00:00','-12:00','+13:00'); +SELECT CONVERT_TZ('2021-01-01 23:59:59','-12:00','+13:00'); +SELECT CONVERT_TZ('2021-01-01 13:19:38','-10:38','+10:12'); +SELECT CONVERT_TZ('2021-01-01 12:23:35','-09:23','-11:11'); +SELECT CONVERT_TZ('2021-01-01 00:01:00','+10:00','-11:00'); +SELECT CONVERT_TZ('2021-01-01 00:11:00','+00:00','-11:00'); +SELECT CONVERT_TZ('2021-03-01 00:11:00','+00:00','-11:00'); +SELECT CONVERT_TZ('2021-06-01 00:11:00','+00:00','-11:00'); +SELECT CONVERT_TZ('2020-03-01 00:11:00','+00:00','-11:00'); +SELECT CONVERT_TZ('2020-02-28 23:11:00','-00:00','+11:00'); +SELECT CONVERT_TZ('2020-12-31 23:11:00','-05:00','+11:00'); + +#直接时刻类型异常 +SELECT CONVERT_TZ('2020-12-31 23:11:00',null,'+11:00'); +SELECT CONVERT_TZ('2020-12-31 23:11:00','+11:00', null); +SELECT CONVERT_TZ(null,'-13:00','+11:00'); +SELECT CONVERT_TZ(null, null,'+11:00'); +SELECT CONVERT_TZ(null, null, null); + +#时区类型 +SELECT CONVERT_TZ('2020-12-31 23:11:00','America/Merida','Asia/Tokyo'); +SELECT CONVERT_TZ('2021-01-01 00:11:00','America/Merida','Australia/Darwin'); +SELECT CONVERT_TZ('2021-01-01 00:11:00','America/Merida','Europe/Amsterdam'); +SELECT CONVERT_TZ('2021-01-01 07:11:00','Europe/Amsterdam','America/Merida'); +SELECT CONVERT_TZ('2021-01-01 07:11:00','MET','Libya'); +SELECT CONVERT_TZ('2021-01-01 07:11:00','MET','MST'); +SELECT CONVERT_TZ('2021-01-01 07:11:00','PRC','MST'); +SELECT CONVERT_TZ('2021-01-01 07:11:00','PRC','ROC'); +SELECT CONVERT_TZ('2021-01-01 07:11:00','UCT','ROC'); +SELECT CONVERT_TZ('2021-01-01 07:11:00','Universal','ROC'); +SELECT CONVERT_TZ('2021-01-01 07:11:00','Pacific/Marquesas','ROC'); +SELECT CONVERT_TZ('2021-02-28 17:11:00','GMT+0','ROC'); +SELECT CONVERT_TZ('2021-02-28 17:11:00','GMT+0','Singapore'); +SELECT CONVERT_TZ('2021-02-28 17:11:00','US/Michigan','ROC'); + +#时区类型异常 +SELECT CONVERT_TZ('2021-02-28 17:11:00', null,'ROC'); +SELECT CONVERT_TZ('2021-02-28 17:11:00','US/Michigan', null); +SELECT CONVERT_TZ('2021-02-28 17:11:00', null, null); + +#混合类型 +SELECT CONVERT_TZ('2021-02-28 17:11:00', '+00:00','ROC'); +SELECT CONVERT_TZ('2021-02-28 17:11:00', '+00:00','US/Michigan'); +SELECT CONVERT_TZ('2021-02-28 17:11:00', 'ROC','+00:00'); +SELECT CONVERT_TZ('2021-02-28 17:11:00', 'US/Michigan', '+00:00'); +SELECT CONVERT_TZ('2021-02-28 17:11:00', 'ROC','+12:58'); +SELECT CONVERT_TZ('2021-01-01 07:11:00', 'UCT','-12:58'); +SELECT CONVERT_TZ('2021-01-01 07:11:00', '-12:58','UCT'); +SELECT CONVERT_TZ('2021-01-01 07:11:00', '-12:58','US/Michigan'); +SELECT CONVERT_TZ('2021-01-01 07:11:00', '+05:12','MET'); +SELECT CONVERT_TZ('2021-01-01 07:11:00', '+03:32','PRC'); +SELECT CONVERT_TZ('2021-01-01 07:11:00', '+11:32','PRC'); \ No newline at end of file