fix function convert_tz bug
This commit is contained in:
parent
8629461387
commit
0002ca3b94
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
||||
|
@ -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*/
|
||||
|
@ -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*/
|
||||
|
@ -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 <typename T>
|
||||
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<int64_t>(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<ObTZInfoMap *>(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<ObTZInfoMap *>(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<int64_t>(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
|
@ -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 <typename T>
|
||||
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);
|
||||
|
@ -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<ObDatum*>(&expr.locate_param_datum(ctx, res_idx));
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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 |
|
||||
|
@ -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 |
|
||||
|
Loading…
x
Reference in New Issue
Block a user