aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/jsonpath_exec.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2020-10-07 17:10:26 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2020-10-07 17:10:26 -0400
commit3db322eaab9688d57643b4d2a5f52b7f350ef46f (patch)
tree66318bc8ee6d673df3b6dbc67de45bf8d0ec590f /src/backend/utils/adt/jsonpath_exec.c
parent6c05e5b77471dfadebe50ad4a8bdedef02ad0078 (diff)
downloadpostgresql-3db322eaab9688d57643b4d2a5f52b7f350ef46f.tar.gz
postgresql-3db322eaab9688d57643b4d2a5f52b7f350ef46f.zip
Prevent internal overflows in date-vs-timestamp and related comparisons.
The date-vs-timestamp, date-vs-timestamptz, and timestamp-vs-timestamptz comparators all worked by promoting the first type to the second and then doing a simple same-type comparison. This works fine, except when the conversion result is out of range, in which case we throw an entirely avoidable error. The sources of such failures are (a) type date can represent dates much farther in the future than the timestamp types can; (b) timezone rotation might cause a just-in-range timestamp value to become a just-out-of-range timestamptz value. Up to now we just ignored these corner-case issues, but now we have an actual user complaint (bug #16657 from Huss EL-Sheikh), so let's do something about it. It turns out that commit 52ad1e659 already built all the necessary infrastructure to support error-free comparisons, but neglected to actually use it in the main-line code paths. Fix that, do a little bit of code style review, and remove the now-duplicate logic in jsonpath_exec.c. Back-patch to v13 where 52ad1e659 came in. We could take this back further by back-patching said infrastructure, but given the small number of complaints so far, I don't feel a great need to. Discussion: https://postgr.es/m/16657-cde2f876d8cc7971@postgresql.org
Diffstat (limited to 'src/backend/utils/adt/jsonpath_exec.c')
-rw-r--r--src/backend/utils/adt/jsonpath_exec.c71
1 files changed, 7 insertions, 64 deletions
diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c
index 28be845770a..1059f34130a 100644
--- a/src/backend/utils/adt/jsonpath_exec.c
+++ b/src/backend/utils/adt/jsonpath_exec.c
@@ -2602,93 +2602,36 @@ castTimeToTimeTz(Datum time, bool useTz)
return DirectFunctionCall1(time_timetz, time);
}
-/*---
- * Compares 'ts1' and 'ts2' timestamp, assuming that ts1 might be overflowed
- * during cast from another datatype.
- *
- * 'overflow1' specifies overflow of 'ts1' value:
- * 0 - no overflow,
- * -1 - exceed lower boundary,
- * 1 - exceed upper boundary.
- */
-static int
-cmpTimestampWithOverflow(Timestamp ts1, int overflow1, Timestamp ts2)
-{
- /*
- * All the timestamps we deal with in jsonpath are produced by
- * to_datetime() method. So, they should be valid.
- */
- Assert(IS_VALID_TIMESTAMP(ts2));
-
- /*
- * Timestamp, which exceed lower (upper) bound, is always lower (higher)
- * than any valid timestamp except minus (plus) infinity.
- */
- if (overflow1)
- {
- if (overflow1 < 0)
- {
- if (TIMESTAMP_IS_NOBEGIN(ts2))
- return 1;
- else
- return -1;
- }
- if (overflow1 > 0)
- {
- if (TIMESTAMP_IS_NOEND(ts2))
- return -1;
- else
- return 1;
- }
- }
-
- return timestamp_cmp_internal(ts1, ts2);
-}
-
/*
- * Compare date to timestamptz without throwing overflow error during cast.
+ * Compare date to timestamp.
+ * Note that this doesn't involve any timezone considerations.
*/
static int
cmpDateToTimestamp(DateADT date1, Timestamp ts2, bool useTz)
{
- TimestampTz ts1;
- int overflow = 0;
-
- ts1 = date2timestamp_opt_overflow(date1, &overflow);
-
- return cmpTimestampWithOverflow(ts1, overflow, ts2);
+ return date_cmp_timestamp_internal(date1, ts2);
}
/*
- * Compare date to timestamptz without throwing overflow error during cast.
+ * Compare date to timestamptz.
*/
static int
cmpDateToTimestampTz(DateADT date1, TimestampTz tstz2, bool useTz)
{
- TimestampTz tstz1;
- int overflow = 0;
-
checkTimezoneIsUsedForCast(useTz, "date", "timestamptz");
- tstz1 = date2timestamptz_opt_overflow(date1, &overflow);
-
- return cmpTimestampWithOverflow(tstz1, overflow, tstz2);
+ return date_cmp_timestamptz_internal(date1, tstz2);
}
/*
- * Compare timestamp to timestamptz without throwing overflow error during cast.
+ * Compare timestamp to timestamptz.
*/
static int
cmpTimestampToTimestampTz(Timestamp ts1, TimestampTz tstz2, bool useTz)
{
- TimestampTz tstz1;
- int overflow = 0;
-
checkTimezoneIsUsedForCast(useTz, "timestamp", "timestamptz");
- tstz1 = timestamp2timestamptz_opt_overflow(ts1, &overflow);
-
- return cmpTimestampWithOverflow(tstz1, overflow, tstz2);
+ return timestamp_cmp_timestamptz_internal(ts1, tstz2);
}
/*