|
14 | 14 | * Copyright (c) 1998-2010, PostgreSQL Global Development Group
|
15 | 15 | *
|
16 | 16 | * IDENTIFICATION
|
17 |
| - * $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.125 2010/08/03 23:09:29 rhaas Exp $ |
| 17 | + * $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.126 2010/08/04 17:33:09 rhaas Exp $ |
18 | 18 | *
|
19 | 19 | *-------------------------------------------------------------------------
|
20 | 20 | */
|
@@ -565,18 +565,37 @@ numeric_is_nan(Numeric num)
|
565 | 565 | * Maximum size of a numeric with given typmod, or -1 if unlimited/unknown.
|
566 | 566 | */
|
567 | 567 | int32
|
568 |
| -numeric_maximum_size(int32 typemod) |
| 568 | +numeric_maximum_size(int32 typmod) |
569 | 569 | {
|
570 | 570 | int precision;
|
| 571 | + int numeric_digits; |
571 | 572 |
|
572 |
| - if (typemod <= VARHDRSZ) |
| 573 | + if (typmod < (int32) (VARHDRSZ)) |
573 | 574 | return -1;
|
574 | 575 |
|
575 | 576 | /* precision (ie, max # of digits) is in upper bits of typmod */
|
576 |
| - precision = ((typemod - VARHDRSZ) >> 16) & 0xffff; |
| 577 | + precision = ((typmod - VARHDRSZ) >> 16) & 0xffff; |
| 578 | + |
| 579 | + /* |
| 580 | + * This formula computes the maximum number of NumericDigits we could |
| 581 | + * need in order to store the specified number of decimal digits. |
| 582 | + * Because the weight is stored as a number of NumericDigits rather |
| 583 | + * than a number of decimal digits, it's possible that the first |
| 584 | + * NumericDigit will contain only a single decimal digit. Thus, the |
| 585 | + * first two decimal digits can require two NumericDigits to store, |
| 586 | + * but it isn't until we reach DEC_DIGITS + 2 decimal digits that we |
| 587 | + * potentially need a third NumericDigit. |
| 588 | + */ |
| 589 | + numeric_digits = (precision + 2 * (DEC_DIGITS - 1)) / DEC_DIGITS; |
577 | 590 |
|
578 |
| - /* Numeric stores 2 decimal digits/byte, plus header */ |
579 |
| - return (precision + 1) / 2 + NUMERIC_HDRSZ; |
| 591 | + /* |
| 592 | + * In most cases, the size of a numeric will be smaller than the value |
| 593 | + * computed below, because the varlena header will typically get toasted |
| 594 | + * down to a single byte before being stored on disk, and it may also |
| 595 | + * be possible to use a short numeric header. But our job here is to |
| 596 | + * compute the worst case. |
| 597 | + */ |
| 598 | + return NUMERIC_HDRSZ + (numeric_digits * sizeof(NumericDigit)); |
580 | 599 | }
|
581 | 600 |
|
582 | 601 | /*
|
|
0 commit comments