SQL → Clojure function wrappers.
Every named function the translator can emit at query time lives
here, behind a stable (fully-qualified) symbol that Datahike's
resolve-fn looks up at execute time:
Aggregate wrappers (filter-sum / filter-avg / …) — variants of
the core Datahike aggregates that skip the :__null__ sentinel and
treat nil as SQL NULL. Needed because core's sum/avg throw on
keyword arithmetic and min/max mis-order keyword vs number.
null-safe — wraps a scalar fn so either-operand-is-NULL returns
NULL. Used to adapt Clojure string/math fns (upper, length,
arithmetic) to SQL 3-valued logic.
SQL string fns (sql-lpad, sql-position, …) — thin wrappers
with standard SQL semantics (1-based positions, padding behavior).
PG-catalog-function stubs (pg-table-is-visible, pg-format-type,
pg-get-expr) — minimum viable to make JDBC drivers and ORMs
that probe the catalog not trip over missing functions.
Lookup tables:
sql-aggregate->datalog — SQL agg name → fully-qualified
symbol. Emitted symbol resolves via
datahike.pg.sql/filter-* which re-exports from this ns.sql-fn->clj-fn — SQL fn name → actual IFn value. Used by
translate-function-call at emit time to wrap in null-safe.Runtime symbols re-exported from datahike.pg.sql so the
translator's emitted forms keep the old qualified path
('datahike.pg.sql/filter-count, 'datahike.pg.sql/sql-+, …)
for backward compat with already-prepared statements cached on
clients.
SQL → Clojure function wrappers.
Every named function the translator can emit at query time lives
here, behind a stable (fully-qualified) symbol that Datahike's
`resolve-fn` looks up at execute time:
- Aggregate wrappers (`filter-sum` / `filter-avg` / …) — variants of
the core Datahike aggregates that skip the `:__null__` sentinel and
treat nil as SQL NULL. Needed because core's `sum`/`avg` throw on
keyword arithmetic and `min`/`max` mis-order keyword vs number.
- `null-safe` — wraps a scalar fn so either-operand-is-NULL returns
NULL. Used to adapt Clojure string/math fns (upper, length,
arithmetic) to SQL 3-valued logic.
- SQL string fns (`sql-lpad`, `sql-position`, …) — thin wrappers
with standard SQL semantics (1-based positions, padding behavior).
- PG-catalog-function stubs (`pg-table-is-visible`, `pg-format-type`,
`pg-get-expr`) — minimum viable to make JDBC drivers and ORMs
that probe the catalog not trip over missing functions.
- Lookup tables:
* `sql-aggregate->datalog` — SQL agg name → fully-qualified
symbol. Emitted symbol resolves via
`datahike.pg.sql/filter-*` which re-exports from this ns.
* `sql-fn->clj-fn` — SQL fn name → actual IFn value. Used by
`translate-function-call` at emit time to wrap in `null-safe`.
Runtime symbols re-exported from `datahike.pg.sql` so the
translator's emitted forms keep the old qualified path
(`'datahike.pg.sql/filter-count`, `'datahike.pg.sql/sql-+`, …)
for backward compat with already-prepared statements cached on
clients.(aggregate-function? fname)(filter-array-agg coll)SQL array_agg(col) — collect all non-NULL values into a PgArray.
Element-type inferred from the first non-nil element; falls back
to :text when the input is empty (PG would return NULL; we follow
that by returning :__null__).
Requires datahike.pg.arrays which lives below this ns on the load order — use requiring-resolve at call time to avoid a cycle.
SQL array_agg(col) — collect all non-NULL values into a PgArray. Element-type inferred from the first non-nil element; falls back to :text when the input is empty (PG would return NULL; we follow that by returning `:__null__`). Requires datahike.pg.arrays which lives below this ns on the load order — use requiring-resolve at call time to avoid a cycle.
(filter-avg coll)AVG that ignores :null sentinel values. Returns :null if all filtered.
Returns Double — used for AVG(float4) / AVG(float8). For AVG(int*)
/ AVG(numeric) the translator picks filter-avg-numeric which
preserves precision via BigDecimal.
AVG that ignores :__null__ sentinel values. Returns :__null__ if all filtered. Returns Double — used for AVG(float4) / AVG(float8). For AVG(int*) / AVG(numeric) the translator picks `filter-avg-numeric` which preserves precision via BigDecimal.
(filter-avg-numeric coll)AVG with BigDecimal precision. Matches PG's AVG(int*)→numeric and
AVG(numeric)→numeric. Scale tracks PG's select_div_scale: at
least 16 significant digits, no less than the input column's
scale, and adjusted down for sums whose magnitude already takes
most of the available digits.
Concretely: AVG(int) on small values → 16 fractional digits (same as PG); AVG(NUMERIC(p, 2)) → max(16, 2) = 16 digits; AVG of a sum with weight 4+ digits in the integer part → fewer fractional digits, mirroring PG's precision-economy rule.
Skips nil and :__null__ sentinels.
AVG with BigDecimal precision. Matches PG's AVG(int*)→numeric and AVG(numeric)→numeric. Scale tracks PG's `select_div_scale`: at least 16 significant digits, no less than the input column's scale, and adjusted down for sums whose magnitude already takes most of the available digits. Concretely: AVG(int) on small values → 16 fractional digits (same as PG); AVG(NUMERIC(p, 2)) → max(16, 2) = 16 digits; AVG of a sum with weight 4+ digits in the integer part → fewer fractional digits, mirroring PG's precision-economy rule. Skips nil and `:__null__` sentinels.
(filter-corr pairs)SQL CORR(y, x) — Pearson correlation. Input is a collection of [x y] pairs (as produced by translate-select for two-arg CORR). Pairs where either element is :null/nil are dropped. Returns :null when fewer than 2 pairs remain or the denominator is zero (one side is a constant).
SQL CORR(y, x) — Pearson correlation. Input is a collection of [x y] pairs (as produced by translate-select for two-arg CORR). Pairs where either element is :__null__/nil are dropped. Returns :__null__ when fewer than 2 pairs remain or the denominator is zero (one side is a constant).
(filter-count coll)SQL COUNT(col) — counts non-NULL values. Unlike COUNT(*), which counts all rows, COUNT(col) skips rows where col IS NULL. Returns a long (never NULL — COUNT of empty is 0).
SQL COUNT(col) — counts non-NULL values. Unlike COUNT(*), which counts all rows, COUNT(col) skips rows where col IS NULL. Returns a long (never NULL — COUNT of empty is 0).
(filter-count-distinct coll)SQL COUNT(DISTINCT col) — counts distinct non-NULL values.
SQL COUNT(DISTINCT col) — counts distinct non-NULL values.
(filter-max coll)MAX that ignores :null sentinel values. Returns :null if all filtered.
MAX that ignores :__null__ sentinel values. Returns :__null__ if all filtered.
(filter-min coll)MIN that ignores :null sentinel values. Returns :null if all filtered.
MIN that ignores :__null__ sentinel values. Returns :__null__ if all filtered.
(filter-mode coll)PG MODE() WITHIN GROUP (ORDER BY x) — most frequent value.
Receives raw x values (no percentile parameter). Tie-broken by
ORDER BY ascending, matching PG's stable-sort tiebreak.
PG `MODE() WITHIN GROUP (ORDER BY x)` — most frequent value. Receives raw x values (no percentile parameter). Tie-broken by ORDER BY ascending, matching PG's stable-sort tiebreak.
(filter-percentile-cont coll)PG PERCENTILE_CONT(p) WITHIN GROUP (ORDER BY x) — linearly-
interpolated continuous percentile. Receives a coll of [p x] pairs
(every p is the same constant, threaded per-row by the translator
so the aggregate fn can stay single-arg per Datahike's aggregate
contract). Returns the interpolated p-th percentile of the x values,
:__null__ for an empty input.
PG `PERCENTILE_CONT(p) WITHIN GROUP (ORDER BY x)` — linearly- interpolated continuous percentile. Receives a coll of `[p x]` pairs (every `p` is the same constant, threaded per-row by the translator so the aggregate fn can stay single-arg per Datahike's aggregate contract). Returns the interpolated p-th percentile of the x values, `:__null__` for an empty input.
(filter-percentile-disc coll)PG PERCENTILE_DISC(p) WITHIN GROUP (ORDER BY x) — discrete
percentile, no interpolation. Returns the value at position
ceil(p * n) (1-based) in the sorted non-null x values.
PG `PERCENTILE_DISC(p) WITHIN GROUP (ORDER BY x)` — discrete percentile, no interpolation. Returns the value at position `ceil(p * n)` (1-based) in the sorted non-null x values.
(filter-stddev-samp coll)SQL STDDEV_SAMP(x) — sample standard deviation. See filter-variance-samp.
SQL STDDEV_SAMP(x) — sample standard deviation. See filter-variance-samp.
(filter-sum coll)SUM that ignores :null sentinel values. Returns :null if all filtered.
Uses Clojure's auto-promoting + so int8 inputs that overflow
silently become BigInt — filter-sum-numeric is the variant the
translator picks for SUM(int8) / SUM(numeric) where the result OID
is NUMERIC; this one stays for SUM(int4) / SUM(float*).
SUM that ignores :__null__ sentinel values. Returns :__null__ if all filtered. Uses Clojure's auto-promoting `+` so int8 inputs that overflow silently become BigInt — `filter-sum-numeric` is the variant the translator picks for SUM(int8) / SUM(numeric) where the result OID is NUMERIC; this one stays for SUM(int4) / SUM(float*).
(filter-sum-numeric coll)SUM with explicit BigDecimal accumulation. PG returns NUMERIC for
SUM(int8) and SUM(numeric) to avoid overflow; this variant matches
that. Coerces inputs to BigDecimal once at the boundary so
+ stays primitive across the reduce. Skips nil and :__null__
sentinels.
SUM with explicit BigDecimal accumulation. PG returns NUMERIC for SUM(int8) and SUM(numeric) to avoid overflow; this variant matches that. Coerces inputs to BigDecimal once at the boundary so `+` stays primitive across the reduce. Skips nil and `:__null__` sentinels.
(filter-variance-samp coll)SQL VAR_SAMP(x) — sample variance, ignores :null/nil. Returns :null when fewer than 2 non-null values remain (matches PG).
SQL VAR_SAMP(x) — sample variance, ignores :__null__/nil. Returns :__null__ when fewer than 2 non-null values remain (matches PG).
(null-safe f)Wrap a scalar function f to propagate SQL NULL: if any argument is the
:__null__ sentinel (or Clojure nil), return :__null__ without calling
f. Otherwise apply f to the arguments.
Used to make scalar SQL functions (upper, lower, substring, length, abs,
arithmetic, ...) match SQL semantics: UPPER(NULL) = NULL, LENGTH(NULL) = NULL, 1 + NULL = NULL. Without this guard, Clojure string/numeric
functions throw on :__null__ (a Keyword, not a String/Number).
Wrap a scalar function `f` to propagate SQL NULL: if any argument is the `:__null__` sentinel (or Clojure nil), return `:__null__` without calling `f`. Otherwise apply `f` to the arguments. Used to make scalar SQL functions (upper, lower, substring, length, abs, arithmetic, ...) match SQL semantics: `UPPER(NULL) = NULL`, `LENGTH(NULL) = NULL`, `1 + NULL = NULL`. Without this guard, Clojure string/numeric functions throw on `:__null__` (a Keyword, not a String/Number).
(pg-format-type type-oid _typmod)Convert a type OID + type modifier to a type name string. Delegates to the centralized type registry.
Convert a type OID + type modifier to a type name string. Delegates to the centralized type registry.
(pg-get-expr expr-text _relation-oid)Return the expression text as-is (CockroachDB's approach).
Return the expression text as-is (CockroachDB's approach).
(pg-many-ref-array db source-eid ref-attr target-pk-attr)Per-row Datalog fn for :db.cardinality/many :db.type/ref SQL
projection: given the source entity-id, fetch all values of
ref-attr (each is a target entity-id), look up target-pk-attr
on each, and return a PgArray of the resulting PK values.
Empty for source entities with no ref values — matches what a
real PG int[] column would render for a row that has no
elements. Avoids the Datalog array_agg + or-join dance because
it runs per-row in pure Clojure: the source entity is already
bound, so we just do two lookups and box.
Used as [(?pg-many-ref-array $ ?source-eid :order/tags :tag/id) ?out]
in the translator-emitted Datalog query.
Per-row Datalog fn for `:db.cardinality/many :db.type/ref` SQL projection: given the source entity-id, fetch all values of `ref-attr` (each is a target entity-id), look up `target-pk-attr` on each, and return a PgArray of the resulting PK values. Empty for source entities with no ref values — matches what a real PG `int[]` column would render for a row that has no elements. Avoids the Datalog `array_agg` + or-join dance because it runs per-row in pure Clojure: the source entity is already bound, so we just do two lookups and box. Used as `[(?pg-many-ref-array $ ?source-eid :order/tags :tag/id) ?out]` in the translator-emitted Datalog query.
(pg-size-pretty bytes)Format a byte count as PG's pretty string ('1024 bytes', '12 kB',
'5 MB'). Mirrors pg_size_pretty in src/backend/utils/adt/dbsize.c.
Format a byte count as PG's pretty string ('1024 bytes', '12 kB',
'5 MB'). Mirrors `pg_size_pretty` in src/backend/utils/adt/dbsize.c.(pg-table-is-visible _oid)Stub: always returns true (all tables are visible in the default schema).
Stub: always returns true (all tables are visible in the default schema).
Map SQL aggregate function names (lowercased) to Datalog aggregate
symbols. SUM/AVG/MIN/MAX route to our filter-* variants so they
skip the :__null__ sentinel that col-var! emits for missing
attribute values — Datahike's raw sum/avg would throw trying
(+ :__null__ 0), and raw min/max would mis-order a keyword
against a number.
COUNT(*) is handled specially in translate-select (counts entities,
always produces a long). COUNT(col) / COUNT(DISTINCT col) route to
filter-count / filter-count-distinct which skip NULLs per SQL
spec (PG: 'count(expression) returns the number of non-null input
rows').
Map SQL aggregate function names (lowercased) to Datalog aggregate symbols. SUM/AVG/MIN/MAX route to our `filter-*` variants so they skip the `:__null__` sentinel that col-var! emits for missing attribute values — Datahike's raw `sum`/`avg` would throw trying `(+ :__null__ 0)`, and raw `min`/`max` would mis-order a keyword against a number. COUNT(*) is handled specially in translate-select (counts entities, always produces a long). COUNT(col) / COUNT(DISTINCT col) route to `filter-count` / `filter-count-distinct` which skip NULLs per SQL spec (PG: 'count(expression) returns the number of non-null input rows').
Map of SQL function names (lowercased) to Clojure fn values.
Values are actual IFn objects (not symbols) so we can wrap them in
null-safe at emit time. Java static methods are wrapped in thin fns
so they're callable through the same path.
Map of SQL function names (lowercased) to Clojure fn values. Values are actual `IFn` objects (not symbols) so we can wrap them in `null-safe` at emit time. Java static methods are wrapped in thin fns so they're callable through the same path.
(sql-initcap s)Capitalize first letter of each word.
Capitalize first letter of each word.
(sql-left s n)Return first n characters of string.
Return first n characters of string.
(sql-lpad s n)(sql-lpad s n fill)Left-pad string s to length n with fill character/string.
Left-pad string s to length n with fill character/string.
(sql-position substring string)Return 1-based position of substring in string, 0 if not found.
Return 1-based position of substring in string, 0 if not found.
(sql-right s n)Return last n characters of string.
Return last n characters of string.
(sql-rpad s n)(sql-rpad s n fill)Right-pad string s to length n with fill character/string.
Right-pad string s to length n with fill character/string.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |