diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index a83feea396..f76b7bbbd0 100644 --- a/src/backend/utils/adt/numeric.c +++ b/src/backend/utils/adt/numeric.c @@ -301,6 +301,7 @@ struct NumericData * This is feasible because the digit buffer is separate from the variable. * ---------- */ +#define FIXED_BUF_LEN 4 typedef struct NumericVar { int ndigits; /* # of digits in digits[] - can be 0! */ @@ -309,6 +310,8 @@ typedef struct NumericVar int dscale; /* display scale */ NumericDigit *buf; /* start of palloc'd space for digits[] */ NumericDigit *digits; /* base-NBASE digits */ + bool is_allocated; /* is buf palloc'd? */ + NumericDigit fixed_buf[FIXED_BUF_LEN]; } NumericVar; @@ -414,18 +417,18 @@ typedef struct NumericSumAccum */ static const NumericDigit const_zero_data[1] = {0}; static const NumericVar const_zero = -{0, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_zero_data}; +{0, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_zero_data, false, {0}}; static const NumericDigit const_one_data[1] = {1}; static const NumericVar const_one = -{1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_one_data}; +{1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_one_data, false, {0}}; static const NumericVar const_minus_one = -{1, 0, NUMERIC_NEG, 0, NULL, (NumericDigit *) const_one_data}; +{1, 0, NUMERIC_NEG, 0, NULL, (NumericDigit *) const_one_data, false, {0}}; static const NumericDigit const_two_data[1] = {2}; static const NumericVar const_two = -{1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_two_data}; +{1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_two_data, false, {0}}; #if DEC_DIGITS == 4 static const NumericDigit const_zero_point_nine_data[1] = {9000}; @@ -435,7 +438,7 @@ static const NumericDigit const_zero_point_nine_data[1] = {90}; static const NumericDigit const_zero_point_nine_data[1] = {9}; #endif static const NumericVar const_zero_point_nine = -{1, -1, NUMERIC_POS, 1, NULL, (NumericDigit *) const_zero_point_nine_data}; +{1, -1, NUMERIC_POS, 1, NULL, (NumericDigit *) const_zero_point_nine_data, false, {0}}; #if DEC_DIGITS == 4 static const NumericDigit const_one_point_one_data[2] = {1, 1000}; @@ -445,16 +448,16 @@ static const NumericDigit const_one_point_one_data[2] = {1, 10}; static const NumericDigit const_one_point_one_data[2] = {1, 1}; #endif static const NumericVar const_one_point_one = -{2, 0, NUMERIC_POS, 1, NULL, (NumericDigit *) const_one_point_one_data}; +{2, 0, NUMERIC_POS, 1, NULL, (NumericDigit *) const_one_point_one_data, false, {0}}; static const NumericVar const_nan = -{0, 0, NUMERIC_NAN, 0, NULL, NULL}; +{0, 0, NUMERIC_NAN, 0, NULL, NULL, false, {0}}; static const NumericVar const_pinf = -{0, 0, NUMERIC_PINF, 0, NULL, NULL}; +{0, 0, NUMERIC_PINF, 0, NULL, NULL, false, {0}}; static const NumericVar const_ninf = -{0, 0, NUMERIC_NINF, 0, NULL, NULL}; +{0, 0, NUMERIC_NINF, 0, NULL, NULL, false, {0}}; #if DEC_DIGITS == 4 static const int round_powers[4] = {0, 1000, 100, 10}; @@ -6871,10 +6874,23 @@ dump_var(const char *str, NumericVar *var) static void alloc_var(NumericVar *var, int ndigits) { - digitbuf_free(var->buf); - var->buf = digitbuf_alloc(ndigits + 1); - var->buf[0] = 0; /* spare digit for rounding */ - var->digits = var->buf + 1; + if (var->is_allocated) + digitbuf_free(var->buf); + if (ndigits < FIXED_BUF_LEN - 1) + { + init_var(var); + var->is_allocated = false; + var->fixed_buf[0] = 0; /* spare digit for rounding */ + var->digits = var->fixed_buf + 1; + + } + else + { + var->is_allocated = true; + var->buf = digitbuf_alloc(ndigits + 1); + var->buf[0] = 0; /* spare digit for rounding */ + var->digits = var->buf + 1; + } var->ndigits = ndigits; }