8000 Back-patch critical fixes for NUMERIC... · sangli00/postgres@8d018f9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8d018f9

Browse files
committed
Back-patch critical fixes for NUMERIC...
1 parent 2513765 commit 8d018f9

File tree

2 files changed

+63
-42
lines changed

2 files changed

+63
-42
lines changed

src/backend/catalog/pg_aggregate.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.20.2.1 1999/08/02 05:56:55 scrappy Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.20.2.2 2000/01/16 00:44:04 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -313,7 +313,10 @@ AggNameGetInitVal(char *aggName, Oid basetype, int xfuncno, bool *isNull)
313313
pfree(strInitVal);
314314
elog(ERROR, "AggNameGetInitVal: cache lookup failed on aggregate transition function return type");
315315
}
316-
initVal = fmgr(((Form_pg_type) GETSTRUCT(tup))->typinput, strInitVal, -1);
316+
initVal = fmgr(((Form_pg_type) GETSTRUCT(tup))->typinput,
317+
strInitVal,
318+
((Form_pg_type) GETSTRUCT(tup))->typelem,
319+
-1);
317320
pfree(strInitVal);
318321
return initVal;
319322
}

src/backend/utils/adt/numeric.c

Lines changed: 58 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* 1998 Jan Wieck
77
*
8-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.16.2.1 1999/08/02 05:24:55 scrappy Exp $
8+
* $Head 10000 er: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.16.2.2 2000/01/16 00:44:06 tgl Exp $
99
*
1010
* ----------
1111
*/
@@ -249,46 +249,50 @@ numeric_out(Numeric num)
249249
init_var(&x);
250250
set_var_from_num(num, &x);
251251

252-
/* ----------
253-
* Allocate space for the result
254-
* ----------
255-
*/
256-
str = palloc(x.dscale + MAX(0, x.weight) + 5);
257-
cp = str;
258-
259-
/* ----------
260-
* Output a dash for negative values
261-
* ----------
262-
*/
263-
if (x.sign == NUMERIC_NEG)
264-
*cp++ = '-';
265-
266252
/* ----------
267253
* Check if we must round up before printing the value and
268254
* do so.
269255
* ----------
270256
*/
271-
if (x.dscale < x.rscale && (x.dscale + x.weight + 1) < x.ndigits)
257+
i = x.dscale + x.weight + 1;
258+
if (i >= 0 && x.ndigits > i)
272259
{
273-
int j;
274-
int carry;
260+
int carry = (x.digits[i] > 4) ? 1 : 0;
275261

276-
j = x.dscale + x.weight + 1;
277-
carry = (x.digits[j] > 4) ? 1 : 0;
262+
x.ndigits = i;
278263

279264
while (carry)
280265
{
281-
j--;
282-
carry += x.digits[j];
283-
x.digits[j] = carry % 10;
266+
carry += x.digits[--i];
267+
x.digits[i] = carry % 10;
284268
carry /= 10;
285269
}
286-
if (j < 0)
270+
271+
if (i < 0)
287272
{
273+
Assert(i == -1); /* better not have added more than 1 digit */
274+
Assert(x.digits > (NumericDigit *) (x.buf + 1));
288275
x.digits--;
276+
x.ndigits++;
289277
x.weight++;
290278
}
291279
}
280+
else
281+
x.ndigits = MAX(0, MIN(i, x.ndigits));
282+
283+
/* ----------
284+
* Allocate space for the result
285+
* ----------
286+
*/
287+
str = palloc(MAX(0, x.dscale) + MAX(0, x.weight) + 4);
288+
cp = str;
289+
290+
/* ----------
291+
* Output a dash for negative values
292+
* ----------
293+
*/
294+
if (x.sign == NUMERIC_NEG)
295+
*cp++ = '-';
292296

293297
/* ----------
294298
* Output all digits before the decimal point
@@ -2212,7 +2216,8 @@ set_var_from_str(char *str, NumericVar *dest)
22122216

22132217
if (*cp == 'e' || *cp == 'E')
22142218
{
2215-
/* Handle ...Ennn */
2219+
/* XXX Should handle ...Ennn */
2220+
elog(ERROR, "Bad numeric input format '%s'", str);
22162221
}
22172222

22182223
while (dest->ndigits > 0 && *(dest->digits) == 0)
@@ -2378,20 +2383,14 @@ apply_typmod(NumericVar *var, int32 typmod)
23782383
scale = typmod & 0xffff;
23792384
maxweight = precision - scale;
23802385

2381-
if (var->weight >= maxweight)
2382-
{
2383-
free_allvars();
2384-
elog(ERROR, "overflow on numeric "
2385-
"ABS(value) >= 10^%d for field with precision %d scale %d",
2386-
var->weight, precision, scale);
2387-
}
2388-
2386+
/* Round to target scale */
23892387
i = scale + var->weight + 1;
23902388
if (i >= 0 && var->ndigits > i)
23912389
{
2392-
long carry = (var->digits[i] > 4) ? 1 : 0;
2390+
int carry = (var->digits[i] > 4) ? 1 : 0;
23932391

23942392
var->ndigits = i;
2393+
23952394
while (carry)
23962395
{
23972396
carry += var->digits[--i];
@@ -2401,6 +2400,8 @@ apply_typmod(NumericVar *var, int32 typmod)
24012400

24022401
if (i < 0)
24032402
{
2403+
Assert(i == -1); /* better not have added more than 1 digit */
2404+
Assert(var->digits > (NumericDigit *) (var->buf + 1));
24042405
var->digits--;
24052406
var->ndigits++;
24062407
var->weight++;
@@ -2410,16 +2411,33 @@ apply_typmod(NumericVar *var, int32 typmod)
24102411
var->ndigits = MAX(0, MIN(i, var->ndigits));
24112412

24122413
/* ----------
2413-
* Check for overflow again - rounding could have raised the
2414-
* weight.
2414+
* Check for overflow - note we can't do this before rounding,
2415+
* because rounding could raise the weight. Also note that the
2416+
* var's weight could be inflated by leading zeroes, which will
2417+
* be stripped before storage but perhaps might not have been yet.
2418+
* In any case, we must recognize a true zero, whose weight doesn't
2419+
* mean anything.
24152420
* ----------
24162421
*/
24172422
if (var->weight >= maxweight)
24182423
{
2419-
free_allvars();
2420-
elog(ERROR, "overflow on numeric "
2421-
"ABS(value) >= 10^%d for field with precision %d scale %d",
2422-
var->weight, precision, scale);
2424+
/* Determine true weight; and check for all-zero result */
2425+
int tweight = var->weight;
2426+
2427+
for (i = 0; i < var->ndigits; i++)
2428+
{
2429+
if (var->digits[i])
2430+
break;
2431+
tweight--;
2432+
}
2433+
2434+
if (tweight >= maxweight && i < var->ndigits)
2435+
{
2436+
free_allvars();
2437+
elog(ERROR, "overflow on numeric "
2438+
"ABS(value) >= 10^%d for field with precision %d scale %d",
2439+
tweight, precision, scale);
2440+
}
24232441
}
24242442

24252443
var->rscale = scale;

0 commit comments

Comments
 (0)
0