module CQL::Postgres::Types::Binary

Overview

PostgreSQL's binary wire format for values going to the server: bind parameters (chosen per parameter once the server has reported its types) and binary COPY. .encode returns nil when the pair of Crystal value and server type has no binary form here; the caller then sends text, which the server parses as it always did.

Binary is only produced where it means the same thing as the text form: an integer must fit the server's width, a Float32 is widened through its printed form, a Float64 is never narrowed, and a Time is cut to microseconds like its text form. Nothing here puts a value into an error.

Defined in:

postgres/types/binary.cr
postgres/types/binary_decoder.cr

Constant Summary

ARRAY_ELEMENT = {OID::BOOL_ARRAY => OID::BOOL, OID::INT2_ARRAY => OID::INT2, OID::INT4_ARRAY => OID::INT4, OID::INT8_ARRAY => OID::INT8, OID::FLOAT4_ARRAY => OID::FLOAT4, OID::FLOAT8_ARRAY => OID::FLOAT8, OID::TEXT_ARRAY => OID::TEXT, OID::VARCHAR_ARRAY => OID::VARCHAR, OID::BPCHAR_ARRAY => OID::BPCHAR, OID::UUID_ARRAY => OID::UUID, OID::DATE_ARRAY => OID::DATE, OID::TIMESTAMP_ARRAY => OID::TIMESTAMP, OID::TIMESTAMPTZ_ARRAY => OID::TIMESTAMPTZ, OID::NUMERIC_ARRAY => OID::NUMERIC, OID::JSONB_ARRAY => OID::JSONB}
COCKROACHDB_TEXT_ONLY = [OID::FLOAT4, OID::NUMERIC, OID::FLOAT4_ARRAY, OID::NUMERIC_ARRAY]

What CockroachDB 24.3 reads differently from the text of the same value (checked against a live node): a float4 comes back widened to a float8 (0.1 as 0.10000000149011612), and a numeric loses its trailing zeros ("100000000" as 1E+8, "-0.00" as 0). They stay text there.

EPOCH_UNIX = (Time.utc(2000, 1, 1)).to_unix
NUMERIC_MAX_SCALE = 16383
NUMERIC_NEGATIVE = 16384_u16
NUMERIC_POSITIVE = 0_u16
TEXTUAL = [OID::TEXT, OID::VARCHAR, OID::BPCHAR, OID::NAME, OID::JSON]

Types whose binary form is their text, so a String goes in as it is.

Class Method Summary

Class Method Detail

def self.decode(oid : UInt32, bytes : Bytes) : Value #

One field of a binary COPY row. Types without a decoder here come back as the raw bytes the server sent.


[View source]
def self.encode(value : Bool, oid : UInt32) : Bytes | Nil #

[View source]
def self.encode(value : Int, oid : UInt32) : Bytes | Nil #

[View source]
def self.encode(value : Float32, oid : UInt32) : Bytes | Nil #

[View source]
def self.encode(value : Float64, oid : UInt32) : Bytes | Nil #

[View source]
def self.encode(value : UUID, oid : UInt32) : Bytes | Nil #

[View source]
def self.encode(value : Time, oid : UInt32) : Bytes | Nil #

[View source]
def self.encode(value : DecimalText, oid : UInt32) : Bytes | Nil #

[View source]
def self.encode(value : JSON::Any, oid : UInt32) : Bytes | Nil #

[View source]
def self.encode(value : String, oid : UInt32) : Bytes | Nil #

[View source]
def self.encode(value : Bytes, oid : UInt32) : Bytes | Nil #

[View source]
def self.encode(value : Array, oid : UInt32) : Bytes | Nil #

[View source]
def self.encode(value, oid : UInt32) : Bytes | Nil #

[View source]
def self.numeric(text : String) : Bytes | Nil #

numeric: base-10000 digits, the weight of the first digit group, a sign and the number of decimal digits after the point. Only plain decimals ("-12.50") are converted; NaN, infinities and exponent forms go as text.


[View source]
def self.numeric_text(bytes : Bytes) : String #

The decimal text of a binary numeric (see .numeric).


[View source]
def self.size_hint(value : Array) : Int32 #

A rough size of the value on the wire (the elements of an array added up).


[View source]
def self.size_hint(value : String | Bytes) : Int32 #

[View source]
def self.size_hint(value : DecimalText) : Int32 #

[View source]
def self.size_hint(value : JSON::Any) : Int32 #

[View source]
def self.size_hint(value) : Int32 #

Numbers, times and uuids: a bound that covers their text form (a time is 29 characters, a uuid 36, an Int128 up to 40), since that is what goes out when no binary form applies. Deliberately generous: an array of them splits a pipeline batch earlier than strictly needed, which costs a round trip, never a stall.


[View source]
def self.supported?(value : Bool | Int | Float | UUID | DecimalText | Time | JSON::Any | Array) : Bool #

The values that may wait for the server's parameter types.


[View source]
def self.supported?(value) : Bool #

[View source]