OxL Справочник OxL
РусскийEnglish

Хранилище и ORM

В OxL три уровня хранения (§12.8): встроенное реплицируемое хранилище узлов кластера (Raft, шарды), транзакционный KV std.kv и таблицы ORM std.orm над SQLite или PostgreSQL. Данные узла лежат в каталоге --data-dir.

Таблицы#

data с @table("имя") — таблица; @pk — первичный ключ, @auto — значение выдаёт база. Запросы пишутся прямо в языке: from n in db.Note order by n.id select n.id (§5.9) — компилятор переводит их в SQL и проверяет типы.

oxl✓ проверяется в 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}")
}
Вывод
1 2
second 2
[1, 2]

Схема меняется миграциями: oxl db ведёт oxl.db.lock и файлы migrations/NNNN_name.up.sql / .down.sql (§12.8). Несколько записей в одну транзакцию собирает atomic(db) { … } (§11.2); конфликт перезапускает тело, а события emit публикуются только после коммита.

Ключ-значение#

Kv.open("имя") открывает именованное пространство ключей; значения — bytes, у каждого ключа монотонная версия, поэтому доступны сравнить-и-записать (putIf), префиксный просмотр (scan) и подписки (watch).

oxl✓ проверяется в 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")!
  // putIf записывает только если версия совпала (0 — ключа ещё нет)
  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()
}
Вывод
["a/1", "a/2"]
false true
true false
1

Db.open(url) понимает sqlite:…, postgres://… и builtin://имя — таблицу во встроенном хранилище кластера: у каждой реплики шарда своя SQLite-база, а Raft реплицирует изменения строк (§12.8). Тот же код работает со всеми адресами; адрес обычно берут из конфигурации.

См. также

OxL 1.0.0-beta · Версия документации 1.0.0-beta© OxwaldLink · сгенерировано из Стандарта, исходников std и руководства