Liking cljdoc? Tell your friends :D

datahike.pg.sql.coerce

Numeric coercion helpers for SQL value paths (CAST + INSERT/UPDATE).

Both apply-sql-cast (in stmt.clj) and coerce-insert-value (also stmt.clj) used to inline Long/parseLong / Double/parseDouble / BigDecimal. with subtly different null/blank/overflow rules:

  • apply-sql-cast threw NumberFormatException on parse failure and .longValue on overflow (silently truncating).
  • coerce-insert-value's BigInteger branch silently truncated to long via Number.longValue.longValue of 2^63 returns Long/MIN_VALUE, which is a wrong-value bug, not a parse bug.
  • The bigdec / float / double string branches each had their own (try … (catch NumberFormatException _ val)) returning the original string on failure, which Datahike then rejected downstream with a generic schema error instead of 22P02.

This namespace centralises those rules so every numeric write goes through helpers that raise the right SQLSTATE:

  • 22003 numeric_value_out_of_range when a value can't fit the target's range.
  • 22P02 invalid_text_representation when a string can't be parsed as the target type.

Both errors are encoded as ex-info with :sqlstate; the wire layer's handler.clj already lifts those into ErrorResponse messages.

Numeric coercion helpers for SQL value paths (CAST + INSERT/UPDATE).

Both `apply-sql-cast` (in stmt.clj) and `coerce-insert-value`
(also stmt.clj) used to inline `Long/parseLong` /
`Double/parseDouble` / `BigDecimal.` with subtly different
null/blank/overflow rules:

  * apply-sql-cast threw `NumberFormatException` on parse failure
    and `.longValue` on overflow (silently truncating).
  * coerce-insert-value's BigInteger branch silently truncated
    to long via `Number.longValue` — `.longValue` of `2^63` returns
    `Long/MIN_VALUE`, which is a wrong-value bug, not a parse bug.
  * The bigdec / float / double string branches each had their
    own `(try … (catch NumberFormatException _ val))` returning
    the original string on failure, which Datahike then rejected
    downstream with a generic schema error instead of `22P02`.

This namespace centralises those rules so every numeric write goes
through helpers that raise the right SQLSTATE:

  * `22003 numeric_value_out_of_range` when a value can't fit
    the target's range.
  * `22P02 invalid_text_representation` when a string can't be
    parsed as the target type.

Both errors are encoded as `ex-info` with `:sqlstate`; the wire
layer's `handler.clj` already lifts those into ErrorResponse
messages.
raw docstring

bigint->longclj

(bigint->long bi)

BigInteger → primitive long, or raise 22003 numeric_value_out_of_range.

BigInteger → primitive long, or raise `22003 numeric_value_out_of_range`.
raw docstring

coerce-bigintclj

(coerce-bigint v)

Coerce a numeric value to a Java long with PG-style overflow checking.

Raises 22003 numeric_value_out_of_range when v exceeds Long range. Truncates fractional parts (matches CAST(numeric AS int8) — PG actually rounds, but Datahike has no exact-numeric int type; this mirrors the rest of the pipeline that uses (long …)).

Strings: parsed strictly as integers (no decimal point, no exponent). Use coerce-numeric :long if you want decimal-string support.

Coerce a numeric value to a Java long with PG-style overflow checking.

Raises `22003 numeric_value_out_of_range` when v exceeds Long range.
Truncates fractional parts (matches `CAST(numeric AS int8)` — PG
actually rounds, but Datahike has no exact-numeric int type; this
mirrors the rest of the pipeline that uses `(long …)`).

Strings: parsed strictly as integers (no decimal point, no
exponent). Use `coerce-numeric :long` if you want decimal-string
support.
raw docstring

coerce-numericclj

(coerce-numeric v target)

Coerce v (number or string) to the requested numeric target.

target is one of: :long — Java Long; raises 22003 on overflow. Strings may include a decimal/exponent (parsed via BigDecimal then narrowed). :double — Java Double (±Infinity allowed, mirrors PG float8). :float — Java Float (±Infinity allowed, mirrors PG real). :bigdec — Java BigDecimal (exact, scientific notation OK).

Numbers pass through as the right type. Strings go through parse-decimal as the canonical intermediate. Unparseable strings raise 22P02; out-of-range numbers (only for :long) raise 22003. nil → nil.

Coerce `v` (number or string) to the requested numeric `target`.

`target` is one of:
  :long    — Java Long; raises 22003 on overflow. Strings may include
             a decimal/exponent (parsed via BigDecimal then narrowed).
  :double  — Java Double (±Infinity allowed, mirrors PG float8).
  :float   — Java Float  (±Infinity allowed, mirrors PG real).
  :bigdec  — Java BigDecimal (exact, scientific notation OK).

Numbers pass through as the right type. Strings go through
`parse-decimal` as the canonical intermediate. Unparseable strings
raise `22P02`; out-of-range numbers (only for `:long`) raise
`22003`. nil → nil.
raw docstring

coerce-unknownclj

(coerce-unknown s vtype)
(coerce-unknown s vtype timestamp-parser)

PG-style typinput dispatch: coerce an unknown-type string literal to vtype using the type's typinput equivalent. Returns the typed value on success, the original string on failure (so the surrounding comparison falls through to text equality and matches nothing — PG's outcome when an unknown literal can't resolve to the operator's expected type).

The :db.type/instant typinput needs a parse-timestamp helper that lives in expr.clj; instant coercion is wired separately via coerce-comparison-operands taking an explicit timestamp parser.

PG-style typinput dispatch: coerce an unknown-type string literal to
`vtype` using the type's typinput equivalent. Returns the typed
value on success, the original string on failure (so the
surrounding comparison falls through to text equality and matches
nothing — PG's outcome when an unknown literal can't resolve to
the operator's expected type).

The `:db.type/instant` typinput needs a parse-timestamp helper
that lives in expr.clj; instant coercion is wired separately via
`coerce-comparison-operands` taking an explicit timestamp parser.
raw docstring

parse-decimalclj

(parse-decimal s)

Parse a string as BigDecimal — accepts scientific notation, trims whitespace. Raises 22P02 on unparseable input. Returns nil for nil input. Empty / whitespace-only strings raise 22P02.

Parse a string as BigDecimal — accepts scientific notation, trims
whitespace. Raises `22P02` on unparseable input. Returns nil for
nil input. Empty / whitespace-only strings raise 22P02.
raw docstring

pg-errorclj

(pg-error sqlstate msg)
(pg-error sqlstate msg data)

Build an ex-info that the wire layer renders as PG ErrorResponse. sqlstate is the 5-char SQLSTATE; msg is the human-readable text.

Build an ex-info that the wire layer renders as PG ErrorResponse.
`sqlstate` is the 5-char SQLSTATE; `msg` is the human-readable text.
raw docstring

vtype->typinputclj

{:db/valueType → (fn [^String s] typed-value-or-nil)}. Each fn is the Datahike-side analogue of PG's typinput for the corresponding target type — oidin/int8inLong/parseLong, numericinBigDecimal., etc. A nil return means the literal is unparseable for that type; the caller decides how to handle (typically: keep the original string so the comparison falls through to text equality, never matches, returns 0 rows — exactly what PG would do if the surrounding operator-resolution failed).

Restricted to pure / immutable conversions; mutable typinputs (e.g. timestamptz with the session's TimeZone GUC) need ctx threaded through and aren't covered.

`{:db/valueType → (fn [^String s] typed-value-or-nil)}`. Each fn is
the Datahike-side analogue of PG's typinput for the corresponding
target type — `oidin`/`int8in` → `Long/parseLong`, `numericin` →
`BigDecimal.`, etc. A nil return means the literal is unparseable
for that type; the caller decides how to handle (typically: keep
the original string so the comparison falls through to text
equality, never matches, returns 0 rows — exactly what PG would do
if the surrounding operator-resolution failed).

Restricted to pure / immutable conversions; mutable typinputs
(e.g. timestamptz with the session's TimeZone GUC) need ctx
threaded through and aren't covered.
raw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close