Qirava DMS docs
DDL: CREATE TABLE (schema/schemaless, columns, TTL)
Tables are created with QQL, like everything else: CREATE TABLE <name> [SCHEMALESS | SCHEMA <col>:<type> ...]. A schemaless table accepts any fields; a schema table declares typed columns and is validated strictly on every write. Both share one implicit, DB-generated, immutable primary key _id. Vector columns carry a fixed dimension (vector(<dim>)). Tables can also declare a TTL field for automatic expiry. Created user tables are recorded in the _sys_tables system catalog so the schema is data in the system DB. This page covers the syntax, column types, validation rules, TTL, and the catalog.
CREATE TABLE syntax#
CREATE TABLE <name> SCHEMALESS (the default — the SCHEMALESS keyword is optional) creates a free-form table. CREATE TABLE <name> SCHEMA <col>:<type> <col>:<type> ... creates a strictly-validated typed table with at least one column. Table names must be non-empty, ≤ 128 chars, and use only lowercase letters, digits, _, and ..
Request
CREATE TABLE users SCHEMALESS
CREATE TABLE items SCHEMA name:str e:vector(4)Response
// each -> { "error": null, "data": null, "root": { "count": 0 } }Column types#
| Type keyword | ColumnType | Accepts |
|---|---|---|
| int | Int | i64 integer |
| bigint | BigInt | arbitrary-precision integer |
| decimal | Decimal | arbitrary-precision exact decimal |
| float | Float | f64 |
| timestamp | Timestamp | nanoseconds since epoch (i64) |
| bool | Bool | true / false |
| str / string | Str | UTF-8 string |
| bytes | Bytes | byte blob |
| list | List | ordered list |
| map | Map | key→value object |
| vector(<dim>) | Vector(dim) | fixed-dimension f32 embedding |
Schema validation rules#
Schemaless tables always pass validation. Schema tables are strict on every INSERT and UPDATE:
- Every declared column must be present and match its type (a non-nullable column that is missing or null is a missing-field error).
- A vector column's value must have EXACTLY the declared dimension, else a vector-dim error.
- Unknown fields (not a declared column) are rejected.
- Columns can be declared nullable to allow absence/null.
Request
-- users SCHEMA name:str age:int
INSERT INTO users { name: "x", age: "oops" }Response
{ "error": { "code": "bad_request", "message": "field 'age' expected Int" }, "data": null, "root": { "count": 0 } }The implicit primary key#
Every table has an implicit _id primary key: a DB-generated, monotonically increasing integer assigned on INSERT and immutable thereafter. You never declare it and cannot set or change it — supplying _id in an INSERT or UPDATE is ignored. _id powers the O(1) point-read path (WHERE _id = n) and the per-record write serialization key.
TTL (time-to-live) expiry#
A table can declare a TTL field holding a unix-seconds expiry; the scheduled sweeper deletes rows whose expiry <= now. Declare a Filter index on the TTL field so the sweep is index-served (a range scan, no full scan). TTL is set on the table definition (via with_ttl(field) in code); see the TTL Sweep page for the maintenance flow.
The _sys_tables catalog#
Creating a non-system table records a row in _sys_tables with its name, mode (schemaless/schema), and columns (a comma-separated col:type string). This makes the schema queryable like any other data and lets a durable engine restore the full catalog on restart. (Tables whose name starts with _sys_ are not self-recorded.)
Request
SELECT name FROM _sys_tablesResponse
// after creating `users` and `items`:
{ "error": null, "data": [ { "name": "users" }, { "name": "items" } ], "root": { "count": 2 } }