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

and-bitsclj

(and-bits a b)

& — bitwise AND of two equal-width bit strings.

`&` — bitwise AND of two equal-width bit strings.
sourceraw docstring

bit-string-literal-valueclj

(bit-string-literal-value expr)

The PgBit for a literal accepted by bit-string-literal?.

Both spellings produce type bit, not bit varying: PG's grammar builds a BitString constant that bit_in types as bit, so the width is exactly what was written. Hex expands to four bits per digit, leading zeros included — X'4A' is the 8-bit 01001010.

The PgBit for a literal accepted by `bit-string-literal?`.

Both spellings produce type `bit`, not `bit varying`: PG's grammar
builds a BitString constant that `bit_in` types as bit, so the width
is exactly what was written. Hex expands to four bits per digit,
leading zeros included — `X'4A'` is the 8-bit `01001010`.
sourceraw docstring

bit-string-literal?clj

(bit-string-literal? expr)

True for a SQL bit-string literal — B'1001000' or X'4A'.

JSqlParser spells the two differently: B'…' is a StringValue carrying prefix "B", X'…' is a HexValue.

True for a SQL bit-string literal — `B'1001000'` or `X'4A'`.

JSqlParser spells the two differently: `B'…'` is a StringValue
carrying prefix "B", `X'…'` is a HexValue.
sourceraw 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

concat-bitsclj

(concat-bits a b)

|| on two bit strings — PG's bitcat (varbit.c:1180).

The result is always bit varying, whatever the inputs were: the widths add up, so no fixed-width type could describe it.

`||` on two bit strings — PG's `bitcat` (varbit.c:1180).

The result is always `bit varying`, whatever the inputs were: the
widths add up, so no fixed-width type could describe it.
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

not-bitsclj

(not-bits b)

~ — bitwise NOT. Width is preserved; the result is bit (see zipwith-bits on why never varbit).

`~` — bitwise NOT. Width is preserved; the result is `bit` (see
zipwith-bits on why never varbit).
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

or-bitsclj

(or-bits a b)

| — bitwise OR of two equal-width bit strings.

`|` — bitwise OR of two equal-width bit strings.
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

shift-bitsclj

(shift-bits b n)

<< / >> on a bit string — shift WITHIN the existing width, zero filling (varbit.c:1310). The result is the same width as the input, so B'1100' << 1 is 1000, not 11000. A shift at least as wide as the value yields all zeros. A negative distance shifts the other way, as PG's does.

`<<` / `>>` on a bit string — shift WITHIN the existing width, zero
filling (varbit.c:1310). The result is the same width as the input,
so `B'1100' << 1` is `1000`, not `11000`. A shift at least as wide as
the value yields all zeros. A negative distance shifts the other way,
as PG's does.
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

xor-bitsclj

(xor-bits a b)

# — bitwise XOR of two equal-width bit strings.

`#` — bitwise XOR of two equal-width bit strings.
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