Skip to content

Commit 97f3800

Browse files
committed
Fix numeric_maximum_size() calculation.
The old computation can sometimes underestimate the necessary space by 2 bytes; however we're not back-patching this, because this result isn't used for anything critical. Per discussion with Tom Lane, make the typmod test in this function match the ones in numeric() and apply_typmod() exactly.
1 parent ba19b23 commit 97f3800

File tree

1 file changed

+25
-6
lines changed

1 file changed

+25
-6
lines changed

src/backend/utils/adt/numeric.c

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* Copyright (c) 1998-2010, PostgreSQL Global Development Group
1515
*
1616
* 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 $
1818
*
1919
*-------------------------------------------------------------------------
2020
*/
@@ -565,18 +565,37 @@ numeric_is_nan(Numeric num)
565565
* Maximum size of a numeric with given typmod, or -1 if unlimited/unknown.
566566
*/
567567
int32
568-
numeric_maximum_size(int32 typemod)
568+
numeric_maximum_size(int32 typmod)
569569
{
570570
int precision;
571+
int numeric_digits;
571572

572-
if (typemod <= VARHDRSZ)
573+
if (typmod < (int32) (VARHDRSZ))
573574
return -1;
574575

575576
/* 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;
577590

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));
580599
}
581600

582601
/*

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy