mirror of
https://github.com/postgres/postgres.git
synced 2025-06-26 12:21:12 +03:00
Remove dependence on -fwrapv semantics in a few places.
This commit attempts to update a few places, such as the money, numeric, and timestamp types, to no longer rely on signed integer wrapping for correctness. This is intended to move us closer towards removing -fwrapv, which may enable some compiler optimizations. However, there is presently no plan to actually remove that compiler option in the near future. Besides using some of the existing overflow-aware routines in int.h, this commit introduces and makes use of some new ones. Specifically, it adds functions that accept a signed integer and return its absolute value as an unsigned integer with the same width (e.g., pg_abs_s64()). It also adds functions that accept an unsigned integer, store the result of negating that integer in a signed integer with the same width, and return whether the negation overflowed (e.g., pg_neg_u64_overflow()). Finally, this commit adds a couple of tests for timestamps near POSTGRES_EPOCH_JDATE. Author: Joseph Koshakow Reviewed-by: Tom Lane, Heikki Linnakangas, Jian He Discussion: https://postgr.es/m/CAAvxfHdBPOyEGS7s%2Bxf4iaW0-cgiq25jpYdWBqQqvLtLe_t6tw%40mail.gmail.com
This commit is contained in:
@ -618,19 +618,8 @@ make_timestamp_internal(int year, int month, int day,
|
||||
time = (((hour * MINS_PER_HOUR + min) * SECS_PER_MINUTE)
|
||||
* USECS_PER_SEC) + (int64) rint(sec * USECS_PER_SEC);
|
||||
|
||||
result = date * USECS_PER_DAY + time;
|
||||
/* check for major overflow */
|
||||
if ((result - time) / USECS_PER_DAY != date)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||
errmsg("timestamp out of range: %d-%02d-%02d %d:%02d:%02g",
|
||||
year, month, day,
|
||||
hour, min, sec)));
|
||||
|
||||
/* check for just-barely overflow (okay except time-of-day wraps) */
|
||||
/* caution: we want to allow 1999-12-31 24:00:00 */
|
||||
if ((result < 0 && date > 0) ||
|
||||
(result > 0 && date < -1))
|
||||
if (unlikely(pg_mul_s64_overflow(date, USECS_PER_DAY, &result) ||
|
||||
pg_add_s64_overflow(result, time, &result)))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||
errmsg("timestamp out of range: %d-%02d-%02d %d:%02d:%02g",
|
||||
@ -2010,17 +1999,8 @@ tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
|
||||
date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
|
||||
time = time2t(tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);
|
||||
|
||||
*result = date * USECS_PER_DAY + time;
|
||||
/* check for major overflow */
|
||||
if ((*result - time) / USECS_PER_DAY != date)
|
||||
{
|
||||
*result = 0; /* keep compiler quiet */
|
||||
return -1;
|
||||
}
|
||||
/* check for just-barely overflow (okay except time-of-day wraps) */
|
||||
/* caution: we want to allow 1999-12-31 24:00:00 */
|
||||
if ((*result < 0 && date > 0) ||
|
||||
(*result > 0 && date < -1))
|
||||
if (unlikely(pg_mul_s64_overflow(date, USECS_PER_DAY, result) ||
|
||||
pg_add_s64_overflow(*result, time, result)))
|
||||
{
|
||||
*result = 0; /* keep compiler quiet */
|
||||
return -1;
|
||||
|
Reference in New Issue
Block a user