OxL Reference

Storage and ORM

OxL has three levels of storage (§12.8): the built-in replicated storage of the cluster nodes (Raft, shards), the transactional KV std.kv, and ORM tables std.orm over SQLite or PostgreSQL. The data of a node lives in the --data-dir directory.

Tables#

A data with @table("name") is a table; @pk is the primary key, @auto means the database assigns the value. Queries are written in the language itself: from n in db.Note order by n.id select n.id (§5.9); the compiler turns them into SQL and checks the types.

oxl✓ checked in CI
use std.orm { Db }

@table("notes")
data Note {
  @pk @auto id: i64
  text: str
}

fn main() io, db {
  let db = Db.open("sqlite::memory:")!
  db.insert(Note{ id: 0, text: "first" })
  let a = db.lastInsertId()
  db.insert(Note{ id: 0, text: "second" })
  let b = db.lastInsertId()
  print("{a} {b}")
  print("{db.find(Note, 2)!.text} {db.count(Note)}")
  let ids = from n in db.Note order by n.id select n.id
  print("{ids}")
}
Output
1 2
second 2
[1, 2]

The schema changes through migrations: oxl db keeps oxl.db.lock and the files migrations/NNNN_name.up.sql / .down.sql (§12.8). atomic(db) { … } groups several writes into one transaction (§11.2); a conflict restarts the body, and emit events are published only after the commit.

Key-value#

Kv.open("name") opens a named key space; values are bytes, every key has a monotonic version, so compare-and-set (putIf), prefix scans (scan) and subscriptions (watch) are available.

oxl✓ checked in CI
use std.kv { Kv }
use std.core { Utf8 }

fn main() io, db {
  let kv = Kv.open("tour")!
  kv.put("a/1", Utf8.encode("one"))!
  kv.put("a/2", Utf8.encode("two"))!
  kv.put("b/1", Utf8.encode("other"))!
  let page = kv.scan("a/", 0)!
  var keys: List<str> = []
  for e in page { keys.push(e.key) }
  print("{keys}")
  let v = kv.version("a/1")!
  print("{kv.putIf("a/1", Utf8.encode("uno"), v + 100)!} {kv.putIf("a/1", Utf8.encode("uno"), v)!}")
  print("{kv.putIf("fresh", Utf8.encode("x"), 0)!} {kv.putIf("fresh", Utf8.encode("y"), 0)!}")
  kv.delete("a/2")!
  print("{kv.scan("a/", 0)!.len()}")
  kv.close()
}
Output
["a/1", "a/2"]
false true
true false
1

Db.open(url) understands sqlite:…, postgres://… and builtin://name, a table in the built-in storage of the cluster: every replica of a shard has its own SQLite database and Raft replicates the row changes (§12.8). The same code works with all URLs; the URL usually comes from the configuration.

See also

OxL 1.0.0-beta · Documentation version 1.0.0-beta© OxwaldLink · generated from the Standard, the std sources and the guides