Interface Numeric<T>

All Superinterfaces:
Adapter.Contract<T>, Adapter.Contract.Scalar<T>
All Known Implementing Classes:
Numeric.AsBigDecimal
Functional Interface:
This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.

@FunctionalInterface public interface Numeric<T> extends Adapter.Contract.Scalar<T>
The NUMERIC type's PostgreSQL semantics: a sign (or indication that the value is NaN, + infinity, or - infinity), a display scale, a weight, and zero or more base-ten-thousand digits.

This data type can have a type modifier that specifies a maximum precision (total number of base-ten digits to retain) and a maximum scale (how many of those base-ten digits are right of the decimal point).

A curious feature of the type is that, when a type modifier is specified, the value becomes "anchored" to the decimal point: all of its decimal digits must be within precision places of the decimal point, or an error is reported. This rules out the kind of values that can crop up in physics, for example, where there might be ten digits of precision but those are twenty places away from the decimal point. This limitation apparently follows from the ISO SQL definitions of the precision and scale.

However, when PostgreSQL NUMERIC is used with no type modifier, such values are not rejected, and are stored efficiently, just as you would expect, keeping only the digits that are needed and adjusting weight for the distance to the decimal point.

In mapping to and from a Java representation, extra care may be needed if that capability is to be preserved.

  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Interface
    Description
    static class 
    A reference implementation that maps to BigDecimal (but cannot represent all possible values).
    static enum 
    Label to distinguish positive, negative, and three kinds of special values.
    static interface 
    Functional interface to obtain information from the PostgreSQL type modifier applied to the type.

    Nested classes/interfaces inherited from interface org.postgresql.pljava.Adapter.Contract

    Adapter.Contract.Array<T,E,A extends Adapter<E,?>>, Adapter.Contract.Scalar<T>
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final int
    Decimal digits per NBASE digit.
    static final int
    The base of the 'digit' elements supplied by PostgreSQL.
    static final int
    The maximum precision that may be specified in a numeric type modifier.
    static final int
    The maximum 'scale' that may be specified in a numeric type modifier in PostgreSQL 15 or later.
    static final int
    The minimum 'scale' that may be specified in a numeric type modifier in PostgreSQL 15 or later.
  • Method Summary

    Modifier and Type
    Method
    Description
    construct(Numeric.Kind kind, int displayScale, int weight, short[] base10000Digits)
    Constructs a representation T from the components of the PostgreSQL data type.
  • Field Details

    • NUMERIC_MAX_PRECISION

      static final int NUMERIC_MAX_PRECISION
      The maximum precision that may be specified in a numeric type modifier.

      Without a modifier, the type is subject only to its implementation limits, which are much larger.

      See Also:
    • NUMERIC_MIN_SCALE

      static final int NUMERIC_MIN_SCALE
      The minimum 'scale' that may be specified in a numeric type modifier in PostgreSQL 15 or later.

      Negative scale indicates rounding left of the decimal point. A scale of -1000 indicates rounding to a multiple of 101000.

      Prior to PostgreSQL 15, a type modifier did not allow a negative scale.

      Without a modifier, the type is subject only to its implementation limits.

      See Also:
    • NUMERIC_MAX_SCALE

      static final int NUMERIC_MAX_SCALE
      The maximum 'scale' that may be specified in a numeric type modifier in PostgreSQL 15 or later.

      When scale is positive, the digits string represents a value smaller by the indicated power of ten. When scale exceeds precision, the digits string represents digits that appear following (scale - precision) zeros to the right of the decimal point.

      Prior to PostgreSQL 15, a type modifier did not allow a scale greater than the specified precision.

      Without a modifier, the type is subject only to its implementation limits.

      See Also:
    • NBASE

      static final int NBASE
      The base of the 'digit' elements supplied by PostgreSQL.

      This is also built into the parameter name base10000Digits and is highly unlikely to change; a comment in the PostgreSQL code since 2015 confirms "values of NBASE other than 10000 are considered of historical interest only and are no longer supported in any sense".

      See Also:
    • DEC_DIGITS

      static final int DEC_DIGITS
      Decimal digits per NBASE digit.
      See Also:
  • Method Details

    • construct

      T construct(Numeric.Kind kind, int displayScale, int weight, short[] base10000Digits) throws SQLException
      Constructs a representation T from the components of the PostgreSQL data type.

      A note about displayScale: when positive, it is information, stored with the PostgreSQL value, that conveys how far (right of the units place) the least significant decimal digit of the intended value falls.

      An apparentScale can also be computed:

        apparentScale = (1 + weight - base10000Digits.length) * (- DEC_DIGITS)
      
      This computation has a simple meaning, and gives the distance, right of the units place, of the least-significant decimal digit in the stored representation. When negative, of course, it means that least stored digit falls left of the units place.

      Because of the DEC_DIGITS factor, apparentScale computed this way will always be a multiple of four, the next such (in the direction of more significant digits) from the position of the actual least significant digit in the value. So apparentScale may exceed displayScale by as much as three, and, if so, displayScale should be used in preference, to avoid overstating the value's significant figures.

      Likewise, if displayScale is positive, it should be used even if it exceeds apparentScale. In that case, it conveys that PostgreSQL knows additional digits are significant, even though they were zero and it did not store them.

      However, the situation when displayScale is zero is less clear-cut, because PostgreSQL simply disallows it ever to be negative. This clamping of displayScale loses information, such that a value with displayScale zero and apparentScale negative may represent any of:

      • A limited-precision value with non-significant trailing zeros (from -apparentScale to as many as -apparentScale+3 of them)
      • A precise integer, all of whose -apparentScale non-stored significant digits just happened to be zeros
      • or anything in between.

      That these cases can't be distinguished is inherent in PostgreSQL's representation of the type, and any implementation of this interface will need to make and document a choice of how to proceed. If the choice is to rely on apparentScale, then the fact that it is a multiple of four and may overstate, by up to three, the number of significant digits (as known, perhaps, to a human who assigned the value) has to be lived with; when displayScale is clamped to zero there simply isn't enough information to do better.

      For example, consider this adapter applied to the result of:

       SELECT 6.62607015e-34 AS planck, 6.02214076e23 AS avogadro;
      

      Planck's constant (a small number defined with nine significant places) will be presented with displayScale=42, weight=-9, and base10000Digits=[662, 6070, 1500]. Because apparentScale works out to 44 (placing the least stored digit 44 places right of the decimal point, a multiple of 4) but displayScale is only 42, it is clear that the two trailing zeroes in the last element are non-significant, and the value has not eleven but only nine significant figures.

      In contrast, Avogadro's number (a large one, defined also with nine significant places) will arrive with weight=5 and base10000Digits=[6022, 1407, 6000], but displayScale will not be -15; it is clamped to zero instead. If an implementation of this contract chooses to compute apparentScale, that will be -12 (the next larger multiple of four) and the value will seem to have gained three extra significant figures. On the other hand, in an implementation that takes the clamped-to-zero displayScale at face value, the number will seem to have gained fifteen extra significant figures.

      Parameters:
      kind - POSITIVE, NEGATIVE, POSINFINITY, NEGINFINITY, or NAN
      displayScale - nominal precision, nonnegative; the number of base ten digits right of the decimal point. If this exceeds the number of right-of-decimal digits determined by the stored value, the excess represents a number of trailing decimal zeroes that are significant but trimmed from storage.
      weight - indicates the power of ten thousand which the first base ten-thousand digit is taken is taken to represent. If the array base10000Digits has length one, and that one digit has the value 3, and weight is zero, the value is 3. If weight is 1, the value is 30000, and if weight is -1, the value is 0.0003.
      base10000Digits - each array element is a nonnegative value not above 9999, representing a single digit of a base-ten-thousand number. The element at index zero is the most significant. The caller may pass a zero-length array, but may not pass null. The array is unshared and may be used as desired.
      Throws:
      SQLException