Auto-indexing service and GraphQL API for AT Protocol Records quickslice.slices.network/
atproto gleam graphql
at main 2.4 kB view raw
1// server/src/database/sqlite/executor.gleam 2 3import database/executor.{ 4 type DbError, type Executor, type Value, Blob, Bool, ConstraintError, Float, 5 Int, Null, QueryError, SQLite, Text, Timestamptz, 6} 7import gleam/dynamic/decode 8import gleam/list 9import gleam/result 10import gleam/string 11import sqlight 12 13/// Create an Executor for SQLite from an open connection 14pub fn new(conn: sqlight.Connection) -> Executor { 15 executor.new( 16 SQLite, 17 fn(sql, params) { 18 sqlight.query( 19 sql, 20 on: conn, 21 with: to_sqlight_values(params), 22 expecting: decode.dynamic, 23 ) 24 |> result.map_error(sqlight_error_to_db_error) 25 }, 26 fn(sql, params) { 27 sqlight.query( 28 sql, 29 on: conn, 30 with: to_sqlight_values(params), 31 expecting: decode.dynamic, 32 ) 33 |> result.map(fn(_) { Nil }) 34 |> result.map_error(sqlight_error_to_db_error) 35 }, 36 fn(_index) { "?" }, 37 fn(column, field) { "json_extract(" <> column <> ", '$." <> field <> "')" }, 38 fn(column, path) { 39 let path_str = string.join(path, ".") 40 "json_extract(" <> column <> ", '$." <> path_str <> "')" 41 }, 42 fn() { "datetime('now')" }, 43 ) 44} 45 46/// Convert our Value type to sqlight.Value 47fn to_sqlight_values(values: List(Value)) -> List(sqlight.Value) { 48 list.map(values, fn(v) { 49 case v { 50 Text(s) -> sqlight.text(s) 51 Int(i) -> sqlight.int(i) 52 Float(f) -> sqlight.float(f) 53 Bool(b) -> 54 case b { 55 True -> sqlight.int(1) 56 False -> sqlight.int(0) 57 } 58 Null -> sqlight.null() 59 Blob(b) -> sqlight.blob(b) 60 // SQLite stores timestamps as TEXT 61 Timestamptz(s) -> sqlight.text(s) 62 } 63 }) 64} 65 66/// Convert sqlight.Error to our DbError type 67fn sqlight_error_to_db_error(err: sqlight.Error) -> DbError { 68 case err { 69 sqlight.SqlightError(code, message, _) -> 70 case code { 71 sqlight.ConstraintCheck 72 | sqlight.ConstraintCommithook 73 | sqlight.ConstraintDatatype 74 | sqlight.ConstraintForeignkey 75 | sqlight.ConstraintFunction 76 | sqlight.ConstraintNotnull 77 | sqlight.ConstraintPinned 78 | sqlight.ConstraintPrimarykey 79 | sqlight.ConstraintRowid 80 | sqlight.ConstraintTrigger 81 | sqlight.ConstraintUnique 82 | sqlight.ConstraintVtab -> ConstraintError(message) 83 _ -> QueryError(message) 84 } 85 } 86}