Skip to content

gcvctor: PGNumericValue silently rounds to 9 fractional digits — too lossy for the PostgreSQL dialect #249

Closed

Description

@apstndb

Feedback from spanpg phase 3 (apstndb/spanpg#5), where this had to be documented as a hazard on spanpg's EncodeOptions.

Problem

PGNumericValue(*big.Rat) (and PGNumericValueChecked) format the wire string with spanner.NumericString, which renders FloatString(9) — the GoogleSQL NUMERIC scale. The PostgreSQL-dialect numeric type accepts far more than 9 fractional digits, so building a PG_NUMERIC GCV from a big.Rat silently rounds values the target type could represent exactly. Unlike the GoogleSQL path there is no validation counterpart either: NumericValueChecked validates GoogleSQL precision/scale, which is not the PG constraint.

This is wire-correct for round-tripping values that originated in GoogleSQL NUMERIC, but as a general PG_NUMERIC constructor the 9-digit rounding is an arbitrary loss.

Suggested direction

Options, roughly in preference order:

  1. PGNumericValueExact(*big.Rat) (GCV, error) — exact decimal rendering when the rational has a finite decimal expansion (denominator of the form 2^a·5^b), error otherwise; callers with non-terminating rationals choose their own scale explicitly.
  2. A scale-parameterized variant (PGNumericValueScale(v *big.Rat, scale int)).
  3. Documentation-only: state the 9-digit rounding prominently on PGNumericValue and point callers holding exact decimal strings at StringBasedValueOf(typector.PGNumeric(), s) / PGNumericFromNullable (the workaround spanpg documents today).

At minimum option 3; option 1 keeps the family's explicit-strictness posture (no silent loss unless asked).

Activity

  1. added 2 commits that reference this issue on Jun 12, 2026
    aef12f9
    8c94312
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions