to_number(): allow 'V' to divide by 10^(the number of digits)
authorBruce Momjian <[email protected]>
Tue, 6 Oct 2015 01:03:38 +0000 (21:03 -0400)
committerBruce Momjian <[email protected]>
Tue, 6 Oct 2015 01:03:38 +0000 (21:03 -0400)
to_char('V') already multiplied in a similar manner.

Report by Jeremy Lowery

doc/src/sgml/func.sgml
src/backend/utils/adt/formatting.c

index 897ed647798c11a4168b135daf9e0e88c1b8b935..f8d9e460937b3294880bb65327f6264085705c17 100644 (file)
@@ -6152,12 +6152,14 @@ SELECT regexp_matches('abc01234xyz', '(?:(.*?)(\d+)(.*)){1,1}');
 
      <listitem>
       <para>
-       <literal>V</literal> effectively
+       <literal>V</literal> with <function>to_char</function>
        multiplies the input values by
        <literal>10^<replaceable>n</replaceable></literal>, where
        <replaceable>n</replaceable> is the number of digits following
-       <literal>V</literal>.
-       <function>to_char</function> does not support the use of
+       <literal>V</literal>.  <literal>V</literal> with
+       <function>to_number</function> divides in a similar manner.
+       <function>to_char</function> and <function>to_number</function>
+       do not support the use of
        <literal>V</literal> combined with a decimal point
        (e.g., <literal>99.9V99</literal> is not allowed).
       </para>
index 5b09de32efc66d3ac07c559837ff101c45324f04..0a203f88991d128c5e787edc7e82183d3b62093a 100644 (file)
@@ -5055,7 +5055,7 @@ numeric_to_number(PG_FUNCTION_ARGS)
                  VARSIZE(value) - VARHDRSZ, 0, 0, false, PG_GET_COLLATION());
 
    scale = Num.post;
-   precision = Max(0, Num.pre) + scale;
+   precision = Num.pre + Num.multi + scale;
 
    if (shouldFree)
        pfree(format);
@@ -5064,6 +5064,23 @@ numeric_to_number(PG_FUNCTION_ARGS)
                                 CStringGetDatum(numstr),
                                 ObjectIdGetDatum(InvalidOid),
                      Int32GetDatum(((precision << 16) | scale) + VARHDRSZ));
+
+   if (IS_MULTI(&Num))
+   {
+       Numeric     x;
+       Numeric     a = DatumGetNumeric(DirectFunctionCall1(int4_numeric,
+                                                    Int32GetDatum(10)));
+       Numeric     b = DatumGetNumeric(DirectFunctionCall1(int4_numeric,
+                                             Int32GetDatum(-Num.multi)));
+
+       x = DatumGetNumeric(DirectFunctionCall2(numeric_power,
+                                               NumericGetDatum(a),
+                                               NumericGetDatum(b)));
+       result = DirectFunctionCall2(numeric_mul,
+                                    result,
+                                    NumericGetDatum(x));
+   }
+
    pfree(numstr);
    return result;
 }