Liking cljdoc? Tell your friends :D

datahike.pg.arrays

First-class array values for pgwire-datahike.

Mirrors PostgreSQL's ArrayType (src/include/utils/array.h): a value carrying element-type, the element vector (possibly nested for multi-dim), per-dimension sizes, and per-dimension lower bounds. Subscripting, slicing, membership, containment, concat, PG text-format codec.

Design notes:

  • elem-type is a keyword matching our types/oid-* naming (:int8, :text, :name, :bool, :float8, …) — not an OID. Resolution to OID happens at the oid-infer / describeResult layer.
  • elements is a Clojure vector. For 1-D arrays it's a flat vector of element values (nil represents SQL NULL). For multi-dim it's a nested vector — outermost level is the first dimension, innermost is the last. Always a uniform shape; PG rejects ragged arrays and so do we (the parser raises on a dimension mismatch).
  • dims is the vector of per-dimension sizes. nil is shorthand for [(count elements)] — a 1-D array. For multi-dim, (count dims) = ndim, (reduce * dims) = total leaf count.
  • lbounds is the vector of per-dimension lower bounds. nil is shorthand for [1, 1, …]. PG defaults to 1; non-1 lbounds come from ARRAY[lo:hi]=… literals (rare). Preserved through to-pg-text/from-pg-text round-trip when non-default.
  • We deliberately do NOT use the :__null__ sentinel inside arrays. Arrays are values we own end-to-end, so element NULLs are Clojure nil.
  • Subscript semantics follow PG exactly: 1-indexed (offset by lbound), out-of-range returns nil (SQL NULL), NOT an error. arr[0] and arr[-1] return nil for the default lbound=1.
  • defrecord gives us structural equality/hash — important for datahike/datalog round-trip (arrays flow through query results, bind params, and DISTINCT/GROUP BY without special handling).

Text codec follows PG (src/backend/utils/adt/arrayfuncs.c: array_out / array_in):

  • {} for empty
  • Elements joined by ,; nested dimensions emit nested {…}
  • Quote "…" when element contains ,, ", \, {, }, or whitespace, or is empty, or is the literal NULL (case-insensitive)
  • Inside quotes: escape \ and " with backslash
  • NULL elements emit unquoted NULL token
  • Booleans as t/f (PG text format for BOOL)
  • Non-default lbounds emit a [lo1:hi1][lo2:hi2]…= prefix
First-class array values for pgwire-datahike.

Mirrors PostgreSQL's `ArrayType` (src/include/utils/array.h): a
value carrying element-type, the element vector (possibly nested
for multi-dim), per-dimension sizes, and per-dimension lower
bounds. Subscripting, slicing, membership, containment, concat,
PG text-format codec.

Design notes:
- `elem-type` is a keyword matching our types/oid-* naming
  (`:int8`, `:text`, `:name`, `:bool`, `:float8`, …) — not an OID.
  Resolution to OID happens at the oid-infer / describeResult layer.
- `elements` is a Clojure vector. For 1-D arrays it's a flat
  vector of element values (`nil` represents SQL NULL). For
  multi-dim it's a nested vector — outermost level is the first
  dimension, innermost is the last. Always a uniform shape; PG
  rejects ragged arrays and so do we (the parser raises on a
  dimension mismatch).
- `dims` is the vector of per-dimension sizes. `nil` is shorthand
  for `[(count elements)]` — a 1-D array. For multi-dim,
  `(count dims) = ndim`, `(reduce * dims) = total leaf count`.
- `lbounds` is the vector of per-dimension lower bounds. `nil` is
  shorthand for `[1, 1, …]`. PG defaults to 1; non-1 lbounds come
  from `ARRAY[lo:hi]=…` literals (rare). Preserved through
  to-pg-text/from-pg-text round-trip when non-default.
- We deliberately do NOT use the `:__null__` sentinel inside
  arrays. Arrays are values we own end-to-end, so element NULLs
  are Clojure `nil`.
- Subscript semantics follow PG exactly: 1-indexed (offset by
  lbound), out-of-range returns `nil` (SQL NULL), NOT an error.
  `arr[0]` and `arr[-1]` return nil for the default lbound=1.
- `defrecord` gives us structural equality/hash — important for
  datahike/datalog round-trip (arrays flow through query results,
  bind params, and DISTINCT/GROUP BY without special handling).

Text codec follows PG (`src/backend/utils/adt/arrayfuncs.c`:
`array_out` / `array_in`):
- `{}` for empty
- Elements joined by `,`; nested dimensions emit nested `{…}`
- Quote `"…"` when element contains `,`, `"`, `\`, `{`, `}`, or
  whitespace, or is empty, or is the literal `NULL` (case-insensitive)
- Inside quotes: escape `\` and `"` with backslash
- NULL elements emit unquoted `NULL` token
- Booleans as `t`/`f` (PG text format for BOOL)
- Non-default lbounds emit a `[lo1:hi1][lo2:hi2]…=` prefix
raw docstring

all-match?clj

(all-match? a pred)

Predicate form: returns true if (pred leaf) returns truthy for every leaf. Vacuously true for an empty array (PG semantics for x = ALL(<empty>)).

Predicate form: returns true if (pred leaf) returns truthy for
every leaf. Vacuously true for an empty array (PG semantics for
`x = ALL(<empty>)`).
raw docstring

any-match?clj

(any-match? a pred)

Predicate form: returns true if (pred leaf) returns truthy for some leaf. Walks all dimensions.

Predicate form: returns true if (pred leaf) returns truthy for some
leaf. Walks all dimensions.
raw docstring

arrayclj

(array elem-type elements)
(array elem-type elements dims-or-lbound)
(array elem-type elements dims lbounds)

Construct a PgArray. Element-type is a keyword (:int8, :text, :bool, …). Optional dims (vector of per-dim sizes) and lbounds (vector of per-dim lower bounds, defaulting to 1 for each).

For 1-D arrays you can omit dims/lbounds — they're derived from (count elements) and 1 respectively. For multi-dim, pass a nested-vector elements and dims is computed automatically; or pass dims explicitly when the elements form is something exotic.

Construct a PgArray. Element-type is a keyword (`:int8`, `:text`,
`:bool`, …). Optional dims (vector of per-dim sizes) and lbounds
(vector of per-dim lower bounds, defaulting to 1 for each).

For 1-D arrays you can omit dims/lbounds — they're derived from
`(count elements)` and `1` respectively. For multi-dim, pass a
nested-vector `elements` and dims is computed automatically; or
pass dims explicitly when the elements form is something exotic.
raw docstring

array?clj

(array? v)

True iff v is a PgArray instance.

True iff v is a PgArray instance.
raw docstring

cat-rejecting-mismatchclj


concat-arrsclj

(concat-arrs a b)

PG a || b — full multi-dim semantics via cat-rejecting-mismatch. Element-types must match; we leave compatibility checks to the call-site (PG coerces via least common supertype).

PG `a || b` — full multi-dim semantics via `cat-rejecting-mismatch`.
Element-types must match; we leave compatibility checks to the
call-site (PG coerces via least common supertype).
raw docstring

contains-arr?clj

(contains-arr? a b)

PG a @> b: every non-null leaf of b is present somewhere in a. Operates on flattened leaves — PG ignores shape for @>.

PG `a @> b`: every non-null leaf of b is present somewhere in a.
Operates on flattened leaves — PG ignores shape for `@>`.
raw docstring

element-typeclj

(element-type a)

Element-type keyword (:text, :int8, etc.).

Element-type keyword (:text, :int8, etc.).
raw docstring

flat-elementsclj

(flat-elements a)

Walk a (possibly nested) elements vector to a flat seq of leaves — used by member? / contains-arr? / overlap? and the binary codec which encode element-by-element regardless of shape. Preserves nil leaves so 3-valued logic works through them. Descends into nested PgArray records as well as Clojure sequentials so an outer PgArray whose :elements happen to hold inner PgArrays (the common shape produced by expr.clj's ArrayConstructor build-fn for ARRAY[ARRAY[…],…]) is walked correctly.

Walk a (possibly nested) elements vector to a flat seq of leaves —
used by member? / contains-arr? / overlap? and the binary codec
which encode element-by-element regardless of shape. Preserves nil
leaves so 3-valued logic works through them. Descends into nested
PgArray records as well as Clojure sequentials so an outer
PgArray whose `:elements` happen to hold inner PgArrays (the
common shape produced by expr.clj's ArrayConstructor build-fn for
`ARRAY[ARRAY[…],…]`) is walked correctly.
raw docstring

from-pg-textclj

(from-pg-text s elem-type)

Parse PG array text format into a PgArray of the given element-type. Inverse of to-pg-text. Handles:

  • {} — empty array
  • {1,2,3} — flat 1-D
  • {{1,2},{3,4}} — multi-dim (nested braces)
  • [2:4]={a,b,c} — non-default lbound
  • [1:2][1:2]={{1,0},{0,1}} — non-default multi-dim lbound
  • quoted strings with ,, ", \ escape sequences
  • unquoted NULL token → element nil Raises on malformed input or ragged shape.
Parse PG array text format into a PgArray of the given element-type.
Inverse of `to-pg-text`. Handles:
- `{}` — empty array
- `{1,2,3}` — flat 1-D
- `{{1,2},{3,4}}` — multi-dim (nested braces)
- `[2:4]={a,b,c}` — non-default lbound
- `[1:2][1:2]={{1,0},{0,1}}` — non-default multi-dim lbound
- quoted strings with `,`, `"`, `\` escape sequences
- unquoted `NULL` token → element nil
Raises on malformed input or ragged shape.
raw docstring

lboundclj

(lbound a)
(lbound a d)

Lower bound for dimension d (1-indexed, default 1). PG: arrays default to 1; explicit [lo:hi]= literals can shift this.

Lower bound for dimension `d` (1-indexed, default 1). PG: arrays
default to 1; explicit `[lo:hi]=` literals can shift this.
raw docstring

lengthclj

(length a)

Element count along the outermost (first) dimension. For 1-D arrays that's the total leaf count. For multi-dim it's the size of dim 1. Differs from PG's array_length — this returns 0 for an empty array; call-sites that need PG's NULL-for-empty check explicitly.

Element count along the outermost (first) dimension. For 1-D arrays
that's the total leaf count. For multi-dim it's the size of dim 1.
Differs from PG's `array_length` — this returns 0 for an empty
array; call-sites that need PG's NULL-for-empty check explicitly.
raw docstring

length-dclj

(length-d a d)

Length along dimension d (1-indexed). PG's array_length(arr, d) returns NULL when d is out of range — call-sites should check (<= d (ndim a)) before relying on the result.

Length along dimension `d` (1-indexed). PG's `array_length(arr, d)`
returns NULL when d is out of range — call-sites should check
`(<= d (ndim a))` before relying on the result.
raw docstring

match-shapeclj

(match-shape a b)

Predicate: does b have a shape that's compatible with being a sub-element of a? PG accepts this when (rest dims-a) matches dims-b exactly. Used by array_cat for the asymmetric N-D || (N-1)-D and (N-1)-D || N-D cases (array_userfuncs.c:471–479).

Predicate: does `b` have a shape that's compatible with being a
sub-element of `a`? PG accepts this when `(rest dims-a)` matches
`dims-b` exactly. Used by array_cat for the asymmetric N-D || (N-1)-D
and (N-1)-D || N-D cases (`array_userfuncs.c:471–479`).
raw docstring

member?clj

(member? a x)

PG x = ANY(arr) semantics with 3-valued logic. Operates on flattened leaves so multi-dim arrays match anywhere: ARRAY[[1,2],[3,4]] = ANY(…) is true if any leaf equals x.

  • returns true if any leaf = x
  • returns false if no leaf = x AND no NULL leaves
  • returns nil (UNKNOWN) if x isn't matched but NULL leaves exist (a NULL leaf could match any x)
PG `x = ANY(arr)` semantics with 3-valued logic. Operates on
flattened leaves so multi-dim arrays match anywhere:
  ARRAY[[1,2],[3,4]] = ANY(…) is true if any leaf equals x.
- returns true if any leaf = x
- returns false if no leaf = x AND no NULL leaves
- returns nil (UNKNOWN) if x isn't matched but NULL leaves exist
  (a NULL leaf could match any x)
raw docstring

multidim?clj

(multidim? a)

True if the array has more than one dimension. Several PG functions (array_append, array_prepend, array_position, array_remove) explicitly reject multi-dim arrays; callers raise the matching feature_not_supported error in that case.

True if the array has more than one dimension. Several PG functions
(array_append, array_prepend, array_position, array_remove)
explicitly reject multi-dim arrays; callers raise the matching
feature_not_supported error in that case.
raw docstring

ndimclj

(ndim a)

Number of dimensions. 1 for the 1-D default; more for nested arrays.

Number of dimensions. 1 for the 1-D default; more for nested arrays.
raw docstring

overlap?clj

(overlap? a b)

PG a && b: any leaf of a is a leaf of b (NULLs ignored). Operates on flattened leaves.

PG `a && b`: any leaf of a is a leaf of b (NULLs ignored).
Operates on flattened leaves.
raw docstring

replace-leavesclj

(replace-leaves a f)

Walk every leaf of a's nested elements, applying f to each leaf value. Returns a new PgArray with the same shape, dims, and lbounds. Used by array_replace, which PG applies to all leaves regardless of dimensionality (arrayfuncs.c:6662). Descends into nested PgArrays as well as Clojure sequentials.

Walk every leaf of `a`'s nested elements, applying `f` to each
leaf value. Returns a new PgArray with the same shape, dims, and
lbounds. Used by `array_replace`, which PG applies to all leaves
regardless of dimensionality (`arrayfuncs.c:6662`). Descends into
nested PgArrays as well as Clojure sequentials.
raw docstring

sliceclj

(slice a lo hi)

PG array slice: arr[lo:hi]. 1-indexed, inclusive bounds, clamped to [lbound, lbound+length-1]. Returns a PgArray (possibly empty) preserving elem-type. nil bounds → PG default (lbound / lbound+len-1).

Slicing operates on the outermost dimension only; inner shape and lbounds are preserved. Multi-dim aware.

PG array slice: `arr[lo:hi]`. 1-indexed, inclusive bounds, clamped
to `[lbound, lbound+length-1]`. Returns a PgArray (possibly empty)
preserving elem-type. nil bounds → PG default (lbound / lbound+len-1).

Slicing operates on the outermost dimension only; inner shape and
lbounds are preserved. Multi-dim aware.
raw docstring

subscriptclj

(subscript a n)

PG array subscript: arr[n]. 1-indexed (offset by lbound), out-of-range or nil index returns nil (SQL NULL) — never throws.

For multi-dim arrays, returns the nth sub-array (still a PgArray with rank reduced by 1) so caller can chain (subscript (subscript m 1) 2) for m[1][2]. Matches PG: arr[i] on a 2-D yields a 1-D row, arr[i][j] yields a scalar.

PG array subscript: `arr[n]`. 1-indexed (offset by lbound),
out-of-range or nil index returns nil (SQL NULL) — never throws.

For multi-dim arrays, returns the nth sub-array (still a PgArray
with rank reduced by 1) so caller can chain `(subscript (subscript
m 1) 2)` for `m[1][2]`. Matches PG: `arr[i]` on a 2-D yields a
1-D row, `arr[i][j]` yields a scalar.
raw docstring

to-pg-textclj

(to-pg-text a)

Render a PgArray to PG's canonical text format: {e1,e2,...} for 1-D, nested {{…},{…}} for multi-dim. Emits [lo1:hi1][lo2:hi2]…= prefix when any lower bound != 1.

Used by the wire layer's value->string for any PgArray value.

Render a PgArray to PG's canonical text format: `{e1,e2,...}` for
1-D, nested `{{…},{…}}` for multi-dim. Emits `[lo1:hi1][lo2:hi2]…=`
prefix when any lower bound != 1.

Used by the wire layer's value->string for any PgArray value.
raw docstring

uboundclj

(ubound a d)

Upper bound for dimension d (1-indexed). (lbound a d) + (length-d a d) - 1, or nil if d out of range.

Upper bound for dimension `d` (1-indexed). `(lbound a d) + (length-d
a d) - 1`, or nil if d out of range.
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