SQL:2011 SELECT-side temporal clause preprocessor.
Recognises FOR <AXIS> <spec> / FOR ALL <AXIS> clauses on SELECT
statements, strips them from the SQL string, and returns a
side-channel override map the handler threads into apply-temporal
for THIS statement only — equivalent to a per-statement SET datahike.{valid_at,system_at} = … that auto-resets after the query.
Two axes supported:
VALID_TIME — the application-domain time axis. Routed through
d/valid-at / d/valid-between (vt-aware secondary index when
present; predicate fallback otherwise).
FOR VALID_TIME AS OF <expr> → {:valid-at <Date>}FOR VALID_TIME BETWEEN <a> AND <b> → {:valid-between [a b]}FOR VALID_TIME FROM <a> TO <b> → {:valid-between [a b]}FOR ALL VALID_TIME (or FOR VALID_TIME ALL) → {:valid-at :all}SYSTEM_TIME — the transaction-time axis. Routed through d/as-of.
FOR SYSTEM_TIME AS OF <expr> → {:as-of <Date>}FOR ALL SYSTEM_TIME (or FOR SYSTEM_TIME ALL) → {:as-of :all}
BETWEEN / FROM-TO on SYSTEM_TIME is rejected — datahike's
d/as-of takes a single time-point; range tx-time reads would
need a primitive that doesn't currently exist.The two axes compose: SELECT … FROM t FOR SYSTEM_TIME AS OF '…' FOR VALID_TIME AS OF '…' produces {:as-of <Date> :valid-at <Date>}. apply-temporal wraps d/as-of first, then tags
:datahike/valid-at on the result — matching the composition
order documented on d/as-of.
:{valid-at,as-of} :all instructs apply-temporal to clear any
session-scoped marker on that axis for the duration of this query
— useful when the connection has SET datahike.{valid_at,as_of}
pinned and a single query wants the unfiltered view.
The preprocessor is char-based (not token-based) because it runs
BEFORE the main SQL tokenization + rewrite pipeline; it operates
on the raw SQL string so the downstream parser never sees the
non-standard FOR <AXIS> keywords.
SQL:2011 SELECT-side temporal clause preprocessor.
Recognises `FOR <AXIS> <spec>` / `FOR ALL <AXIS>` clauses on SELECT
statements, strips them from the SQL string, and returns a
side-channel override map the handler threads into `apply-temporal`
for THIS statement only — equivalent to a per-statement `SET
datahike.{valid_at,system_at} = …` that auto-resets after the query.
Two axes supported:
VALID_TIME — the application-domain time axis. Routed through
`d/valid-at` / `d/valid-between` (vt-aware secondary index when
present; predicate fallback otherwise).
- `FOR VALID_TIME AS OF <expr>` → {:valid-at <Date>}
- `FOR VALID_TIME BETWEEN <a> AND <b>` → {:valid-between [a b]}
- `FOR VALID_TIME FROM <a> TO <b>` → {:valid-between [a b]}
- `FOR ALL VALID_TIME` (or `FOR VALID_TIME ALL`) → {:valid-at :all}
SYSTEM_TIME — the transaction-time axis. Routed through `d/as-of`.
- `FOR SYSTEM_TIME AS OF <expr>` → {:as-of <Date>}
- `FOR ALL SYSTEM_TIME` (or `FOR SYSTEM_TIME ALL`) → {:as-of :all}
BETWEEN / FROM-TO on SYSTEM_TIME is rejected — datahike's
`d/as-of` takes a single time-point; range tx-time reads would
need a primitive that doesn't currently exist.
The two axes compose: `SELECT … FROM t FOR SYSTEM_TIME AS OF '…'
FOR VALID_TIME AS OF '…'` produces `{:as-of <Date> :valid-at
<Date>}`. `apply-temporal` wraps `d/as-of` first, then tags
`:datahike/valid-at` on the result — matching the composition
order documented on `d/as-of`.
`:{valid-at,as-of} :all` instructs `apply-temporal` to clear any
session-scoped marker on that axis for the duration of this query
— useful when the connection has `SET datahike.{valid_at,as_of}`
pinned and a single query wants the unfiltered view.
The preprocessor is char-based (not token-based) because it runs
BEFORE the main SQL tokenization + rewrite pipeline; it operates
on the raw SQL string so the downstream parser never sees the
non-standard `FOR <AXIS>` keywords.(parse-temporal-literal expr-str)Parse a temporal expression substring into a java.util.Date.
Accepts:
MAX_VALUE → Long/MAX_VALUE sentinelMIN_VALUE → Long/MIN_VALUE sentinelReturns either java.util.Date or one of the Long sentinels. Throws ex-info on unparseable input.
Parse a temporal expression substring into a java.util.Date. Accepts: - ISO instants: '2024-04-15T00:00:00Z', '2024-04-15T00:00:00.000Z' - ISO date-only: '2024-04-15' → 2024-04-15T00:00:00Z - millis since epoch: 1713139200000 - the bare keyword `MAX_VALUE` → Long/MAX_VALUE sentinel - the bare keyword `MIN_VALUE` → Long/MIN_VALUE sentinel Returns either java.util.Date or one of the Long sentinels. Throws ex-info on unparseable input.
(preprocess sql)Strip every FOR VALID_TIME / FOR SYSTEM_TIME clause from sql.
Returns {:sql <stripped-sql> :override <map-or-nil>}.
The override map can carry any combination of:
:valid-at <Date> — VALID_TIME AS OF
:valid-between [<Date> <Date>] — VALID_TIME BETWEEN / FROM-TO
:valid-at :all — FOR ALL VALID_TIME (clears any
session-scoped pin for this stmt)
:as-of <Date> — SYSTEM_TIME AS OF
:as-of :all — FOR ALL SYSTEM_TIME
nil when no clause is present.
Multiple FOR-clauses on the SAME axis (e.g. two FOR VALID_TIMEs
for two joined tables) is rejected — the per-statement override
applies one pin to the whole query. Use explicit per-column
predicates (<table>._valid_from/._valid_to) for the
multi-table case, or split into separate queries.
Mixing the two axes in one statement is supported: FOR SYSTEM_TIME AS OF '…' FOR VALID_TIME AS OF '…' produces
{:as-of <Date> :valid-at <Date>}.
Strip every `FOR VALID_TIME` / `FOR SYSTEM_TIME` clause from `sql`.
Returns `{:sql <stripped-sql> :override <map-or-nil>}`.
The override map can carry any combination of:
`:valid-at <Date>` — VALID_TIME AS OF
`:valid-between [<Date> <Date>]` — VALID_TIME BETWEEN / FROM-TO
`:valid-at :all` — FOR ALL VALID_TIME (clears any
session-scoped pin for this stmt)
`:as-of <Date>` — SYSTEM_TIME AS OF
`:as-of :all` — FOR ALL SYSTEM_TIME
`nil` when no clause is present.
Multiple FOR-clauses on the SAME axis (e.g. two `FOR VALID_TIME`s
for two joined tables) is rejected — the per-statement override
applies one pin to the whole query. Use explicit per-column
predicates (`<table>._valid_from`/`._valid_to`) for the
multi-table case, or split into separate queries.
Mixing the two axes in one statement is supported: `FOR
SYSTEM_TIME AS OF '…' FOR VALID_TIME AS OF '…'` produces
`{:as-of <Date> :valid-at <Date>}`.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 |