postgres · API

postgres.text

postgres.text — the PostgreSQL text-format codec.

libpq hands back every result cell as text (PQgetvalue never returns binary unless the caller asked for binary-format results, which this tin does not). This module is the two-way bridge between that text and Mojo values: decode_* turns a column's text into a typed value given its OID; encode_* turns a Mojo value back into the text PQexecParams/COPY expect. Pure Mojo — no FFI, no libpq call, so it is usable and testable without a server.

Dates and timestamps decode to integers (days/microseconds since the Unix epoch, 1970-01-01) using the proleptic Gregorian calendar via Howard Hinnant's days_from_civil / civil_from_days — see http://howardhinnant.github.io/date_algorithms.html. numeric deliberately stays a String: coercing arbitrary-precision decimals to Float64 would silently lose precision, so callers that want a number parse it themselves. bytea decodes both text sub-formats libpq can emit — hex (the bytea_output=hex server default) and the legacy octal-escape format — so no PQunescapeBytea call is needed either.

Functions

oid_name

def oid_name(oid: UInt32) -> String

Return the PostgreSQL type name for a well-known OID, or "oid:<n>" for anything this tin does not special-case.

is_text_oid

def is_text_oid(oid: UInt32) -> Bool

True for OIDs whose natural Mojo representation is String — TEXT/VARCHAR/BPCHAR/UUID/JSON/JSONB, and NUMERIC (kept a String on purpose; see the module docstring).

decode_bool

def decode_bool(s: StringSpan) -> Bool

Decode bool text. The server always emits t/f; true/false are also accepted because COPY CSV round-trips can carry them.

encode_bool

def encode_bool(v: Bool) -> String

decode_int16

def decode_int16(s: StringSpan) -> Int16

decode_int32

def decode_int32(s: StringSpan) -> Int32

decode_int64

def decode_int64(s: StringSpan) -> Int64

encode_int16

def encode_int16(v: Int16) -> String

encode_int32

def encode_int32(v: Int32) -> String

encode_int64

def encode_int64(v: Int64) -> String

decode_float32

def decode_float32(s: StringSpan) -> Float32

atof already accepts PostgreSQL's NaN/Infinity/-Infinity spellings case-insensitively (and the inf/nan short forms), plus standard decimal/scientific notation, so this is a thin wrapper that narrows to Float32 and rewraps the error with the offending text.

decode_float64

def decode_float64(s: StringSpan) -> Float64

encode_float32

def encode_float32(v: Float32) -> String

encode_float64

def encode_float64(v: Float64) -> String

decode_bytea

def decode_bytea(s: StringSpan) -> List[UInt8]

Decode bytea text — either the \x-prefixed hex format (bytea_output=hex, the server default) or the legacy escape format (\\ for a literal backslash, \ooo three-octal-digit byte escapes, every other byte literal).

encode_bytea

def encode_bytea(data: Span[UInt8]) -> String

\x + lowercase hex — the format bytea_output=hex expects.

is_infinite

def is_infinite(s: StringSpan) -> Bool

True for the literal spellings PostgreSQL uses for the unbounded date/timestamp values, infinity and -infinity.

decode_date

def decode_date(s: StringSpan) -> Int32

Decode date text (YYYY-MM-DD, year may exceed 4 digits) to days since 1970-01-01. infinity/-infinity and a BC suffix raise — read Result.value()'s raw text for those instead of the epoch encoding.

decode_time

def decode_time(s: StringSpan) -> Int64

Decode time text (HH:MM:SS[.ffffff]) to microseconds since midnight.

decode_timestamp

def decode_timestamp(s: StringSpan) -> Int64

Decode naive timestamp text (YYYY-MM-DD HH:MM:SS[.ffffff], no zone) to microseconds since 1970-01-01 00:00:00.

decode_timestamptz

def decode_timestamptz(s: StringSpan) -> Int64

Decode zoned timestamptz text (YYYY-MM-DD HH:MM:SS[.ffffff] plus an offset +HH, +HH:MM, or +HH:MM:SS, either sign) to UTC microseconds since 1970-01-01 00:00:00.

encode_date

def encode_date(days: Int32) -> String

encode_time

def encode_time(micros: Int64) -> String

encode_timestamp

def encode_timestamp(micros: Int64) -> String

Always 6 fractional digits: YYYY-MM-DD HH:MM:SS.ffffff. Negative micros (dates before 1970) work because ///% are floor division/modulo.

encode_timestamptz

def encode_timestamptz(micros: Int64) -> String

Same as encode_timestamp, with a +00 suffix — micros is already UTC, so there is no original offset to restore.

decode_text

def decode_text(s: StringSpan) -> String

Identity decode, so a dispatch-by-OID table can call every decoder uniformly.

Aliases

comptime OID_BOOL = UInt32(16)
comptime OID_BYTEA = UInt32(17)
comptime OID_INT8 = UInt32(20)
comptime OID_INT2 = UInt32(21)
comptime OID_INT4 = UInt32(23)
comptime OID_TEXT = UInt32(25)
comptime OID_JSON = UInt32(114)
comptime OID_FLOAT4 = UInt32(700)
comptime OID_FLOAT8 = UInt32(701)
comptime OID_BPCHAR = UInt32(1042)
comptime OID_VARCHAR = UInt32(1043)
comptime OID_DATE = UInt32(1082)
comptime OID_TIME = UInt32(1083)
comptime OID_TIMESTAMP = UInt32(1114)
comptime OID_TIMESTAMPTZ = UInt32(1184)
comptime OID_NUMERIC = UInt32(1700)
comptime OID_UUID = UInt32(2950)
comptime OID_JSONB = UInt32(3802)