Value : [Null, Real(F64), Integer(I64), String(Str), Bytes(List(U8))] Binding : { name : Str, value : Value } Decoder(cols, stmt, a, derr) : cols -> (stmt => Try(a, derr)) Query(sqlite, path) := { path : path }.{ open : path -> Query(sqlite, path) open = |path| Query.{ path } execute! : Query(sqlite, path), Str, List(Binding) => Try({}, err) where [ sqlite.execute! : { path : path, query : Str, bindings : List(Binding) } => Try({}, err), ] execute! = |self, query, bindings| { Sqlite : sqlite Sqlite.execute!({ path: self.path, query, bindings }) } query_many! : Query(sqlite, path), Str, List(Binding), rows => Try(List(row), err) where [ sqlite.query_many! : { path : path, query : Str, bindings : List(Binding), rows : rows } => Try(List(row), err), ] query_many! = |self, query, bindings, rows| { Sqlite : sqlite Sqlite.query_many!({ path: self.path, query, bindings, rows }) } SubsetMembers := [].{ insert! = |q, { subset_id, record_id }| q.execute!( "INSERT INTO subset_members (subset_id, record_id) VALUES (:subset_id, :record_id)", [ { name: ":subset_id", value: String(subset_id) }, { name: ":record_id", value: Integer(record_id) }, ], ) insert_by_subset_name! : Query(sqlite, path), { name : Str, record_id : I64 } => Try(I64, [DbError(err), SubsetNotFound(Str)]) where [ sqlite.i64 : Str -> Decoder(cols, stmt, I64, derr), sqlite.query_many! : { path : path, query : Str, bindings : List(Binding), rows : Decoder(cols, stmt, I64, derr) } => Try(List(I64), err), sqlite.execute! : { path : path, query : Str, bindings : List(Binding) } => Try({}, err), ] insert_by_subset_name! = |q, { name, record_id }| { Sqlite : sqlite lookup = q.query_many!("SELECT id FROM subsets WHERE name = :name", [{ name: ":name", value: String(name) }], Sqlite.i64("id")) match lookup { Err(e) => Err(DbError(e)) Ok([]) => Err(SubsetNotFound(name)) Ok([subset_id, ..]) => match Query.SubsetMembers.insert!(q, { subset_id, record_id }) { Err(e) => Err(DbError(e)) Ok({}) => Ok(subset_id) } } } } }