| title | Types |
|---|---|
| description | Built-in type system with typed value accessors and cross-database type mapping. |
| package | core, types |
XDB has a built-in type system that maps to both Go types and database-specific types. Every Value in XDB carries its type, enabling type-safe access and cross-database portability.
The canonical user-facing type names are lowercase. Internally, type identifiers are stored as uppercase constants (TID), but TID.Lower() returns the lowercase form for JSON output and CLI display.
| Type | Go Type | PostgreSQL | SQLite | Description |
|---|---|---|---|---|
string |
string |
TEXT |
TEXT |
UTF-8 string |
integer |
int64 |
BIGINT |
INTEGER |
64-bit signed integer |
unsigned |
uint64 |
BIGINT |
INTEGER |
64-bit unsigned integer |
float |
float64 |
DOUBLE PRECISION |
REAL |
64-bit floating point |
boolean |
bool |
BOOLEAN |
INTEGER |
True or false |
time |
time.Time |
TIMESTAMPTZ |
INTEGER |
Date and time in UTC |
json |
json.RawMessage |
JSONB |
TEXT |
Arbitrary JSON data |
bytes |
[]byte |
BYTEA |
BLOB |
Binary data |
array |
[]*Value |
[]T |
TEXT |
Array of typed values |
The ordered list of user-facing types is available as core.ValueTypes. From the CLI, types are declared in schema field definitions ({"fields":{"age":{"type":"integer"}}}) and interpreted by filter predicates; run xdb describe --value-types for the live list.
Types are identified by TID (Type ID), a string constant:
core.TIDString // "STRING"
core.TIDInteger // "INTEGER"
core.TIDUnsigned // "UNSIGNED"
core.TIDFloat // "FLOAT"
core.TIDBoolean // "BOOLEAN"
core.TIDTime // "TIME"
core.TIDJSON // "JSON"
core.TIDBytes // "BYTES"
core.TIDArray // "ARRAY"
core.TIDUnknown // "UNKNOWN"A Value is a typed container that holds data and its type metadata.
Typed constructors (preferred — no reflection):
core.StringVal("hello")
core.IntVal(42)
core.UintVal(100)
core.FloatVal(3.14)
core.BoolVal(true)
core.TimeVal(time.Now())
core.JSONVal(json.RawMessage(`{"key":"val"}`))
core.BytesVal([]byte{0x01, 0x02})
core.ArrayVal(core.TIDString, core.StringVal("a"), core.StringVal("b"))Dynamic constructor (uses reflection):
v := core.NewValue("hello") // panics on unsupported type
v, err := core.NewSafeValue("hello") // safe versionUse As* methods for type-safe extraction. Each returns (T, error):
s, err := value.AsStr() // string
n, err := value.AsInt() // int64
u, err := value.AsUint() // uint64
f, err := value.AsFloat() // float64
b, err := value.AsBool() // bool
t, err := value.AsTime() // time.Time
j, err := value.AsJSON() // json.RawMessage
bs, err := value.AsBytes() // []byte
a, err := value.AsArray() // []*ValueIf the value does not match the requested type, ErrTypeMismatch is returned.
All accessors are nil-safe — calling them on a nil value returns the zero value for the type without error.
For cases where you are certain of the type, Must* methods panic on mismatch:
s := value.MustStr() // panics if not STRING
n := value.MustInt() // panics if not INTEGERvalue.Type() // Type — type metadata
value.IsNil() // bool — true if value is nilImportant: Avoid
Unwrap(). Always useAs*methods for type-safe access.Unwrap()returns the rawanyvalue without type guarantees.
Arrays carry an element type:
arrType := core.NewArrayType(core.TIDString) // ARRAY<STRING>
arrType.ID() // TIDArray
arrType.ElemTypeID() // TIDStringIn Schema definitions, every array field must declare its element
type via the elem_type JSON property (or FieldDef.ElemType in Go). Element
type is required in all modes and is immutable once set — see
Schemas → Array fields.
Each database store defines a codec that maps XDB types to database-specific representations. A codec provides two encoding paths:
- ToDriver / FromDriver — converts
*core.Valueto/fromdriver.Valuefor SQL column storage - ToBytes / FromBytes — converts
*core.Valueto/from[]bytefor KV storage
The SQLite store's codec is defined in store/xdbsqlite/internal/sql/codec.go.
This is how XDB defines types once and maps them to SQLite, Postgres, Redis, or the filesystem.