diff options
Diffstat (limited to 'src/backend/utils')
-rw-r--r-- | src/backend/utils/adt/cash.c | 12 | ||||
-rw-r--r-- | src/backend/utils/adt/numeric.c | 4 | ||||
-rw-r--r-- | src/backend/utils/adt/numutils.c | 34 | ||||
-rw-r--r-- | src/backend/utils/adt/timestamp.c | 28 |
4 files changed, 29 insertions, 49 deletions
diff --git a/src/backend/utils/adt/cash.c b/src/backend/utils/adt/cash.c index ec3c08acfc2..c1a743b2a6b 100644 --- a/src/backend/utils/adt/cash.c +++ b/src/backend/utils/adt/cash.c @@ -387,6 +387,7 @@ Datum cash_out(PG_FUNCTION_ARGS) { Cash value = PG_GETARG_CASH(0); + uint64 uvalue; char *result; char buf[128]; char *bufptr; @@ -429,8 +430,6 @@ cash_out(PG_FUNCTION_ARGS) if (value < 0) { - /* make the amount positive for digit-reconstruction loop */ - value = -value; /* set up formatting data */ signsymbol = (*lconvert->negative_sign != '\0') ? lconvert->negative_sign : "-"; sign_posn = lconvert->n_sign_posn; @@ -445,6 +444,9 @@ cash_out(PG_FUNCTION_ARGS) sep_by_space = lconvert->p_sep_by_space; } + /* make the amount positive for digit-reconstruction loop */ + uvalue = pg_abs_s64(value); + /* we build the digits+decimal-point+sep string right-to-left in buf[] */ bufptr = buf + sizeof(buf) - 1; *bufptr = '\0'; @@ -470,10 +472,10 @@ cash_out(PG_FUNCTION_ARGS) memcpy(bufptr, ssymbol, strlen(ssymbol)); } - *(--bufptr) = ((uint64) value % 10) + '0'; - value = ((uint64) value) / 10; + *(--bufptr) = (uvalue % 10) + '0'; + uvalue = uvalue / 10; digit_pos--; - } while (value || digit_pos >= 0); + } while (uvalue || digit_pos >= 0); /*---------- * Now, attach currency symbol and sign symbol in the correct order. diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index 77f64331f36..44d88e90079 100644 --- a/src/backend/utils/adt/numeric.c +++ b/src/backend/utils/adt/numeric.c @@ -8113,7 +8113,7 @@ int64_to_numericvar(int64 val, NumericVar *var) if (val < 0) { var->sign = NUMERIC_NEG; - uval = -val; + uval = pg_abs_s64(val); } else { @@ -11584,7 +11584,7 @@ power_var_int(const NumericVar *base, int exp, int exp_dscale, * Now we can proceed with the multiplications. */ neg = (exp < 0); - mask = abs(exp); + mask = pg_abs_s32(exp); init_var(&base_prod); set_var_from_var(base, &base_prod); diff --git a/src/backend/utils/adt/numutils.c b/src/backend/utils/adt/numutils.c index adc1e8a4cba..63c2beb6a29 100644 --- a/src/backend/utils/adt/numutils.c +++ b/src/backend/utils/adt/numutils.c @@ -18,6 +18,7 @@ #include <limits.h> #include <ctype.h> +#include "common/int.h" #include "port/pg_bitutils.h" #include "utils/builtins.h" @@ -131,6 +132,7 @@ pg_strtoint16_safe(const char *s, Node *escontext) uint16 tmp = 0; bool neg = false; unsigned char digit; + int16 result; /* * The majority of cases are likely to be base-10 digits without any @@ -190,10 +192,9 @@ pg_strtoint16_safe(const char *s, Node *escontext) if (neg) { - /* check the negative equivalent will fit without overflowing */ - if (unlikely(tmp > (uint16) (-(PG_INT16_MIN + 1)) + 1)) + if (unlikely(pg_neg_u16_overflow(tmp, &result))) goto out_of_range; - return -((int16) tmp); + return result; } if (unlikely(tmp > PG_INT16_MAX)) @@ -333,10 +334,9 @@ slow: if (neg) { - /* check the negative equivalent will fit without overflowing */ - if (tmp > (uint16) (-(PG_INT16_MIN + 1)) + 1) + if (unlikely(pg_neg_u16_overflow(tmp, &result))) goto out_of_range; - return -((int16) tmp); + return result; } if (tmp > PG_INT16_MAX) @@ -393,6 +393,7 @@ pg_strtoint32_safe(const char *s, Node *escontext) uint32 tmp = 0; bool neg = false; unsigned char digit; + int32 result; /* * The majority of cases are likely to be base-10 digits without any @@ -452,10 +453,9 @@ pg_strtoint32_safe(const char *s, Node *escontext) if (neg) { - /* check the negative equivalent will fit without overflowing */ - if (unlikely(tmp > (uint32) (-(PG_INT32_MIN + 1)) + 1)) + if (unlikely(pg_neg_u32_overflow(tmp, &result))) goto out_of_range; - return -((int32) tmp); + return result; } if (unlikely(tmp > PG_INT32_MAX)) @@ -595,10 +595,9 @@ slow: if (neg) { - /* check the negative equivalent will fit without overflowing */ - if (tmp > (uint32) (-(PG_INT32_MIN + 1)) + 1) + if (unlikely(pg_neg_u32_overflow(tmp, &result))) goto out_of_range; - return -((int32) tmp); + return result; } if (tmp > PG_INT32_MAX) @@ -655,6 +654,7 @@ pg_strtoint64_safe(const char *s, Node *escontext) uint64 tmp = 0; bool neg = false; unsigned char digit; + int64 result; /* * The majority of cases are likely to be base-10 digits without any @@ -714,10 +714,9 @@ pg_strtoint64_safe(const char *s, Node *escontext) if (neg) { - /* check the negative equivalent will fit without overflowing */ - if (unlikely(tmp > (uint64) (-(PG_INT64_MIN + 1)) + 1)) + if (unlikely(pg_neg_u64_overflow(tmp, &result))) goto out_of_range; - return -((int64) tmp); + return result; } if (unlikely(tmp > PG_INT64_MAX)) @@ -857,10 +856,9 @@ slow: if (neg) { - /* check the negative equivalent will fit without overflowing */ - if (tmp > (uint64) (-(PG_INT64_MIN + 1)) + 1) + if (unlikely(pg_neg_u64_overflow(tmp, &result))) goto out_of_range; - return -((int64) tmp); + return result; } if (tmp > PG_INT64_MAX) diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index 69fe7860ede..43800addf48 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -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; |