From 75e16aa7f0ebfa19e3fa151a32bf2c4c92c232dd Mon Sep 17 00:00:00 2001 From: wangfeihuo Date: Sat, 21 Dec 2024 16:01:44 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=83=A8=E5=88=86=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E8=BD=AC=E6=8D=A2=E4=B8=8Emysql=E4=B8=8D=E4=B8=80?= =?UTF-8?q?=E8=87=B4=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../b_compatibility_time_funcs2.out | 28 +++++-- .../timediff_illegal_participation.out | 4 +- contrib/dolphin/include/plugin_utils/date.h | 7 +- contrib/dolphin/plugin_utils/adt/date.cpp | 13 +-- .../dolphin/plugin_utils/adt/timestamp.cpp | 82 +++++++++++++++---- .../b_compatibility_time_funcs2.sql | 7 ++ 6 files changed, 108 insertions(+), 33 deletions(-) diff --git a/contrib/dolphin/expected/builtin_funcs/b_compatibility_time_funcs2.out b/contrib/dolphin/expected/builtin_funcs/b_compatibility_time_funcs2.out index 2bdbfe524..c119fad1e 100644 --- a/contrib/dolphin/expected/builtin_funcs/b_compatibility_time_funcs2.out +++ b/contrib/dolphin/expected/builtin_funcs/b_compatibility_time_funcs2.out @@ -857,14 +857,10 @@ insert into func_test2(functionName, result) values('TIMESTAMPADD(SECOND,0.001,' insert into func_test2(functionName, result) values('TIMESTAMPADD(SECOND,-0.001,''2022-07-27 00:00:00'')', TIMESTAMPADD(SECOND,-0.001,'2022-07-27 00:00:00')); -- 越界预判 insert into func_test2(functionName, result) values('TIMESTAMPADD(year,1,time''23:59:59'')', TIMESTAMPADD(year,1,time'23:59:59')); -ERROR: time field value out of range -CONTEXT: referenced column: result insert into func_test2(functionName, result) values('TIMESTAMPADD(qtr,1,time''23:59:59'')', TIMESTAMPADD(qtr,1,time'23:59:59')); -ERROR: time field value out of range -CONTEXT: referenced column: result insert into func_test2(functionName, result) values('TIMESTAMPADD(month,1,time''23:59:59'')', TIMESTAMPADD(month,1,time'23:59:59')); -ERROR: time field value out of range -CONTEXT: referenced column: result +-- timetz +insert into func_test2(functionName, result) values('timestampadd(day, 1, timetz''1:1:0+05'')', timestampadd(day, 1, timetz'1:1:0+05')); -- TIME、TIMESTAMP建表语法修改测试 create table t1(col timestamp('1')); ERROR: Un-support feature @@ -1069,7 +1065,8 @@ select * from func_test2 order by 1, 2; TIMESTAMPADD(DAY,-1.6,'2022-07-27') | 2022-07-25 TIMESTAMPADD(DAY,1.6,'2022-07-27') | 2022-07-29 TIMESTAMPADD(DAY,1,cast('2022-04-05' as datetime)) | 2022-04-06 00:00:00 - TIMESTAMPADD(DAY,1,time'14:30:00') | 38:30:00 +--?.* +--?.* TIMESTAMPADD(DAY,timestamptz'2000-1-1 1:1:1+05','2022-07-01') | 2027-12-21 TIMESTAMPADD(HOUR,0.3,'2022-07-27') | 2022-07-27 00:00:00 TIMESTAMPADD(HOUR,-1.1,'2022-07-27') | 2022-07-26 23:00:00 @@ -1115,9 +1112,11 @@ select * from func_test2 order by 1, 2; TIMESTAMPADD(MONTH,1,'2022-12-31') | 2023-01-31 TIMESTAMPADD(MONTH,-1.6,'2022-07-27') | 2022-05-27 TIMESTAMPADD(MONTH,1.6,'2022-07-27') | 2022-09-27 +--?.* TIMESTAMPADD(MONTH,2,'2022-07-31') | 2022-09-30 TIMESTAMPADD(MONTH,3,'2019-12-31') | 2020-03-31 TIMESTAMPADD(qtr,1,'0000-01-01 00:00:00') | 0000-04-01 00:00:00 +--?.* TIMESTAMPADD(SECOND,0.000000003,'2022-07-27') | 2022-07-27 00:00:00 TIMESTAMPADD(SECOND,-0.001,'2022-07-27 00:00:00') | 2022-07-26 23:59:59.999 TIMESTAMPADD(SECOND,0.001,'2022-07-27 08:30:59.999') | 2022-07-27 08:31:00 @@ -1158,6 +1157,7 @@ select * from func_test2 order by 1, 2; TIMESTAMPADD(YEAR,1,'2022-07-27 08:30:00') | 2023-07-27 08:30:00 TIMESTAMPADD(YEAR,-1.6,'2022-07-27') | 2020-07-27 TIMESTAMPADD(YEAR,1.6,'2022-07-27') | 2024-07-27 +--?.* TIMESTAMP(cast('2007-12-10 23:59:59' as datetime)) | 2007-12-10 23:59:59 TIMESTAMP(cast('2007-12-10 23:59:59' as datetime), cast('2007-12-10 22:59:59' as datetime)) | 2007-12-11 22:59:58 TIMESTAMP(date'2003-01-01') | 2003-01-01 00:00:00 @@ -1248,6 +1248,15 @@ CONTEXT: referenced column: result insert into func_test2(functionName, result) values('subtime(-8385959, ''1:00:00'')', subtime(-8385959,'1:00:00')); WARNING: time field value out of range CONTEXT: referenced column: result +insert into func_test2(functionName, result) values('subtime(B''0'',B''1'')', subtime(B'0',B'1')); +WARNING: unsupported input data type: bit +CONTEXT: referenced column: result +insert into func_test2(functionName, result) values('TIMEDIFF(B''101'', B''101'')', TIMEDIFF(B'101', B'101')); +WARNING: unsupported input data type: bit +CONTEXT: referenced column: result +insert into func_test2(functionName, result) values('TIME(B''1'')', TIME(B'1')); +WARNING: unsupported input data type: bit +CONTEXT: referenced column: result select * from func_test2 order by functionName; functionName | result --------------------------------------+------------ @@ -1258,7 +1267,10 @@ select * from func_test2 order by functionName; subtime('-838:59:59', '25:00') | -838:59:59 subtime('838:59:59', '-25:00') | 838:59:59 subtime('839:59:59', '837:59:59') | 01:00:00 -(7 rows) + subtime(B'0',B'1') | + TIME(B'1') | + TIMEDIFF(B'101', B'101') | +(10 rows) set dolphin.b_compatibility_mode=on; set b_format_behavior_compat_options='enable_set_variables,enable_multi_charset'; diff --git a/contrib/dolphin/expected/timediff_illegal_participation.out b/contrib/dolphin/expected/timediff_illegal_participation.out index f3396fdd4..1470cde22 100644 --- a/contrib/dolphin/expected/timediff_illegal_participation.out +++ b/contrib/dolphin/expected/timediff_illegal_participation.out @@ -234,9 +234,11 @@ CONTEXT: referenced column: timediff -- test normal select timediff(B'101', B'10101'); +WARNING: unsupported input data type: bit +CONTEXT: referenced column: timediff timediff ---------- - 00:00:00 + (1 row) select timediff(time'00:00:00', 'asdfg'); diff --git a/contrib/dolphin/include/plugin_utils/date.h b/contrib/dolphin/include/plugin_utils/date.h index 7b477dcc6..44df07f96 100644 --- a/contrib/dolphin/include/plugin_utils/date.h +++ b/contrib/dolphin/include/plugin_utils/date.h @@ -88,13 +88,10 @@ extern bool is_date_format(const char *str); extern Datum input_date_in(char* str, bool can_ignore); extern bool date_in_no_ereport(const char *str, DateADT *date); extern bool date_sub_interval(DateADT date, Interval *span, DateADT *result, bool is_add_func = false); -#ifdef DOLPHIN -extern void convert_to_time(Datum value, Oid valuetypid, TimeADT *time, bool can_ignore = false); -#else -extern void convert_to_time(Datum value, Oid valuetypid, TimeADT *time); -#endif #ifdef DOLPHIN +extern void convert_to_time(Datum value, Oid valuetypid, TimeADT *time, bool can_ignore = false, + bool* result_isnull = NULL); extern int tm2time(struct pg_tm* tm, fsec_t fsec, TimeADT* result); extern int time2tm(TimeADT time, struct pg_tm* tm, fsec_t* fsec); extern int timetz2tm(TimeTzADT* time, struct pg_tm* tm, fsec_t* fsec, int* tzp); diff --git a/contrib/dolphin/plugin_utils/adt/date.cpp b/contrib/dolphin/plugin_utils/adt/date.cpp index 9ee63f69d..e3c7a48f0 100644 --- a/contrib/dolphin/plugin_utils/adt/date.cpp +++ b/contrib/dolphin/plugin_utils/adt/date.cpp @@ -5092,7 +5092,7 @@ bool date_sub_interval(DateADT date, Interval *span, DateADT *result, bool is_ad /** * Convert non-NULL values of the indicated types to the TimeADT value */ -void convert_to_time(Datum value, Oid valuetypid, TimeADT *time, bool can_ignore) +void convert_to_time(Datum value, Oid valuetypid, TimeADT *time, bool can_ignore, bool* result_isnull) { switch (valuetypid) { case UNKNOWNOID: @@ -5182,11 +5182,14 @@ void convert_to_time(Datum value, Oid valuetypid, TimeADT *time, bool can_ignore break; } case BITOID: { - if (SQL_MODE_STRICT()) { - ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("unsupported input data type: %s", format_type_be(valuetypid)))); - } + int errlevel = SQL_MODE_STRICT() ? ERROR : WARNING; + ereport(errlevel, (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("unsupported input data type: %s", format_type_be(valuetypid)))); *time = 0; + if (result_isnull != NULL) { + *result_isnull = true; + return; + } break; } default: { diff --git a/contrib/dolphin/plugin_utils/adt/timestamp.cpp b/contrib/dolphin/plugin_utils/adt/timestamp.cpp index 96bf31c88..2dfb2501b 100644 --- a/contrib/dolphin/plugin_utils/adt/timestamp.cpp +++ b/contrib/dolphin/plugin_utils/adt/timestamp.cpp @@ -7537,6 +7537,25 @@ void convert_to_datetime(Datum value, Oid valuetypid, Timestamp *datetime) *datetime = DatumGetTimestamp(DirectFunctionCall1(date_timestamp, value)); break; } + case TIMETZOID: { + // The conversion rule from Time to Timestamp is: + // Combining the current date withe the input time + pg_tm tt, *tm = &tt; + int tz = 0; + TimestampTz temp; + TimeTzADT* time = DatumGetTimeTzADTP(value); + GetCurrentDateTime(tm); + tm->tm_hour = tm->tm_min = tm->tm_sec = 0; // Keep date only + tm2timestamp(tm, 0, &tz, &temp); + +#ifdef HAVE_INT64_TIMESTAMP + *datetime = time->time + (time->zone * 1000000.0) + temp; +#else + *datetime = time->time + time->zone + temp; +#endif + break; + } + case TIMEOID: { // The conversion rule from Time to Timestamp is: // Combining the current date withe the input time @@ -7774,7 +7793,7 @@ Oid convert_to_datetime_time(Datum value, Oid valuetypid, Timestamp *datetime, T case INT4OID: case BOOLOID: case BITOID: { - convert_to_time(value, valuetypid, time, can_ignore); + convert_to_time(value, valuetypid, time, can_ignore, result_isnull); check_b_format_time_range_with_ereport(*time); return TIMEOID; } @@ -7887,10 +7906,15 @@ Datum subtime(PG_FUNCTION_ARGS) TimeADT time1, time2, res_time; Timestamp datetime1, datetime2, res_datetime; Oid val_type1, val_type2; + bool result_isnull = false; val_type1 = get_fn_expr_argtype(fcinfo->flinfo, 0); val_type2 = get_fn_expr_argtype(fcinfo->flinfo, 1); - val_type1 = convert_to_datetime_time(PG_GETARG_DATUM(0), val_type1, &datetime1, &time1, true); + val_type1 = convert_to_datetime_time(PG_GETARG_DATUM(0), val_type1, &datetime1, &time1, true, &result_isnull); + + if (result_isnull == true) { + PG_RETURN_NULL(); + } switch (val_type2) { case TIMESTAMPOID: @@ -7902,8 +7926,8 @@ Datum subtime(PG_FUNCTION_ARGS) val_type2 = TIMEOID; break; default: - val_type2 = convert_to_datetime_time(PG_GETARG_DATUM(1), val_type2, &datetime2, &time2, true); - if (val_type2 == TIMESTAMPOID) { + val_type2 = convert_to_datetime_time(PG_GETARG_DATUM(1), val_type2, &datetime2, &time2, true, &result_isnull); + if (val_type2 == TIMESTAMPOID || result_isnull == true) { PG_RETURN_NULL(); } } @@ -7989,6 +8013,7 @@ Datum timediff(PG_FUNCTION_ARGS) Oid val_type1, val_type2; TimeADT result; int level = fcinfo->can_ignore || !SQL_MODE_STRICT() ? WARNING : ERROR; + bool result_isnull = false; val_type1 = get_fn_expr_argtype(fcinfo->flinfo, 0); val_type2 = get_fn_expr_argtype(fcinfo->flinfo, 1); @@ -8004,14 +8029,20 @@ Datum timediff(PG_FUNCTION_ARGS) val_type1 = convert_to_datetime_time(PG_GETARG_DATUM(0), val_type1, &datetime1, &time1); val_type2 = convert_unknown_to_datetime_time(DatumGetCString(PG_GETARG_DATUM(1)), &datetime2, &time2, val_type1); } else { - val_type1 = convert_to_datetime_time(PG_GETARG_DATUM(0), val_type1, &datetime1, &time1); + val_type1 = convert_to_datetime_time(PG_GETARG_DATUM(0), val_type1, &datetime1, &time1, fcinfo->can_ignore, &result_isnull); if (val_type1 == TIMEOID && time1 == B_FORMAT_TIME_INVALID_VALUE_TAG) { PG_RETURN_NULL(); } - val_type2 = convert_to_datetime_time(PG_GETARG_DATUM(1), val_type2, &datetime2, &time2); + if (result_isnull == true) { + PG_RETURN_NULL(); + } + val_type2 = convert_to_datetime_time(PG_GETARG_DATUM(1), val_type2, &datetime2, &time2, fcinfo->can_ignore, &result_isnull); if (val_type2 == TIMEOID && time2 == B_FORMAT_TIME_INVALID_VALUE_TAG) { PG_RETURN_NULL(); } + if (result_isnull == true) { + PG_RETURN_NULL(); + } } if (val_type1 != val_type2) { @@ -8346,6 +8377,25 @@ bool determine_conversion(int dtk) } } + +bool is_conversion_from_time_to_datetime(int dtk, Oid expr_type) +{ + if (expr_type != TIMETZOID && expr_type != TIMEOID) { + return false; + } + switch (dtk) { + case DTK_DAY: + case DTK_WEEK: + case DTK_MONTH: + case DTK_QUARTER: + case DTK_YEAR: + return true; + default: + return false; + } +} + + /* * @Description: Internal operation function of timestamp_add_numeric() * and timestamp_add_text() function. @@ -8358,6 +8408,7 @@ Datum timestamp_add_internal(PG_FUNCTION_ARGS, char *lowunits, int unit, int uni Timestamp datetime, res_datetime; DateADT date, res_date; TimeADT time, res_time; + bool is_need_convert_to_datetime = is_conversion_from_time_to_datetime(unit, expr_type); NumericVar tmp; lldiv_t delta; @@ -8387,17 +8438,20 @@ Datum timestamp_add_internal(PG_FUNCTION_ARGS, char *lowunits, int unit, int uni char *str = DatumGetCString(DirectFunctionCall1(year_out, expr)); ereport(ERROR, (errcode(DTERR_BAD_FORMAT), errmsg("Incorrect datetime value: \"%s\"", str))); } - switch (expr_type) { - // when the input type is time or timetz - case TIMETZOID: - case TIMEOID: - convert_to_time(expr, expr_type, &time); - res_time = time_sub_interval(time, span); - PG_RETURN_TEXT_P(DirectFunctionCall1(time_text, TimeADTGetDatum(res_time))); + + if (is_need_convert_to_datetime == false) { + switch (expr_type) { + // when the input type is time or timetz + case TIMETZOID: + case TIMEOID: + convert_to_time(expr, expr_type, &time); + res_time = time_sub_interval(time, span); + PG_RETURN_TEXT_P(DirectFunctionCall1(time_text, TimeADTGetDatum(res_time))); + } } bool conversion = determine_conversion(unit); - if (conversion) { + if (conversion || is_need_convert_to_datetime) { // With specific units, the return type is datetime convert_to_datetime(expr, expr_type, &datetime); check_b_format_datetime_range_with_ereport(datetime); diff --git a/contrib/dolphin/sql/builtin_funcs/b_compatibility_time_funcs2.sql b/contrib/dolphin/sql/builtin_funcs/b_compatibility_time_funcs2.sql index 5bc224a1f..9ab57d494 100644 --- a/contrib/dolphin/sql/builtin_funcs/b_compatibility_time_funcs2.sql +++ b/contrib/dolphin/sql/builtin_funcs/b_compatibility_time_funcs2.sql @@ -534,6 +534,9 @@ insert into func_test2(functionName, result) values('TIMESTAMPADD(year,1,time''2 insert into func_test2(functionName, result) values('TIMESTAMPADD(qtr,1,time''23:59:59'')', TIMESTAMPADD(qtr,1,time'23:59:59')); insert into func_test2(functionName, result) values('TIMESTAMPADD(month,1,time''23:59:59'')', TIMESTAMPADD(month,1,time'23:59:59')); +-- timetz +insert into func_test2(functionName, result) values('timestampadd(day, 1, timetz''1:1:0+05'')', timestampadd(day, 1, timetz'1:1:0+05')); + -- TIME、TIMESTAMP建表语法修改测试 create table t1(col timestamp('1')); create table t2(col time('1')); @@ -561,6 +564,10 @@ insert into func_test2(functionName, result) values('subtime(''-837:59:59'', ''- insert into func_test2(functionName, result) values('subtime(8385959, ''-1:00:00'')', subtime(8385959,'-1:00:00')); insert into func_test2(functionName, result) values('subtime(8375959.9999999, ''-1:00:00'')', subtime(8375959.9999999,'-1:00:00')); insert into func_test2(functionName, result) values('subtime(-8385959, ''1:00:00'')', subtime(-8385959,'1:00:00')); + +insert into func_test2(functionName, result) values('subtime(B''0'',B''1'')', subtime(B'0',B'1')); +insert into func_test2(functionName, result) values('TIMEDIFF(B''101'', B''101'')', TIMEDIFF(B'101', B'101')); +insert into func_test2(functionName, result) values('TIME(B''1'')', TIME(B'1')); select * from func_test2 order by functionName; set dolphin.b_compatibility_mode=on; -- Gitee