On Fri, Nov 28, 2025 at 09:46:43AM +0530, Amul Sul wrote: > I have attached patch 0002 that renames it. I also updated patch 0001 > to accommodate Amit's comment suggestions.
Thanks, applied this one after more tweaks. Regarding 0002, just doing a renaming makes me a bit uncomfortable after a second look. Another way to look at the problem while being consistent would be to convert date2timestamp_no_overflow() to use soft error reports, requiring its caller in selfuncs.c to use an error context node. I cannot get really excited at the end just for the sake of the planner stats. There were two more functions that btree_gin.c is pointing at that could to the switch: timestamp->timestamptz and its opposite. This also shaves some code, which is nice. Please see the attached. -- Michael
From b662223bac8a50a426f1d42c2f3226362b682675 Mon Sep 17 00:00:00 2001 From: Michael Paquier <[email protected]> Date: Mon, 1 Dec 2025 16:00:04 +0900 Subject: [PATCH] Update timestamp[tz] functions to use soft-error reporting --- src/include/utils/timestamp.h | 8 +- src/backend/utils/adt/timestamp.c | 121 +++++++++++------------------- contrib/btree_gin/btree_gin.c | 12 +-- 3 files changed, 54 insertions(+), 87 deletions(-) diff --git a/src/include/utils/timestamp.h b/src/include/utils/timestamp.h index 93531732b085..f1a85c7d9eba 100644 --- a/src/include/utils/timestamp.h +++ b/src/include/utils/timestamp.h @@ -142,10 +142,10 @@ extern int timestamp_cmp_internal(Timestamp dt1, Timestamp dt2); /* timestamp comparison works for timestamptz also */ #define timestamptz_cmp_internal(dt1,dt2) timestamp_cmp_internal(dt1, dt2) -extern TimestampTz timestamp2timestamptz_opt_overflow(Timestamp timestamp, - int *overflow); -extern Timestamp timestamptz2timestamp_opt_overflow(TimestampTz timestamp, - int *overflow); +extern TimestampTz timestamp2timestamptz_safe(Timestamp timestamp, + Node *escontext); +extern Timestamp timestamptz2timestamp_safe(TimestampTz timestamp, + Node *escontext); extern int32 timestamp_cmp_timestamptz_internal(Timestamp timestampVal, TimestampTz dt2); diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index 156a4830ffda..af48527d436f 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -2363,18 +2363,21 @@ int32 timestamp_cmp_timestamptz_internal(Timestamp timestampVal, TimestampTz dt2) { TimestampTz dt1; - int overflow; + ErrorSaveContext escontext = {T_ErrorSaveContext}; - dt1 = timestamp2timestamptz_opt_overflow(timestampVal, &overflow); - if (overflow > 0) + dt1 = timestamp2timestamptz_safe(timestampVal, (Node *) &escontext); + if (escontext.error_occurred) { - /* dt1 is larger than any finite timestamp, but less than infinity */ - return TIMESTAMP_IS_NOEND(dt2) ? -1 : +1; - } - if (overflow < 0) - { - /* dt1 is less than any finite timestamp, but more than -infinity */ - return TIMESTAMP_IS_NOBEGIN(dt2) ? +1 : -1; + if (TIMESTAMP_IS_NOEND(dt1)) + { + /* dt1 is larger than any finite timestamp, but less than infinity */ + return TIMESTAMP_IS_NOEND(dt2) ? -1 : +1; + } + if (TIMESTAMP_IS_NOBEGIN(dt1)) + { + /* dt1 is less than any finite timestamp, but more than -infinity */ + return TIMESTAMP_IS_NOBEGIN(dt2) ? +1 : -1; + } } return timestamptz_cmp_internal(dt1, dt2); @@ -6434,15 +6437,15 @@ timestamp_timestamptz(PG_FUNCTION_ARGS) /* * Convert timestamp to timestamp with time zone. * - * On successful conversion, *overflow is set to zero if it's not NULL. + * If the timestamp is finite but out of the valid range for timestamptz, + * error handling proceeds based on escontext. * - * If the timestamp is finite but out of the valid range for timestamptz, then: - * if overflow is NULL, we throw an out-of-range error. - * if overflow is not NULL, we store +1 or -1 there to indicate the sign - * of the overflow, and return the appropriate timestamptz infinity. + * If escontext is NULL, we throw an out-of-range error (hard error). + * If escontext is not NULL, we return NOBEGIN or NOEND for lower bound or + * upper bound overflow, respectively, and record a soft error. */ TimestampTz -timestamp2timestamptz_opt_overflow(Timestamp timestamp, int *overflow) +timestamp2timestamptz_safe(Timestamp timestamp, Node *escontext) { TimestampTz result; struct pg_tm tt, @@ -6450,9 +6453,6 @@ timestamp2timestamptz_opt_overflow(Timestamp timestamp, int *overflow) fsec_t fsec; int tz; - if (overflow) - *overflow = 0; - if (TIMESTAMP_NOT_FINITE(timestamp)) return timestamp; @@ -6467,26 +6467,14 @@ timestamp2timestamptz_opt_overflow(Timestamp timestamp, int *overflow) return result; } - if (overflow) - { - if (timestamp < 0) - { - *overflow = -1; - TIMESTAMP_NOBEGIN(result); - } - else - { - *overflow = 1; - TIMESTAMP_NOEND(result); - } - return result; - } + if (timestamp < 0) + TIMESTAMP_NOBEGIN(result); + else + TIMESTAMP_NOEND(result); - ereport(ERROR, + ereturn(escontext, result, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); - - return 0; } /* @@ -6495,7 +6483,7 @@ timestamp2timestamptz_opt_overflow(Timestamp timestamp, int *overflow) static TimestampTz timestamp2timestamptz(Timestamp timestamp) { - return timestamp2timestamptz_opt_overflow(timestamp, NULL); + return timestamp2timestamptz_safe(timestamp, NULL); } /* timestamptz_timestamp() @@ -6515,21 +6503,21 @@ timestamptz_timestamp(PG_FUNCTION_ARGS) static Timestamp timestamptz2timestamp(TimestampTz timestamp) { - return timestamptz2timestamp_opt_overflow(timestamp, NULL); + return timestamptz2timestamp_safe(timestamp, NULL); } /* * Convert timestamp with time zone to timestamp. * - * On successful conversion, *overflow is set to zero if it's not NULL. + * If the timestamptz is finite but out of the valid range for timestamp, + * error handling proceeds based on escontext. * - * If the timestamptz is finite but out of the valid range for timestamp, then: - * if overflow is NULL, we throw an out-of-range error. - * if overflow is not NULL, we store +1 or -1 there to indicate the sign - * of the overflow, and return the appropriate timestamp infinity. + * If escontext is NULL, we throw an out-of-range error (hard error). + * If escontext is not NULL, we return NOBEGIN or NOEND for lower bound or + * upper bound overflow, respectively, and record a soft error. */ Timestamp -timestamptz2timestamp_opt_overflow(TimestampTz timestamp, int *overflow) +timestamptz2timestamp_safe(TimestampTz timestamp, Node *escontext) { Timestamp result; struct pg_tm tt, @@ -6537,50 +6525,29 @@ timestamptz2timestamp_opt_overflow(TimestampTz timestamp, int *overflow) fsec_t fsec; int tz; - if (overflow) - *overflow = 0; - if (TIMESTAMP_NOT_FINITE(timestamp)) result = timestamp; else { if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0) { - if (overflow) - { - if (timestamp < 0) - { - *overflow = -1; - TIMESTAMP_NOBEGIN(result); - } - else - { - *overflow = 1; - TIMESTAMP_NOEND(result); - } - return result; - } - ereport(ERROR, + if (timestamp < 0) + TIMESTAMP_NOBEGIN(result); + else + TIMESTAMP_NOEND(result); + + ereturn(escontext, result, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); } if (tm2timestamp(tm, fsec, NULL, &result) != 0) { - if (overflow) - { - if (timestamp < 0) - { - *overflow = -1; - TIMESTAMP_NOBEGIN(result); - } - else - { - *overflow = 1; - TIMESTAMP_NOEND(result); - } - return result; - } - ereport(ERROR, + if (timestamp < 0) + TIMESTAMP_NOBEGIN(result); + else + TIMESTAMP_NOEND(result); + + ereturn(escontext, result, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); } diff --git a/contrib/btree_gin/btree_gin.c b/contrib/btree_gin/btree_gin.c index 1a2339a70c81..966b76e591b7 100644 --- a/contrib/btree_gin/btree_gin.c +++ b/contrib/btree_gin/btree_gin.c @@ -508,11 +508,11 @@ static Datum cvt_timestamptz_timestamp(Datum input) { TimestampTz val = DatumGetTimestampTz(input); + ErrorSaveContext escontext = {T_ErrorSaveContext}; Timestamp result; - int overflow; - result = timestamptz2timestamp_opt_overflow(val, &overflow); - /* We can ignore the overflow result, since result is useful as-is */ + result = timestamptz2timestamp_safe(val, (Node *) &escontext); + /* We can ignore errors, since result is useful as-is */ return TimestampGetDatum(result); } @@ -543,11 +543,11 @@ static Datum cvt_timestamp_timestamptz(Datum input) { Timestamp val = DatumGetTimestamp(input); + ErrorSaveContext escontext = {T_ErrorSaveContext}; TimestampTz result; - int overflow; - result = timestamp2timestamptz_opt_overflow(val, &overflow); - /* We can ignore the overflow result, since result is useful as-is */ + result = timestamp2timestamptz_safe(val, (Node *) &escontext); + /* We can ignore errors, since result is useful as-is */ return TimestampTzGetDatum(result); } -- 2.51.0
signature.asc
Description: PGP signature
