Liking cljdoc? Tell your friends :D

datahike.pg.interval.core

The interval CARRIER, and interval_out.

A deftype, deliberately, and not a defrecord. The consolidation plan warns that "a record's structural =/hash would split GROUP BY and joins", and that is true -- but it is a reason to choose the carrier's equality, not a reason to avoid a carrier. PostgreSQL compares '1 mon' and '30 days' as EQUAL (interval_cmp_value: a month is 30 days, a day is 24 hours) while PRINTING them differently, so:

structural equality splits two values PostgreSQL groups; canonical TEXT cannot be the key either, for the same reason.

clojure.core/= routes a non-collection, non-Number object to .equals, and clojure.core/hash routes a non-IHashEq, non-Number, non-String object to .hashCode. So implementing those two over interval_cmp_value makes the EXISTING machinery correct, including the parts no comparator can reach: GROUP BY is datahike's own group-by over the non-aggregate :find elements, and DISTINCT, clojure.set/intersection, contains? on a set and datahike's hash join are all clojure.core calls. None of them takes a comparator; all of them are served by .hashCode.

Comparable covers ORDER BY, the comparison operators, BETWEEN and min/max, through fns/order-cmp's existing :else (compare a b) -- so that function needs no interval branch at all. The same route bits.clj's PgBit takes.

THE SPAN NEEDS MORE THAN 64 BITS. month * 30 + day can reach 6.4e10 days, and multiplying that by 86,400,000,000 µs overflows int64 -- which is why the C uses INT128. compareTo therefore works in BigInteger. hashCode does NOT: interval_hash deliberately narrows the INT128 to its low 64 bits (int128_to_int64) before hashing, so two spans differing by exactly 2^64 µs hash together in PostgreSQL, and matching that is what keeps our hashing consistent with a real server's.

toString is NOT the SQL rendering. Output goes through types/->pg-text, which is the single funnel for ::text, array elements, record fields, COPY, pg_dump and to_jsonb.

The interval CARRIER, and `interval_out`.

A `deftype`, deliberately, and not a `defrecord`. The consolidation
plan warns that "a record's structural `=`/hash would split GROUP BY
and joins", and that is true -- but it is a reason to choose the
carrier's equality, not a reason to avoid a carrier. PostgreSQL
compares `'1 mon'` and `'30 days'` as EQUAL (`interval_cmp_value`:
a month is 30 days, a day is 24 hours) while PRINTING them
differently, so:

  structural equality splits two values PostgreSQL groups;
  canonical TEXT cannot be the key either, for the same reason.

`clojure.core/=` routes a non-collection, non-Number object to
`.equals`, and `clojure.core/hash` routes a non-`IHashEq`,
non-Number, non-String object to `.hashCode`. So implementing those
two over `interval_cmp_value` makes the EXISTING machinery correct,
including the parts no comparator can reach: `GROUP BY` is
datahike's own `group-by` over the non-aggregate `:find` elements,
and `DISTINCT`, `clojure.set/intersection`, `contains?` on a set and
datahike's hash join are all `clojure.core` calls. None of them
takes a comparator; all of them are served by `.hashCode`.

`Comparable` covers ORDER BY, the comparison operators, BETWEEN and
min/max, through `fns/order-cmp`'s existing `:else (compare a b)` --
so that function needs no interval branch at all. The same route
`bits.clj`'s `PgBit` takes.

THE SPAN NEEDS MORE THAN 64 BITS. `month * 30 + day` can reach
6.4e10 days, and multiplying that by 86,400,000,000 µs overflows
int64 -- which is why the C uses INT128. `compareTo` therefore works
in `BigInteger`. `hashCode` does NOT: `interval_hash` deliberately
narrows the INT128 to its low 64 bits (`int128_to_int64`) before
hashing, so two spans differing by exactly 2^64 µs hash together in
PostgreSQL, and matching that is what keeps our hashing consistent
with a real server's.

`toString` is NOT the SQL rendering. Output goes through
`types/->pg-text`, which is the single funnel for `::text`, array
elements, record fields, COPY, pg_dump and `to_jsonb`.
raw docstring

->pg-text-postgresclj

(->pg-text-postgres iv)

interval_out under IntervalStyle = postgres, which is the only style the server reports (show IntervalStyle answers postgres unconditionally today). The other three are in the backlog with the GUC.

`interval_out` under IntervalStyle = postgres, which is the only
style the server reports (`show IntervalStyle` answers `postgres`
unconditionally today). The other three are in the backlog with the
GUC.
sourceraw docstring

cmp-spanclj

(cmp-span months days micros)

interval_cmp_value (timestamp.c): the INT128 span, as a BigInteger. A month is 30 days and a day is 24 hours -- the equivalence that makes '1 mon' = '30 days'.

`interval_cmp_value` (timestamp.c): the INT128 span, as a
`BigInteger`. A month is 30 days and a day is 24 hours -- the
equivalence that makes `'1 mon' = '30 days'`.
sourceraw docstring

fieldsclj

(fields iv)

interval2itm (timestamp.c): the carrier as the seven output fields. The divisions are TRUNCATING, so a negative interval keeps each field's own sign -- which is what makes -1 days +02:03:04 printable at all.

`interval2itm` (timestamp.c): the carrier as the seven output
fields. The divisions are TRUNCATING, so a negative interval keeps
each field's own sign -- which is what makes `-1 days +02:03:04`
printable at all.
sourceraw docstring

intervalclj

(interval months days micros)

A carrier from the decoder's three fields.

A carrier from the decoder's three fields.
sourceraw docstring

interval-inclj

(interval-in s)
(interval-in s range)

interval_in. Text to a PgInterval, or the infinity sentinels.

THE FALLBACK ORDER IS EXACT and is the part worth getting right: ParseDateTime then DecodeInterval, and DecodeISO8601Interval is tried ONLY when that returned DTERR_BAD_FORMAT specifically -- not on an overflow. So an input the ordinary decoder rejects as out of range must NOT be retried as ISO, or '2147483648 months' would fall through and be refused with the wrong error.

And FIELD_OVERFLOW is REMAPPED to INTERVAL_OVERFLOW, SQLSTATE 22015 -- interval field value out of range -- not the 22008 the datetime types raise (timestamp.c:941-943).

`interval_in`. Text to a `PgInterval`, or the infinity sentinels.

THE FALLBACK ORDER IS EXACT and is the part worth getting right:
`ParseDateTime` then `DecodeInterval`, and `DecodeISO8601Interval`
is tried ONLY when that returned DTERR_BAD_FORMAT specifically --
not on an overflow. So an input the ordinary decoder rejects as out
of range must NOT be retried as ISO, or `'2147483648 months'` would
fall through and be refused with the wrong error.

And FIELD_OVERFLOW is REMAPPED to INTERVAL_OVERFLOW, SQLSTATE
22015 -- `interval field value out of range` -- not the 22008 the
datetime types raise (timestamp.c:941-943).
sourceraw docstring

interval?clj

(interval? v)
source

justify-daysclj

(justify-days iv)

interval_justify_days: whole months out of the day field, with the same sign correction.

`interval_justify_days`: whole months out of the day field, with the
same sign correction.
sourceraw docstring

justify-hoursclj

(justify-hours iv)

interval_justify_hours: whole days out of the time field, then a sign correction so day and time agree in sign.

`interval_justify_hours`: whole days out of the time field, then a
sign correction so day and time agree in sign.
sourceraw docstring

justify-intervalclj

(justify-interval iv)

interval_justify_interval. Not simply justify-days after justify-hours: the FIRST month extraction runs only when day and time already agree in sign, and the final sign correction looks at the time field too -- month > 0 && (day < 0 || (day == 0 && time < 0)). Composing the other two gives a different answer for a mixed interval.

`interval_justify_interval`. Not simply justify-days after
justify-hours: the FIRST month extraction runs only when day and
time already agree in sign, and the final sign correction looks at
the time field too -- `month > 0 && (day < 0 || (day == 0 && time <
0))`. Composing the other two gives a different answer for a mixed
interval.
sourceraw docstring

months-per-yearclj

source

usecs-per-dayclj

source

usecs-per-hourclj

source

usecs-per-minuteclj

source

usecs-per-secclj

source

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