!1971 修复timestamp不支持infinity的问题

Merge pull request !1971 from Cross-罗/to_timestamp
This commit is contained in:
opengauss-bot
2022-07-26 03:57:42 +00:00
committed by Gitee
10 changed files with 87 additions and 2 deletions

View File

@ -11395,7 +11395,7 @@
),
AddFuncGroup(
"to_timestamp", 3,
AddBuiltinFunc(_0(1158), _1("to_timestamp"), _2(1), _3(true), _4(false), _5(NULL), _6(1184), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(SQLlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 701), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("select ('epoch'::pg_catalog.timestamptz + $1 * '1 second'::pg_catalog.interval)"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)),
AddBuiltinFunc(_0(1158), _1("to_timestamp"), _2(1), _3(true), _4(false), _5(float8_timestamptz), _6(1184), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 701), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("float8_timestamptz"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)),
AddBuiltinFunc(_0(TOTIMESTAMPFUNCOID), _1("to_timestamp"), _2(2), _3(true), _4(false), _5(to_timestamp), _6(1114), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(2, 25, 25), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("to_timestamp"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(true), _32(false), _33("convert text to timestamp with time zone"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)),
AddBuiltinFunc(_0(TOTIMESTAMPDEFAULTFUNCOID), _1("to_timestamp"), _2(1), _3(true), _4(false), _5(to_timestamp_default_format), _6(1114), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(1, 25), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("to_timestamp_default_format"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(true), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
),

View File

@ -5840,3 +5840,45 @@ void WalReplicationTimestampToString(WalReplicationTimestampInfo *timeStampInfo,
MAXTIMESTAMPLEN + 1);
securec_check(rc, "\0", "\0");
}
/*
* to_timestamp(double precision)
* Convert UNIX epoch to timestamptz.
*/
Datum float8_timestamptz(PG_FUNCTION_ARGS)
{
float8 seconds = PG_GETARG_FLOAT8(0);
TimestampTz result;
/* Deal with NaN and infinite inputs ... */
if (isnan(seconds)) {
ereport(ERROR, (errmsg("timestamp cannot be NaN")));
}
if (isinf(seconds)) {
if (seconds < 0) {
TIMESTAMP_NOBEGIN(result);
} else {
TIMESTAMP_NOEND(result);
}
} else {
/* Out of range? */
if (seconds < (float8) SECS_PER_DAY * (DATETIME_MIN_JULIAN - UNIX_EPOCH_JDATE) ||
seconds >= (float8) SECS_PER_DAY * (TIMESTAMP_END_JULIAN - UNIX_EPOCH_JDATE)) {
ereport(ERROR, (errmsg("timestamp out of range: \"%g\"", seconds)));
}
/* Convert UNIX epoch to Postgres epoch */
seconds -= ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);
seconds = rint(seconds * USECS_PER_SEC);
result = (int64) seconds;
/* Recheck in case roundoff produces something just out of range */
if (!IS_VALID_TIMESTAMP(result)) {
ereport(ERROR, (errmsg("timestamp out of range: \"%g\"", PG_GETARG_FLOAT8(0))));
}
}
PG_RETURN_TIMESTAMP(result);
}

View File

@ -59,7 +59,7 @@ bool open_join_children = true;
bool will_shutdown = false;
/* hard-wired binary version number */
const uint32 GRAND_VERSION_NUM = 92610;
const uint32 GRAND_VERSION_NUM = 92611;
const uint32 PREDPUSH_SAME_LEVEL_VERSION_NUM = 92522;
const uint32 UPSERT_WHERE_VERSION_NUM = 92514;

View File

@ -0,0 +1,3 @@
DROP FUNCTION IF EXISTS pg_catalog.to_timestamp(float8);
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 1158;
CREATE FUNCTION pg_catalog.to_timestamp(float8) RETURNS timestamptz LANGUAGE SQL AS 'select (''epoch''::pg_catalog.timestamptz + $1 * ''1 second''::pg_catalog.interval)';

View File

@ -0,0 +1,3 @@
DROP FUNCTION IF EXISTS pg_catalog.to_timestamp(float8);
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 1158;
CREATE FUNCTION pg_catalog.to_timestamp(float8) RETURNS timestamptz LANGUAGE SQL AS 'select (''epoch''::pg_catalog.timestamptz + $1 * ''1 second''::pg_catalog.interval)';

View File

@ -0,0 +1,3 @@
DROP FUNCTION IF EXISTS pg_catalog.to_timestamp(float8);
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 1158;
CREATE FUNCTION pg_catalog.to_timestamp(float8) RETURNS timestamptz LANGUAGE INTERNAL STABLE AS 'float8_timestamptz';

View File

@ -0,0 +1,3 @@
DROP FUNCTION IF EXISTS pg_catalog.to_timestamp(float8);
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 1158;
CREATE FUNCTION pg_catalog.to_timestamp(float8) RETURNS timestamptz LANGUAGE INTERNAL STABLE AS 'float8_timestamptz';

View File

@ -156,6 +156,18 @@ typedef struct {
#define TIMESTAMP_NOT_FINITE(j) (TIMESTAMP_IS_NOBEGIN(j) || TIMESTAMP_IS_NOEND(j))
/* Timestamp limits */
#define MIN_TIMESTAMP INT64CONST(-211813488000000000)
#define END_TIMESTAMP INT64CONST(9223371331200000000)
/* First allowed date, and first disallowed date, in Julian-date form */
#define DATETIME_MIN_JULIAN (0)
#define DATE_END_JULIAN (2147483494) /* == date2j(JULIAN_MAXYEAR, 1, 1) */
#define TIMESTAMP_END_JULIAN (109203528) /* == date2j(294277, 1, 1) */
/* Range-check a timestamp */
#define IS_VALID_TIMESTAMP(t) (MIN_TIMESTAMP <= (t) && (t) < END_TIMESTAMP)
/*
* Julian date support.
*

View File

@ -1020,3 +1020,18 @@ end;
NOTICE: @ 0
NOTICE: @ 0
NOTICE: @ 0
SELECT to_timestamp(' Infinity'::float);
to_timestamp
--------------
infinity
(1 row)
SELECT to_timestamp('-Infinity'::float);
to_timestamp
--------------
-infinity
(1 row)
SELECT to_timestamp('NaN'::float);
ERROR: timestamp cannot be NaN
CONTEXT: referenced column: to_timestamp

View File

@ -265,3 +265,7 @@ begin
set timezone to default;
end;
/
SELECT to_timestamp(' Infinity'::float);
SELECT to_timestamp('-Infinity'::float);
SELECT to_timestamp('NaN'::float);