- 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.
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
Modifier and TypeInterfaceDescriptionstatic class
A reference implementation that maps toBigDecimal
(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
Modifier and TypeFieldDescriptionstatic final int
Decimal digits perNBASE
digit.static final int
The base of the 'digit' elements supplied by PostgreSQL.static final int
The maximum precision that may be specified in anumeric
type modifier.static final int
The maximum 'scale' that may be specified in anumeric
type modifier in PostgreSQL 15 or later.static final int
The minimum 'scale' that may be specified in anumeric
type modifier in PostgreSQL 15 or later. -
Method Summary
Modifier and TypeMethodDescriptionconstruct
(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_PRECISIONThe maximum precision that may be specified in anumeric
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_SCALEThe minimum 'scale' that may be specified in anumeric
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_SCALEThe maximum 'scale' that may be specified in anumeric
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 NBASEThe 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_DIGITSDecimal digits perNBASE
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 NANdisplayScale
- 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
-