One implementation of CAST(<value> AS <type>).
The same cast semantics used to be written out four times — in
sql.clj's table-free literal fast path, in expr.clj's
translate-cast, in stmt.clj's apply-sql-cast, and in
coerce.clj's INSERT path — each a case/cond over
types/cast-category that had drifted from the others. Which copy ran
depended on the SHAPE of the expression, not on its meaning, so the
same cast could behave three ways:
29::bit(4) → literal fast path → correct (-44)::bit(12) → translate-cast → passed through as -44 '101'::bit(3)::int → nested, another path → read the digits as decimal 101, not 5
Issue #12 hit exactly this for '1'::boolean, and issue #19 hit it
again for bit. Adding a branch to one copy fixes one shape.
This namespace holds the value-level semantics — (value, type) → value. Callers keep their own surrounding logic (when to fold at
translate time, how to bind a runtime var, how to read a JSqlParser
AST node); they just stop reimplementing what a cast MEANS.
parse-timestamp is injected rather than required because the parser
lives in expr.clj, which requires this namespace's dependencies —
taking it as an argument keeps this namespace a leaf and avoids a
load cycle.
One implementation of `CAST(<value> AS <type>)`.
The same cast semantics used to be written out four times — in
`sql.clj`'s table-free literal fast path, in `expr.clj`'s
`translate-cast`, in `stmt.clj`'s `apply-sql-cast`, and in
`coerce.clj`'s INSERT path — each a `case`/`cond` over
`types/cast-category` that had drifted from the others. Which copy ran
depended on the SHAPE of the expression, not on its meaning, so the
same cast could behave three ways:
29::bit(4) → literal fast path → correct
(-44)::bit(12) → translate-cast → passed through as -44
'101'::bit(3)::int → nested, another path → read the digits as
decimal 101, not 5
Issue #12 hit exactly this for `'1'::boolean`, and issue #19 hit it
again for bit. Adding a branch to one copy fixes one shape.
This namespace holds the value-level semantics — `(value, type) →
value`. Callers keep their own surrounding logic (when to fold at
translate time, how to bind a runtime var, how to read a JSqlParser
AST node); they just stop reimplementing what a cast MEANS.
`parse-timestamp` is injected rather than required because the parser
lives in `expr.clj`, which requires this namespace's dependencies —
taking it as an argument keeps this namespace a leaf and avoids a
load cycle.(cast-scalar v
type-str
{:keys [explicit? parse-timestamp resolve-regclass
prefer-local-datetime?]
:or {explicit? true}})Apply a SQL cast of v to the target named by type-str.
Options:
:explicit? — an explicit CAST reshapes silently; an assignment
raises instead (matters for bit width coercion).
:parse-timestamp — fn String → java.util.Date, from expr.clj.
:resolve-regclass— fn String → oid, for ::regclass.
:prefer-local-datetime? — return a LocalDateTime (microsecond
precision) rather than a Date for a timestamp
cast. See the :timestamp branch.
Returns v unchanged for a target this doesn't classify, which is
what every call site did before and keeps unknown types passing
through rather than erroring.
Apply a SQL cast of `v` to the target named by `type-str`.
Options:
:explicit? — an explicit CAST reshapes silently; an assignment
raises instead (matters for bit width coercion).
:parse-timestamp — fn String → java.util.Date, from expr.clj.
:resolve-regclass— fn String → oid, for `::regclass`.
:prefer-local-datetime? — return a LocalDateTime (microsecond
precision) rather than a Date for a timestamp
cast. See the :timestamp branch.
Returns `v` unchanged for a target this doesn't classify, which is
what every call site did before and keeps unknown types passing
through rather than erroring.(cast-to-bit v type-str explicit?)int / text / bit → bit(n) or bit varying(n).
An integer source keeps the RIGHTMOST n bits and sign-extends on the
left (varbit.c:1550), which is why (-44)::bit(12) is
111111010100 and not the digits of -44.
int / text / bit → bit(n) or bit varying(n). An integer source keeps the RIGHTMOST n bits and sign-extends on the left (varbit.c:1550), which is why `(-44)::bit(12)` is `111111010100` and not the digits of -44.
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 |