diff options
author | Alexander Korotkov <akorotkov@postgresql.org> | 2019-09-25 21:51:47 +0300 |
---|---|---|
committer | Alexander Korotkov <akorotkov@postgresql.org> | 2019-09-25 22:51:51 +0300 |
commit | 5bc450629b31a0b6986e668056d5bd36792412d2 (patch) | |
tree | 34f352243ddeaf8120fd870ff8460ad7b447ec1c /src/backend/utils/adt/date.c | |
parent | 66c74f8b6e347ba5830bf06468bef8081601c187 (diff) |
Error suppression support for upcoming jsonpath .datetime() method
Add support of error suppression in some date and time manipulation functions
as it's required for jsonpath .datetime() method support. This commit doesn't
use PG_TRY()/PG_CATCH() in order to implement that. Instead, it provides
internal versions of date and time functions used, which support error
suppression.
Discussion: https://postgr.es/m/CAPpHfdsZgYEra_PeCLGNoXOWYx6iU-S3wF8aX0ObQUcZU%2B4XTw%40mail.gmail.com
Author: Alexander Korotkov, Nikita Glukhov
Reviewed-by: Anastasia Lubennikova, Peter Eisentraut
Diffstat (limited to 'src/backend/utils/adt/date.c')
-rw-r--r-- | src/backend/utils/adt/date.c | 86 |
1 files changed, 71 insertions, 15 deletions
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c index 9e291b5c7bc..fa50d79c05d 100644 --- a/src/backend/utils/adt/date.c +++ b/src/backend/utils/adt/date.c @@ -550,13 +550,15 @@ date_mii(PG_FUNCTION_ARGS) PG_RETURN_DATEADT(result); } + /* - * Internal routines for promoting date to timestamp and timestamp with - * time zone + * Promote date to timestamp. + * + * If 'have_error' is NULL, then errors are thrown, else '*have_error' is set + * and zero is returned. */ - -static Timestamp -date2timestamp(DateADT dateVal) +Timestamp +date2timestamp_opt_error(DateADT dateVal, bool *have_error) { Timestamp result; @@ -572,9 +574,19 @@ date2timestamp(DateADT dateVal) * boundary need be checked for overflow. */ if (dateVal >= (TIMESTAMP_END_JULIAN - POSTGRES_EPOCH_JDATE)) - ereport(ERROR, - (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), - errmsg("date out of range for timestamp"))); + { + if (have_error) + { + *have_error = true; + return (Timestamp) 0; + } + else + { + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("date out of range for timestamp"))); + } + } /* date is days since 2000, timestamp is microseconds since same... */ result = dateVal * USECS_PER_DAY; @@ -583,8 +595,23 @@ date2timestamp(DateADT dateVal) return result; } +/* + * Single-argument version of date2timestamp_opt_error(). + */ static TimestampTz -date2timestamptz(DateADT dateVal) +date2timestamp(DateADT dateVal) +{ + return date2timestamp_opt_error(dateVal, NULL); +} + +/* + * Promote date to timestamp with time zone. + * + * If 'have_error' is NULL, then errors are thrown, else '*have_error' is set + * and zero is returned. + */ +TimestampTz +date2timestamptz_opt_error(DateADT dateVal, bool *have_error) { TimestampTz result; struct pg_tm tt, @@ -603,9 +630,19 @@ date2timestamptz(DateADT dateVal) * boundary need be checked for overflow. */ if (dateVal >= (TIMESTAMP_END_JULIAN - POSTGRES_EPOCH_JDATE)) - ereport(ERROR, - (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), - errmsg("date out of range for timestamp"))); + { + if (have_error) + { + *have_error = true; + return (TimestampTz) 0; + } + else + { + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("date out of range for timestamp"))); + } + } j2date(dateVal + POSTGRES_EPOCH_JDATE, &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); @@ -621,15 +658,34 @@ date2timestamptz(DateADT dateVal) * of time zone, check for allowed timestamp range after adding tz. */ if (!IS_VALID_TIMESTAMP(result)) - ereport(ERROR, - (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), - errmsg("date out of range for timestamp"))); + { + if (have_error) + { + *have_error = true; + return (TimestampTz) 0; + } + else + { + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("date out of range for timestamp"))); + } + } } return result; } /* + * Single-argument version of date2timestamptz_opt_error(). + */ +static TimestampTz +date2timestamptz(DateADT dateVal) +{ + return date2timestamptz_opt_error(dateVal, NULL); +} + +/* * date2timestamp_no_overflow * * This is chartered to produce a double value that is numerically |