Liking cljdoc? Tell your friends :D

datahike.pg.bits

PostgreSQL BIT / BIT VARYING values.

Before this namespace a bit value was a bare java.lang.String of '0'/'1' characters. The digits were right, but nothing else was: the type reported as text (OID 25) rather than bit (1560), so pg_typeof(0::bit) answered text and clients that consult the RowDescription OID mapped the column wrong (issue #19).

A wrapper record — the same shape PgArray and PgRecord already use — carries the two things a string cannot:

  1. The WIDTH, which is part of the value. PG compares bit strings with a memcmp of the left-aligned bytes and then breaks ties on length (varbit.c:817), so B'101' and B'10100000' are NOT equal and B'0' < B'00' < B'000'. Any representation that trims or normalises the digits silently changes equality, ordering and index lookups.

  2. bit vs bit varying, which are distinct types (1560 / 1562) with different coercion rules: bit(n) zero-pads on the RIGHT to exactly n, bit varying(n) truncates but never pads.

The digit string stays the storage form because it is exactly PG's text output format (varbit.c:586 always emits bitlen '0'/'1' characters — never hex, never a B prefix), and because bits already encodes the width in its length.

Ordering note: comparing the digit strings lexicographically and then by length gives the same answer as PG's memcmp-then-length, because the zero pad PG compares against behaves like trailing '0' characters and the tie-break covers the proper-prefix case.

PostgreSQL BIT / BIT VARYING values.

Before this namespace a bit value was a bare `java.lang.String` of
'0'/'1' characters. The digits were right, but nothing else was: the
type reported as `text` (OID 25) rather than `bit` (1560), so
`pg_typeof(0::bit)` answered `text` and clients that consult the
RowDescription OID mapped the column wrong (issue #19).

A wrapper record — the same shape `PgArray` and `PgRecord` already
use — carries the two things a string cannot:

1. **The WIDTH, which is part of the value.** PG compares bit strings
   with a memcmp of the left-aligned bytes and then breaks ties on
   length (varbit.c:817), so `B'101'` and `B'10100000'` are NOT equal
   and `B'0' < B'00' < B'000'`. Any representation that trims or
   normalises the digits silently changes equality, ordering and
   index lookups.

2. **bit vs bit varying**, which are distinct types (1560 / 1562) with
   different coercion rules: `bit(n)` zero-pads on the RIGHT to
   exactly n, `bit varying(n)` truncates but never pads.

The digit string stays the storage form because it is exactly PG's
text output format (varbit.c:586 always emits `bitlen` '0'/'1'
characters — never hex, never a `B` prefix), and because `bits`
already encodes the width in its length.

Ordering note: comparing the digit strings lexicographically and then
by length gives the same answer as PG's memcmp-then-length, because
the zero pad PG compares against behaves like trailing '0' characters
and the tie-break covers the proper-prefix case.
raw docstring

coerce-widthclj

(coerce-width b n explicit?)

Apply a bit(n) / bit varying(n) width to a value.

bit zero-pads or truncates on the RIGHT to exactly n (varbit.c:390); bit varying truncates on the right but NEVER pads, so a shorter value passes through unchanged (varbit.c:751). Padding on the left, or padding a varbit, silently corrupts the value.

explicit? distinguishes a cast from an assignment: PG only reshapes silently for an explicit cast and otherwise raises 22026 / 22001.

Apply a `bit(n)` / `bit varying(n)` width to a value.

`bit` zero-pads or truncates on the RIGHT to exactly n (varbit.c:390);
`bit varying` truncates on the right but NEVER pads, so a shorter
value passes through unchanged (varbit.c:751). Padding on the left,
or padding a varbit, silently corrupts the value.

`explicit?` distinguishes a cast from an assignment: PG only reshapes
silently for an explicit cast and otherwise raises 22026 / 22001.
sourceraw docstring

compare-bitsclj

(compare-bits a b)

PG's bit_cmp ordering: content first, then width.

PG's bit_cmp ordering: content first, then width.
sourceraw docstring

from-integerclj

(from-integer v n)

PG's int -> bit(n): keep the RIGHTMOST n bits, sign-extending on the left when n exceeds the source width (varbit.c:1550).

29::bit(4) is 1101 — the low nibble — and (-44)::bit(12) is 111111010100. Rendering the integer's binary string and padding on the wrong end gives wrong bits for every negative value. This never errors; high bits are silently discarded.

PG's `int -> bit(n)`: keep the RIGHTMOST n bits, sign-extending on the
left when n exceeds the source width (varbit.c:1550).

`29::bit(4)` is `1101` — the low nibble — and `(-44)::bit(12)` is
`111111010100`. Rendering the integer's binary string and padding on
the wrong end gives wrong bits for every negative value. This never
errors; high bits are silently discarded.
sourceraw docstring

make-bitclj

(make-bit bits)
(make-bit bits varying?)

Construct a bit-string value from a '0'/'1' digit string.

Construct a bit-string value from a '0'/'1' digit string.
sourceraw docstring

octet-lengthclj

(octet-length b)

PG's octet_length on a bit string: ceil(width / 8).

PG's `octet_length` on a bit string: ceil(width / 8).
sourceraw docstring

parse-bit-literalclj

(parse-bit-literal s)
(parse-bit-literal s varying?)

Parse the text form of a bit value.

Accepts what bit_in accepts (varbit.c:165): a b/B prefix, an x/X prefix for hex, or a bare digit run. Hex expands to exactly FOUR bits per digit including leading zeros — X'1F' is the 8-bit value 00011111, not 5 bits — which is the detail a text-backed implementation gets wrong (it changes length(), octet_length() and the sort position).

Raises 22P02 with PG's wording on a bad character.

Parse the text form of a bit value.

Accepts what `bit_in` accepts (varbit.c:165): a `b`/`B` prefix, an
`x`/`X` prefix for hex, or a bare digit run. Hex expands to exactly
FOUR bits per digit including leading zeros — `X'1F'` is the 8-bit
value `00011111`, not 5 bits — which is the detail a text-backed
implementation gets wrong (it changes `length()`, `octet_length()`
and the sort position).

Raises 22P02 with PG's wording on a bad character.
sourceraw docstring

pg-bit?clj

(pg-bit? v)

True iff v is a PgBit.

True iff v is a PgBit.
sourceraw docstring

to-longclj

(to-long b)

PG's bit -> int8: a REINTERPRETATION of the bits, not a range check. 32 one-bits cast to int4 give -1, not 4294967295 (varbit.c:1598). Only the width is validated.

PG's `bit -> int8`: a REINTERPRETATION of the bits, not a range check.
32 one-bits cast to int4 give -1, not 4294967295 (varbit.c:1598).
Only the width is validated.
sourceraw docstring

to-pg-textclj

(to-pg-text b)

PG text output: the digit run itself, exactly width characters.

PG text output: the digit run itself, exactly `width` characters.
sourceraw docstring

widthclj

(width b)

Number of bits — PG's length() / bit_length().

Number of bits — PG's `length()` / `bit_length()`.
sourceraw 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