E2 codec family: arbitrary-precisionnumeric / decimal ↔ Decimal.
PostgreSQL'snumericis a base-10000 ("NBASE") big-decimal: a sign, a base-10000
exponent (weight), a display scale (dscale— the number of fractional decimal
digits to render), and a run of base-10000 digit groups most-significant first. The binary
wire layout produced bynumeric_send / consumed by numeric_recvis::
int16 ndigits -- count of base-10000 digit groups that follow
int16 weight -- base-10000 exponent of the FIRST group (group value = digit * 10000^weight)
uint16 sign -- 0x0000 positive, 0x4000 negative,
0xC000 NaN, 0xD000 +Infinity, 0xF000 -Infinity (PG14+)
int16 dscale -- display scale: number of fractional decimal digits
uint16[ndigits] -- base-10000 digit groups, 0..9999, most-significant first
Decoding reconstructs the exactDecimal, preserving dscaleas the
result's scale (soDecimal('1.50') round-trips as 1.50, not 1.5). Encoding goes
the other way: it splits aDecimal's decimal digits into base-10000 groups aligned on the
decimal point, normalizes off leading/trailing zero groups, and carries the original scale
throughdscale. The special-value sign codes carry Decimal NaN/
Infinitywith no digit groups.
The text format defers toDecimal(str)— PostgreSQL emits the canonical decimal string.
prefers_binary stays Trueso the hot path takes the exact base-10000 route and never
round-trips through a lossy float. This module touches no socket and no anyio: bytes in,
Decimalout.
data.drivers._pelt._codecs_numeric
| Name | Type | Default | Description |
|---|---|---|---|
type
|
|
— | |
qualified_name
|
|
— | |
element_type
|
|
— | |
description
|
|
— | |
source_file
|
|
— | |
line_number
|
|
— | |
is_autodoc
|
|
— | |
autodoc_element
|
|
— | |
_autodoc_template
|
|
— | |
_autodoc_url_path
|
|
— | |
_autodoc_page_type
|
|
— | |
title
|
|
— | |
doc_content_hash
|
|
— |
Symbols on this page
Buildunscaled * 10**point_exp exactly with result exponent pinned to target_exp.
Uses the precision-independentDecimal((sign, digit_tuple, exponent))constructor — it
never consultsgetcontext().prec…
Reconstruct an exactDecimalfrom the base-10000 wire layout.
Encode aDecimal(or numeric-coercible) into the base-10000 layout.
Thenumeric/decimalcodec (OID 1700) as a standalone instance.
_build_decimal
function
def _build_decimal(sign_bit: int, unscaled: int, point_exp: int, *, target_exp: int) -> Decimal
Buildunscaled * 10**point_exp exactly with result exponent pinned to target_exp.
Uses the precision-independentDecimal((sign, digit_tuple, exponent))constructor — it
never consultsgetcontext().precand never rounds, so the result is exact regardless of
which thread runs it (the ambient decimal context is thread-local; relying on it would
silently round on a worker whose context still carries the defaultprec=28).
The display scaletarget_exp = -dscaleis honored without ever discarding a nonzero
digit: if it is coarser thanpoint_expwe append trailing zeros; if it is finer we drop
trailing zero digits, but never below the resolution of the last nonzero digit (PG's
dscale always covers every stored fractional digit, so a finer point_exponly ever
carries zeros — but we stay exact even if it does not).
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
sign_bit
|
int
|
— | |
unscaled
|
int
|
— | |
point_exp
|
int
|
— | |
target_exp
|
int
|
— |
_decode_numeric_binary
function
def _decode_numeric_binary(data: bytes) -> Decimal
Reconstruct an exactDecimalfrom the base-10000 wire layout.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
data
|
bytes
|
— |
_encode_numeric_binary
function
def _encode_numeric_binary(value: Any) -> bytes
Encode aDecimal(or numeric-coercible) into the base-10000 layout.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
value
|
Any
|
— |
numeric_codec
function
def numeric_codec() -> Codec
Thenumeric/decimalcodec (OID 1700) as a standalone instance.
No parameters.