Packages

Create SQL requests from Gleam types effortlessly !

Current section

Files

Jump to
glitr_convert_sql src glitr convert sql.gleam
Raw

src/glitr/convert/sql.gleam

import gleam/bool
import gleam/float
import gleam/int
import gleam/io
import gleam/json
import gleam/list
import gleam/result
import gleam/string
import glitr/convert as c
import glitr/convert/json as j
pub fn insert(
table: String,
converter: c.Converter(a),
values: List(a),
) -> String {
case converter |> c.type_def {
c.Object(fields) -> {
let field_names = list.map(fields, fn(f) { f.0 })
"INSERT INTO "
<> table
<> " ("
<> field_names |> string.join(", ")
<> ") VALUES "
<> list.map(values, fn(v) {
v |> c.encode(converter) |> to_insert_values(field_names)
})
|> string.join(", ")
<> ";"
}
_ -> {
io.println_error("Cannot insert non object values")
""
}
}
}
pub fn update(
table: String,
converter: c.Converter(a),
value: a,
selector_col: String,
) -> String {
case converter |> c.type_def {
c.Object(_fields) -> {
let glitr_value = value |> c.encode(converter)
"UPDATE "
<> table
<> " SET "
<> glitr_value |> to_update_values(selector_col)
<> " WHERE "
<> to_condition(glitr_value, selector_col)
<> ";"
}
_ -> {
io.println_error("Cannot update non object values")
""
}
}
}
pub fn select(table: String, converter: c.Converter(a)) -> String {
case converter |> c.type_def {
c.Object(fields) -> {
let field_names = list.map(fields, fn(f) { f.0 })
"SELECT " <> field_names |> string.join(", ") <> " FROM " <> table <> ";"
}
_ -> {
io.println_error("Cannot select non object values")
""
}
}
}
fn to_insert_values(value: c.GlitrValue, field_names: List(String)) -> String {
case value {
c.ObjectValue(fields) -> {
field_names
|> list.map(fn(f) { list.key_find(fields, f) |> result.map(to_sql_value) })
|> result.all
|> result.map(fn(values) { "(" <> values |> string.join(", ") <> ")" })
|> result.lazy_unwrap(fn() {
io.println_error("There was an error getting some values")
""
})
}
_ -> {
io.println_error("Cannot insert non object values")
""
}
}
}
fn to_update_values(value: c.GlitrValue, col_to_ignore: String) -> String {
case value {
c.ObjectValue(fields) -> {
fields
|> list.filter_map(fn(v) {
use <- bool.guard(v.0 == col_to_ignore, Error(Nil))
Ok(v.0 <> "=" <> to_sql_value(v.1))
})
|> string.join(", ")
}
_ -> {
io.println_error("Cannot update non object values")
""
}
}
}
fn to_condition(value: c.GlitrValue, selector_col: String) -> String {
case value {
c.ObjectValue(fields) -> {
fields
|> list.key_find(selector_col)
|> result.map(fn(val) { selector_col <> "=" <> to_sql_value(val) })
|> result.unwrap("NULL")
}
_ -> {
io.println_error("Cannot update non object values")
""
}
}
}
fn to_sql_value(value: c.GlitrValue) -> String {
case value {
c.BoolValue(True) -> "1"
c.BoolValue(False) -> "0"
c.FloatValue(v) -> float.to_string(v)
c.IntValue(v) -> int.to_string(v)
c.NullValue -> "NULL"
c.StringValue(v) -> "'" <> v <> "'"
_ -> j.encode_value(value) |> json.to_string
}
}