// PostgreSQL type descriptors used by encoding, decoding, and catalog lookups.
///|
/// Classifies the structural shape of a PostgreSQL type.
///
/// Most user-facing codecs only care whether a type is a simple scalar or an
/// array, but the richer variants let the client cache enough metadata for
/// advanced introspection and future extension points.
pub enum Kind {
/// A plain scalar type such as `int4` or `timestamp`.
Simple
/// An array type whose element type is identified by OID.
Array(@proto.Oid)
/// An enum type with the full ordered label set cached locally.
Enum(Array[String])
/// A composite/record-like type with named fields.
Composite(Array[Field])
/// A domain that wraps another base type.
Domain(@proto.Oid)
/// A range type whose subtype is identified by OID.
Range(@proto.Oid)
/// A pseudo type such as `void`.
Pseudo
/// A placeholder used when only the OID is known.
Unknown
} derive(Debug, Eq)
///|
/// Field descriptor stored inside `Kind::Composite`.
pub struct Field {
/// Field name as reported by PostgreSQL system catalogs.
name : String
/// OID of the field type.
type_oid : @proto.Oid
} derive(Debug, Eq)
///|
/// Stable description of a PostgreSQL type known to the client.
///
/// Built-in descriptors are created eagerly for common scalar and array types.
/// Less common server-defined types are resolved lazily through catalog queries
/// and then cached in the shared client state.
pub struct Type {
/// Numeric PostgreSQL object identifier.
oid : @proto.Oid
/// Server-visible type name, such as `"int4"` or `"_uuid"`.
name : String
/// Structural classification used by higher-level logic.
kind : Kind
} derive(Debug, Eq)
///|
/// Return the built-in PostgreSQL `bool` type descriptor.
pub fn Type::bool() -> Type {
{ oid: BOOL_OID, name: "bool", kind: Simple, }
}
///|
/// Return the built-in PostgreSQL `bytea` type descriptor.
pub fn Type::bytea() -> Type {
{ oid: BYTEA_OID, name: "bytea", kind: Simple, }
}
///|
/// Return the built-in PostgreSQL `char` type descriptor.
pub fn Type::char() -> Type {
{ oid: CHAR_OID, name: "char", kind: Simple, }
}
///|
/// Return the built-in PostgreSQL `name` type descriptor.
pub fn Type::name_type() -> Type {
{ oid: NAME_OID, name: "name", kind: Simple, }
}
///|
/// Return the built-in PostgreSQL `int8` type descriptor.
pub fn Type::int8() -> Type {
{ oid: INT8_OID, name: "int8", kind: Simple, }
}
///|
/// Return the built-in PostgreSQL `int2` type descriptor.
pub fn Type::int2() -> Type {
{ oid: INT2_OID, name: "int2", kind: Simple, }
}
///|
/// Return the built-in PostgreSQL `int4` type descriptor.
pub fn Type::int4() -> Type {
{ oid: INT4_OID, name: "int4", kind: Simple, }
}
///|
/// Return the built-in PostgreSQL `text` type descriptor.
pub fn Type::text() -> Type {
{ oid: TEXT_OID, name: "text", kind: Simple, }
}
///|
/// Return the built-in PostgreSQL `oid` type descriptor.
pub fn Type::oid_type() -> Type {
{ oid: OID_TYPE_OID, name: "oid", kind: Simple, }
}
///|
/// Return the built-in PostgreSQL `float4` type descriptor.
pub fn Type::float4() -> Type {
{ oid: FLOAT4_OID, name: "float4", kind: Simple, }
}
///|
/// Return the built-in PostgreSQL `float8` type descriptor.
pub fn Type::float8() -> Type {
{ oid: FLOAT8_OID, name: "float8", kind: Simple, }
}
///|
/// Return the built-in PostgreSQL `varchar` type descriptor.
pub fn Type::varchar() -> Type {
{ oid: VARCHAR_OID, name: "varchar", kind: Simple, }
}
///|
/// Return the built-in PostgreSQL `date` type descriptor.
pub fn Type::date() -> Type {
{ oid: DATE_OID, name: "date", kind: Simple, }
}
///|
/// Return the built-in PostgreSQL `time` type descriptor.
pub fn Type::time() -> Type {
{ oid: TIME_OID, name: "time", kind: Simple, }
}
///|
/// Return the built-in PostgreSQL `timestamp` type descriptor.
pub fn Type::timestamp() -> Type {
{ oid: TIMESTAMP_OID, name: "timestamp", kind: Simple, }
}
///|
/// Return the built-in PostgreSQL `timestamptz` type descriptor.
pub fn Type::timestamptz() -> Type {
{ oid: TIMESTAMPTZ_OID, name: "timestamptz", kind: Simple, }
}
///|
/// Return the built-in PostgreSQL `uuid` type descriptor.
pub fn Type::uuid() -> Type {
{ oid: UUID_OID, name: "uuid", kind: Simple, }
}
///|
/// Return the built-in PostgreSQL `json` type descriptor.
pub fn Type::json() -> Type {
{ oid: JSON_OID, name: "json", kind: Simple, }
}
///|
/// Return the built-in PostgreSQL `json[]` type descriptor.
pub fn Type::json_array() -> Type {
{ oid: JSON_ARRAY_OID, name: "_json", kind: Array(JSON_OID), }
}
///|
/// Return the built-in PostgreSQL `jsonb` type descriptor.
pub fn Type::jsonb() -> Type {
{ oid: JSONB_OID, name: "jsonb", kind: Simple, }
}
///|
/// Return the built-in PostgreSQL `jsonb[]` type descriptor.
pub fn Type::jsonb_array() -> Type {
{ oid: JSONB_ARRAY_OID, name: "_jsonb", kind: Array(JSONB_OID), }
}
///|
/// Return the built-in PostgreSQL `bool[]` type descriptor.
pub fn Type::bool_array() -> Type {
{ oid: BOOL_ARRAY_OID, name: "_bool", kind: Array(BOOL_OID), }
}
///|
/// Return the built-in PostgreSQL `bytea[]` type descriptor.
pub fn Type::bytea_array() -> Type {
{ oid: BYTEA_ARRAY_OID, name: "_bytea", kind: Array(BYTEA_OID), }
}
///|
/// Return the built-in PostgreSQL `int2[]` type descriptor.
pub fn Type::int2_array() -> Type {
{ oid: INT2_ARRAY_OID, name: "_int2", kind: Array(INT2_OID), }
}
///|
/// Return the built-in PostgreSQL `int4[]` type descriptor.
pub fn Type::int4_array() -> Type {
{ oid: INT4_ARRAY_OID, name: "_int4", kind: Array(INT4_OID), }
}
///|
/// Return the built-in PostgreSQL `text[]` type descriptor.
pub fn Type::text_array() -> Type {
{ oid: TEXT_ARRAY_OID, name: "_text", kind: Array(TEXT_OID), }
}
///|
/// Return the built-in PostgreSQL `varchar[]` type descriptor.
pub fn Type::varchar_array() -> Type {
{ oid: VARCHAR_ARRAY_OID, name: "_varchar", kind: Array(VARCHAR_OID), }
}
///|
/// Return the built-in PostgreSQL `int8[]` type descriptor.
pub fn Type::int8_array() -> Type {
{ oid: INT8_ARRAY_OID, name: "_int8", kind: Array(INT8_OID), }
}
///|
/// Return the built-in PostgreSQL `float4[]` type descriptor.
pub fn Type::float4_array() -> Type {
{ oid: FLOAT4_ARRAY_OID, name: "_float4", kind: Array(FLOAT4_OID), }
}
///|
/// Return the built-in PostgreSQL `float8[]` type descriptor.
pub fn Type::float8_array() -> Type {
{ oid: FLOAT8_ARRAY_OID, name: "_float8", kind: Array(FLOAT8_OID), }
}
///|
/// Return the built-in PostgreSQL `timestamp[]` type descriptor.
pub fn Type::timestamp_array() -> Type {
{ oid: TIMESTAMP_ARRAY_OID, name: "_timestamp", kind: Array(TIMESTAMP_OID), }
}
///|
/// Return the built-in PostgreSQL `date[]` type descriptor.
pub fn Type::date_array() -> Type {
{ oid: DATE_ARRAY_OID, name: "_date", kind: Array(DATE_OID), }
}
///|
/// Return the built-in PostgreSQL `uuid[]` type descriptor.
pub fn Type::uuid_array() -> Type {
{ oid: UUID_ARRAY_OID, name: "_uuid", kind: Array(UUID_OID), }
}
///|
/// Construct a placeholder descriptor for a type that has not been catalogued.
///
/// Unknown descriptors let the client carry OID information through error
/// messages and metadata paths even when it has not yet queried PostgreSQL's
/// system catalogs for richer shape information.
pub fn Type::unknown(oid : @proto.Oid, name? : String = "unknown") -> Type {
{ oid, name, kind: Unknown, }
}
///|
/// Resolve a well-known built-in type without querying PostgreSQL catalogs.
///
/// This is the hot path for the scalar and array types the package currently
/// ships first-class codecs for.
fn builtin_type(oid : @proto.Oid) -> Type? {
match oid {
BOOL_OID => Some(Type::bool())
BYTEA_OID => Some(Type::bytea())
CHAR_OID => Some(Type::char())
NAME_OID => Some(Type::name_type())
INT8_OID => Some(Type::int8())
INT2_OID => Some(Type::int2())
INT4_OID => Some(Type::int4())
TEXT_OID => Some(Type::text())
OID_TYPE_OID => Some(Type::oid_type())
JSON_OID => Some(Type::json())
JSON_ARRAY_OID => Some(Type::json_array())
FLOAT4_OID => Some(Type::float4())
FLOAT8_OID => Some(Type::float8())
BOOL_ARRAY_OID => Some(Type::bool_array())
BYTEA_ARRAY_OID => Some(Type::bytea_array())
INT2_ARRAY_OID => Some(Type::int2_array())
INT4_ARRAY_OID => Some(Type::int4_array())
TEXT_ARRAY_OID => Some(Type::text_array())
VARCHAR_ARRAY_OID => Some(Type::varchar_array())
INT8_ARRAY_OID => Some(Type::int8_array())
FLOAT4_ARRAY_OID => Some(Type::float4_array())
FLOAT8_ARRAY_OID => Some(Type::float8_array())
VARCHAR_OID => Some(Type::varchar())
DATE_OID => Some(Type::date())
TIME_OID => Some(Type::time())
TIMESTAMP_OID => Some(Type::timestamp())
TIMESTAMP_ARRAY_OID => Some(Type::timestamp_array())
DATE_ARRAY_OID => Some(Type::date_array())
TIMESTAMPTZ_OID => Some(Type::timestamptz())
UUID_OID => Some(Type::uuid())
UUID_ARRAY_OID => Some(Type::uuid_array())
JSONB_OID => Some(Type::jsonb())
JSONB_ARRAY_OID => Some(Type::jsonb_array())
_ => None
}
}
///|
/// Return the best local descriptor available for an OID.
///
/// This helper never performs I/O. It is used while parsing row descriptions,
/// where only the OID is available initially and a fully catalogued type may be
/// resolved later by the client's shared type cache.
fn resolve_type(oid : @proto.Oid) -> Type {
builtin_type(oid).unwrap_or(Type::unknown(oid, name="oid_\{oid.to_string()}"))
}
///|
/// Build a uniform `ClientError::WrongType` value for codec compatibility checks.
fn wrong_type_error(moonbit_type : String, postgres_type : Type) -> ClientError {
WrongType({ moonbit_type, postgres_type, })
}
///|
/// Return whether a PostgreSQL type should be treated as textual by default.
///
/// Besides core text-like OIDs, this helper recognizes a handful of common
/// extension types that are naturally represented as strings in user code.
fn is_text_type(type_ : Type) -> Bool {
match type_.oid {
NAME_OID | TEXT_OID | VARCHAR_OID => true
_ =>
match type_.name {
"bpchar" | "citext" | "lquery" | "ltree" | "ltxtquery" | "unknown" =>
true
_ => false
}
}
}
///|
/// Return whether the built-in `Bytes` codec should accept this PostgreSQL type.
fn is_bytes_type(type_ : Type) -> Bool {
match type_.oid {
BYTEA_OID | UUID_OID => true
_ => false
}
}
///|
/// Return whether a PostgreSQL type is one of the built-in JSON scalar types.
fn is_json_type(type_ : Type) -> Bool {
match type_.oid {
JSON_OID | JSONB_OID => true
_ => false
}
}
///|
/// Return the built-in element descriptor for a supported PostgreSQL array.
fn array_element_type(type_ : Type) -> Type? {
match type_.oid {
BOOL_ARRAY_OID => Some(Type::bool())
BYTEA_ARRAY_OID => Some(Type::bytea())
INT2_ARRAY_OID => Some(Type::int2())
INT4_ARRAY_OID => Some(Type::int4())
TEXT_ARRAY_OID => Some(Type::text())
VARCHAR_ARRAY_OID => Some(Type::varchar())
INT8_ARRAY_OID => Some(Type::int8())
FLOAT4_ARRAY_OID => Some(Type::float4())
FLOAT8_ARRAY_OID => Some(Type::float8())
UUID_ARRAY_OID => Some(Type::uuid())
JSON_ARRAY_OID => Some(Type::json())
JSONB_ARRAY_OID => Some(Type::jsonb())
_ => None
}
}