Standard library Β· Databases
db/oxidb
Imported as import "db/oxidb" as oxidb, its names are then oxidb.β¦. Every signature below is the one the checker infers.
Functions
fn dial(host: Str, port: Int) -> Result(Int, Str)
# not run import "db/oxidb" fd = dial("127.0.0.1", 7411)? # a socket, or Err(cannot connect to 127.0.0.1:7411)
fn hang_up(fd: Int) -> Unit
# not run import "db/oxidb" hang_up(fd)
fn call(fd: Int, request: Json) -> Result(Json, Str)
One request, one reply, unwrapped into a Result.
# not run import "db/oxidb" reply = call(fd, command("ping", Nil)) # Ok(the value the server answered), or Err(its message)
fn command(name: Str, fields: List(Field)) -> Json
command("find", Cons(field("collection", JStr(c)), Nil)) β the cmd field is added here so no caller has to remember its name.
import "db/oxidb" command("find", Cons(field("collection", text("people")), Nil)) # => JObj(Cons(Field(cmd, JStr(find)), Cons(Field(collection, JStr(people)), Nil)))
fn field(key: Str, value: Json) -> Field
import "db/oxidb" field("age", int(36)) # => Field(age, JInt(36))
fn text(s: Str) -> Json
import "db/oxidb" text("ada") # => JStr(ada)
fn int(n: Int) -> Json
import "db/oxidb" int(36) # => JInt(36)
fn on(collection: Str, fields: List(Field)) -> List(Field)
import "db/oxidb" on("people", Cons(field("query", JObj(Nil)), Nil)) # => Cons(Field(collection, JStr(people)), Cons(Field(query, JObj(Nil)), Nil))
fn ping(fd: Int) -> Result(Json, Str)
# not run import "db/oxidb" ping(fd) # Ok(JStr("pong"))
fn hello(fd: Int) -> Result(Json, Str)
The handshake, and the one command whose reply is not on the wire the request was written in: the server answers hello before it has looked at the format, so what comes back is JSON whatever went out, and it is the server's own shape rather than the usual envelope β {"ok":true, "server":{...}}. So this reads either, and hands back what the reply says about the server.
# not run import "db/oxidb" info = hello(fd)? server_name(info) # "oxidb"
fn server_name(info: Json) -> Str
What the handshake says, for a client that wants to know before it asks.
import "db/oxidb" server_name(JObj(Cons(Field("name", JStr("oxidb")), Nil))) # => oxidb
fn server_version(info: Json) -> Str
import "db/oxidb" server_version(JObj(Cons(Field("version", JStr("0.9.0")), Nil))) # => 0.9.0
fn wire_version(info: Json) -> Int
import "db/oxidb" wire_version(JObj(Cons(Field("wire_version", JInt(2)), Nil))) # => 2
fn server_features(info: Json) -> List(Str)
import "db/oxidb" server_features(JObj(Cons(Field("features", JArr(Cons(JStr("tsdb"), Cons(JStr("sql"), Nil)))), Nil))) # => Cons(tsdb, Cons(sql, Nil))
fn list_collections(fd: Int) -> Result(Json, Str)
# not run import "db/oxidb" list_collections(fd) # Ok(JArr(the names))
fn insert(fd: Int, collection: Str, doc: Json) -> Result(Json, Str)
# not run import "db/oxidb" inserted_id(insert(fd, "people", JObj(Cons(field("name", text("ada")), Nil)))?) # the new document's id
fn insert_many(fd: Int, collection: Str, docs: List(Json)) -> Result(Json, Str)
# not run import "db/oxidb" inserted_ids(insert_many(fd, "people", Cons(doc1, Cons(doc2, Nil)))?) # Cons(id1, Cons(id2, Nil))
fn find(fd: Int, collection: Str, query: Json) -> Result(Json, Str)
# not run import "db/oxidb" docs(find(fd, "people", JObj(Cons(field("age", int(36)), Nil)))?) # every document with age 36
fn find_sorted(fd: Int, collection: Str, query: Json, sort: Json, limit: Int) -> Result(Json, Str)
sort is a document like {"age": -1}; a limit of 0 asks for no limit.
# not run import "db/oxidb" docs(find_sorted(fd, "people", JObj(Nil), JObj(Cons(field("age", int(-1)), Nil)), 10)?) # the ten oldest
fn count(fd: Int, collection: Str) -> Result(Json, Str)
# not run import "db/oxidb" counted(count(fd, "people")?) # how many documents
fn count_where(fd: Int, collection: Str, query: Json) -> Result(Json, Str)
How many match, which is what a pager needs before it can say "of 4200".
# not run import "db/oxidb" counted(count_where(fd, "people", JObj(Cons(field("role", text("admin")), Nil)))?)
fn find_page(fd: Int, collection: Str, query: Json, sort: Json, limit: Int, skip: Int) -> Result(Json, Str)
One page of a query: limit documents, the first skip of them passed over. The sort has to be given, because a page is only a page if the order is the same each time.
# not run import "db/oxidb" docs(find_page(fd, "people", JObj(Nil), JObj(Cons(field("name", int(1)), Nil)), 20, 40)?) # the third page of twenty, by name
fn update(fd: Int, collection: Str, query: Json, changes: Json) -> Result(Json, Str)
# not run import "db/oxidb" modified(update(fd, "people", JObj(Cons(field("name", text("ada")), Nil)), set(Cons(field("age", int(37)), Nil)))?) # how many changed
fn delete(fd: Int, collection: Str, query: Json) -> Result(Json, Str)
# not run import "db/oxidb" deleted(delete(fd, "people", JObj(Cons(field("name", text("ada")), Nil)))?) # how many went
fn aggregate(fd: Int, collection: Str, pipeline: Json) -> Result(Json, Str)
A pipeline β a list of stages, $match, $group, $sort, $facet and the rest, each a document like {"$group": {"_id": "$role", "n": {"$sum": 1}}} β and what comes out of the end of it.
# not run import "db/oxidb" pipeline = JArr(Cons(JObj(Cons(field("$group", JObj(Cons(field("_id", text("$role")), Cons(field("n", JObj(Cons(field("$sum", int(1)), Nil))), Nil)))), Nil)), Nil)) docs(aggregate(fd, "people", pipeline)?) # one document per role, with its count
fn create_index(fd: Int, collection: Str, field_name: Str) -> Result(Json, Str)
# not run import "db/oxidb" create_index(fd, "people", "name")
fn proc_status(fd: Int) -> Result(Json, Str)
What the server process itself is doing: how much memory it is holding, how busy it is, how many threads it has, how long it has been up. Nothing about the data, so a page can show it to anyone who may see the page.
# not run import "db/oxidb" st = proc_status(fd)? rss_mb(st) # the server's resident memory, in MB
fn rss_mb(data: Json) -> Float
import "db/oxidb" rss_mb(JObj(Cons(Field("mem_rss_mb", JNum(12.5)), Nil))) # => 12.5
fn cpu_percent(data: Json) -> Float
import "db/oxidb" cpu_percent(JObj(Cons(Field("cpu_percent", JNum(3.0)), Nil))) # => 3
fn uptime_s(data: Json) -> Int
import "db/oxidb" uptime_s(JObj(Cons(Field("uptime_s", JInt(3600)), Nil))) # => 3600
fn set(fields: List(Field)) -> Json
$set is the update operator the server expects for a partial change.
import "db/oxidb" set(Cons(field("age", int(37)), Nil)) # => JObj(Cons(Field($set, JObj(Cons(Field(age, JInt(37)), Nil))), Nil))
fn docs(data: Json) -> List(Json)
find answers with an array; insert with {"id": n}; count with {"count": n}. These name those shapes so callers do not repeat them.
import "db/oxidb" docs(JArr(Cons(JObj(Nil), Cons(JObj(Nil), Nil)))) # => Cons(JObj(Nil), Cons(JObj(Nil), Nil))
fn inserted_id(data: Json) -> Int
import "db/oxidb" inserted_id(JObj(Cons(Field("id", JInt(42)), Nil))) # => 42
fn inserted_ids(data: Json) -> List(Int)
import "db/oxidb" inserted_ids(JArr(Cons(JInt(1), Cons(JInt(2), Nil)))) # => Cons(1, Cons(2, Nil))
fn counted(data: Json) -> Int
import "db/oxidb" counted(JObj(Cons(Field("count", JInt(7)), Nil))) # => 7
fn modified(data: Json) -> Int
import "db/oxidb" modified(JObj(Cons(Field("modified", JInt(1)), Nil))) # => 1
fn deleted(data: Json) -> Int
import "db/oxidb" deleted(JObj(Cons(Field("deleted", JInt(2)), Nil))) # => 2
fn field_str(doc: Json, key: Str) -> Str
A field of one document, as text β field_str(doc, "name").
import "db/oxidb" field_str(JObj(Cons(Field("name", JStr("ada")), Nil)), "name") # => ada field_str(JObj(Nil), "name") # =>
fn field_int(doc: Json, key: Str) -> Int
import "db/oxidb" field_int(JObj(Cons(Field("age", JInt(36)), Nil)), "age") # => 36