Auto-indexing service and GraphQL API for AT Protocol Records
quickslice.slices.network/
atproto
gleam
graphql
1/// Converts GraphQL where input types to SQL where clause types
2///
3/// This module bridges the gap between the GraphQL layer (lexicon_graphql/input/where)
4/// and the database layer (where_clause with database Value types).
5import database/executor.{type Value, Bool, Int, Text}
6import database/queries/where_clause
7import gleam/dict
8import gleam/list
9import gleam/option.{type Option}
10import lexicon_graphql/input/where
11
12/// Convert a where.WhereValue to a database Value
13fn convert_value(value: where.WhereValue) -> Value {
14 case value {
15 where.StringValue(s) -> Text(s)
16 where.IntValue(i) -> Int(i)
17 where.BoolValue(b) -> Bool(b)
18 }
19}
20
21/// Check if a WhereValue is numeric (Int)
22fn is_numeric_value(value: where.WhereValue) -> Bool {
23 case value {
24 where.IntValue(_) -> True
25 where.StringValue(_) -> False
26 where.BoolValue(_) -> False
27 }
28}
29
30/// Check if any comparison value in the condition is numeric
31fn has_numeric_comparison(cond: where.WhereCondition) -> Bool {
32 let check_opt = fn(opt: Option(where.WhereValue)) -> Bool {
33 case opt {
34 option.Some(v) -> is_numeric_value(v)
35 option.None -> False
36 }
37 }
38 check_opt(cond.gt)
39 || check_opt(cond.gte)
40 || check_opt(cond.lt)
41 || check_opt(cond.lte)
42}
43
44/// Convert a where.WhereCondition to a where_clause.WhereCondition
45fn convert_condition(cond: where.WhereCondition) -> where_clause.WhereCondition {
46 where_clause.WhereCondition(
47 eq: option.map(cond.eq, convert_value),
48 in_values: option.map(cond.in_values, fn(values) {
49 list.map(values, convert_value)
50 }),
51 contains: cond.contains,
52 gt: option.map(cond.gt, convert_value),
53 gte: option.map(cond.gte, convert_value),
54 lt: option.map(cond.lt, convert_value),
55 lte: option.map(cond.lte, convert_value),
56 is_null: cond.is_null,
57 is_numeric: has_numeric_comparison(cond),
58 )
59}
60
61/// Convert a where.WhereClause to a where_clause.WhereClause
62pub fn convert_where_clause(
63 clause: where.WhereClause,
64) -> where_clause.WhereClause {
65 where_clause.WhereClause(
66 conditions: dict.map_values(clause.conditions, fn(_key, value) {
67 convert_condition(value)
68 }),
69 and: option.map(clause.and, fn(clauses) {
70 list.map(clauses, convert_where_clause)
71 }),
72 or: option.map(clause.or, fn(clauses) {
73 list.map(clauses, convert_where_clause)
74 }),
75 )
76}