aboutsummaryrefslogtreecommitdiff
path: root/src/app/plv8.gleam
blob: e89617e1e4d1902c934d4846814b1d8dfe08cc52 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//// the module implements some plv8 examples
////

import gleam/bool
import gleam/dynamic/decode
import gleam/javascript/array.{type Array}
import gleam/json
import gleam/list
import gleam/result
import gleam/string
import glv8
import glv8/database
import glv8/util.{elog_notice}

pub fn plv8_test(keys ka: Array(String), values va: Array(String)) -> String {
  // list.zip(ka |> array.to_list, va |> array.to_list)
  // |> list.map(fn(t) { #(t.0, json.string(t.1)) })
  // |> json.object
  // |> json.to_string

  array.fold(ka, #(0, []), fn(t, k) {
    let kv = #(k, array.get(va, t.0))
    #(t.0 + 1, [kv, ..t.1])
  }).1
  |> list.map(fn(t) {
    #(t.0, case t.1 {
      Error(Nil) -> json.null()
      Ok(x) -> json.string(x)
    })
  })
  |> json.object
  |> json.to_string
}

pub fn catch_sql_error() -> Nil {
  let r = database.execute("throw SQL error", Nil)
  use <- bool.guard(result.is_ok(r), Nil)

  case r {
    Error(glv8.DBErrorJson(j)) -> elog_notice(j |> json.to_string)
    _ -> elog_notice("should not come here")
  }
}

pub fn catch_sql_error2() -> String {
  let rs = database.execute_as("throw SQL error", Nil, decode.string)
  let fold = fn(rx) { array.fold(rx, "", string.append) }

  use <- bool.guard(
    when: result.is_ok(rs),
    return: result.map(rs, fold) |> result.unwrap(""),
  )

  rs
  |> result.try_recover(fn(e) {
    let _ = elog_notice(e |> glv8.error_to_string)
    let decoder = {
      use value <- decode.field("t", decode.string)
      decode.success(value)
    }
    database.execute_as("select 'and execute queries again' t", Nil, decoder)
  })
  |> result.map(fold)
  |> result.unwrap("")
}

pub type Rec {
  Rec(i: Int, t: String)
}

pub fn set_of_records() -> Array(Rec) {
  [Rec(1, "a"), Rec(2, "b"), Rec(3, "c")]
  |> array.from_list
}

pub fn set_of_integers() -> Array(Int) {
  [1, 2, 3]
  |> array.from_list
}

pub fn scalar_to_record(i: Int, t: String) -> Rec {
  Rec(i, t)
}

pub fn fastsum(arr: Array(Int)) -> Int {
  array.fold(arr, 0, fn(s, e) { s + e })
}

pub fn return_sql() -> Array(Rec) {
  let decoder = {
    use i <- decode.field("i", decode.int)
    use t <- decode.field("t", decode.string)
    decode.success(Rec(i: i, t: t))
  }
  database.execute_as(
    "SELECT i, $1 || i AS t FROM generate_series(1, $2) as tt(i)",
    #("s", 4),
    decoder,
  )
  |> result.unwrap([] |> array.from_list)
}