• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / pg_graphql / 16431879287

22 Jul 2025 01:05AM UTC coverage: 92.335% (-1.7%) from 94.056%
16431879287

Pull #590

github

web-flow
Merge e434169cd into a899acda9
Pull Request #590: Add support for single record queries by primary key

219 of 317 new or added lines in 5 files covered. (69.09%)

43 existing lines in 4 files now uncovered.

7649 of 8284 relevant lines covered (92.33%)

1137.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.89
/src/builder.rs
1
use crate::graphql::*;
2
use crate::gson;
3
use crate::parser_util::*;
4
use crate::sql_types::*;
5
use graphql_parser::query::*;
6
use serde::Serialize;
7
use std::collections::HashMap;
8
use std::hash::Hash;
9
use std::ops::Deref;
10
use std::str::FromStr;
11
use std::sync::Arc;
12

13
#[derive(Clone, Debug)]
14
pub struct AggregateBuilder {
15
    pub alias: String,
16
    pub selections: Vec<AggregateSelection>,
17
}
18

19
#[derive(Clone, Debug)]
20
pub enum AggregateSelection {
21
    Count {
22
        alias: String,
23
    },
24
    Sum {
25
        alias: String,
26
        column_builders: Vec<ColumnBuilder>,
27
    },
28
    Avg {
29
        alias: String,
30
        column_builders: Vec<ColumnBuilder>,
31
    },
32
    Min {
33
        alias: String,
34
        column_builders: Vec<ColumnBuilder>,
35
    },
36
    Max {
37
        alias: String,
38
        column_builders: Vec<ColumnBuilder>,
39
    },
40
    Typename {
41
        alias: String,
42
        typename: String,
43
    },
44
}
45

46
#[derive(Clone, Debug)]
47
pub struct InsertBuilder {
48
    // args
49
    pub objects: Vec<InsertRowBuilder>,
50

51
    // metadata
52
    pub table: Arc<Table>,
53

54
    //fields
55
    pub selections: Vec<InsertSelection>,
56
}
57

58
#[derive(Clone, Debug)]
59
pub struct InsertRowBuilder {
60
    // String is Column name
61
    pub row: HashMap<String, InsertElemValue>,
62
}
63

64
#[derive(Clone, Debug)]
65
pub enum InsertElemValue {
66
    Default, // Equivalent to gson::Absent
67
    Value(serde_json::Value),
68
}
69

70
#[allow(clippy::large_enum_variant)]
71
#[derive(Clone, Debug)]
72
pub enum InsertSelection {
73
    AffectedCount { alias: String },
74
    Records(NodeBuilder),
75
    Typename { alias: String, typename: String },
76
}
77

78
fn read_argument<'a, T>(
3,104✔
79
    arg_name: &str,
3,104✔
80
    field: &__Field,
3,104✔
81
    query_field: &graphql_parser::query::Field<'a, T>,
3,104✔
82
    variables: &serde_json::Value,
3,104✔
83
    variable_definitions: &Vec<VariableDefinition<'a, T>>,
3,104✔
84
) -> Result<gson::Value, String>
3,104✔
85
where
3,104✔
86
    T: Text<'a> + Eq + AsRef<str>,
3,104✔
87
{
88
    let input_value: __InputValue = match field.get_arg(arg_name) {
3,104✔
89
        Some(arg) => arg,
2,446✔
90
        None => return Err(format!("Internal error 1: {}", arg_name)),
658✔
91
    };
92

93
    let user_input: Option<&graphql_parser::query::Value<'a, T>> = query_field
2,446✔
94
        .arguments
2,446✔
95
        .iter()
2,446✔
96
        .filter(|(input_arg_name, _)| input_arg_name.as_ref() == arg_name)
2,446✔
97
        .map(|(_, v)| v)
2,446✔
98
        .next();
2,446✔
99

100
    let user_json_unvalidated = match user_input {
2,446✔
101
        None => gson::Value::Absent,
1,853✔
102
        Some(val) => to_gson(val, variables, variable_definitions)?,
593✔
103
    };
104

105
    let user_json_validated = validate_arg_from_type(&input_value.type_(), &user_json_unvalidated)?;
2,446✔
106
    Ok(user_json_validated)
2,385✔
107
}
3,104✔
108

109
fn read_argument_at_most<'a, T>(
43✔
110
    field: &__Field,
43✔
111
    query_field: &graphql_parser::query::Field<'a, T>,
43✔
112
    variables: &serde_json::Value,
43✔
113
    variable_definitions: &Vec<VariableDefinition<'a, T>>,
43✔
114
) -> Result<i64, String>
43✔
115
where
43✔
116
    T: Text<'a> + Eq + AsRef<str>,
43✔
117
{
118
    let at_most: gson::Value = read_argument(
43✔
119
        "atMost",
43✔
120
        field,
43✔
121
        query_field,
43✔
122
        variables,
43✔
123
        variable_definitions,
43✔
124
    )
125
    .unwrap_or(gson::Value::Number(gson::Number::Integer(1)));
43✔
126
    match at_most {
43✔
127
        gson::Value::Number(gson::Number::Integer(x)) => Ok(x),
43✔
128
        _ => Err("Internal Error: failed to parse validated atFirst".to_string()),
×
129
    }
130
}
43✔
131

132
fn parse_node_id(encoded: gson::Value) -> Result<NodeIdInstance, String> {
22✔
133
    extern crate base64;
134
    use std::str;
135

136
    let node_id_base64_encoded_string: String = match encoded {
22✔
137
        gson::Value::String(s) => s,
22✔
138
        _ => return Err("Invalid value passed to nodeId argument, Error 1".to_string()),
×
139
    };
140

141
    let node_id_json_string_utf8: Vec<u8> = base64::decode(node_id_base64_encoded_string)
22✔
142
        .map_err(|_| "Invalid value passed to nodeId argument. Error 2".to_string())?;
22✔
143

144
    let node_id_json_string: &str = str::from_utf8(&node_id_json_string_utf8)
22✔
145
        .map_err(|_| "Invalid value passed to nodeId argument. Error 3".to_string())?;
22✔
146

147
    let node_id_json: serde_json::Value = serde_json::from_str(node_id_json_string)
22✔
148
        .map_err(|_| "Invalid value passed to nodeId argument. Error 4".to_string())?;
22✔
149

150
    match node_id_json {
21✔
151
        serde_json::Value::Array(x_arr) => {
21✔
152
            if x_arr.len() < 3 {
21✔
153
                return Err("Invalid value passed to nodeId argument. Error 5".to_string());
×
154
            }
21✔
155

156
            let mut x_arr_iter = x_arr.into_iter();
21✔
157
            let schema_name = match x_arr_iter
21✔
158
                .next()
21✔
159
                .expect("failed to get schema name from nodeId argument")
21✔
160
            {
161
                serde_json::Value::String(s) => s,
21✔
162
                _ => {
163
                    return Err("Invalid value passed to nodeId argument. Error 6".to_string());
×
164
                }
165
            };
166

167
            let table_name = match x_arr_iter
21✔
168
                .next()
21✔
169
                .expect("failed to get table name from nodeId argument")
21✔
170
            {
171
                serde_json::Value::String(s) => s,
21✔
172
                _ => {
173
                    return Err("Invalid value passed to nodeId argument. Error 7".to_string());
×
174
                }
175
            };
176
            let values: Vec<serde_json::Value> = x_arr_iter.collect();
21✔
177

178
            // Popuate a NodeIdInstance
179
            Ok(NodeIdInstance {
21✔
180
                schema_name,
21✔
181
                table_name,
21✔
182
                values,
21✔
183
            })
21✔
184
        }
185
        _ => Err("Invalid value passed to nodeId argument. Error 10".to_string()),
×
186
    }
187
}
22✔
188

189
fn read_argument_node_id<'a, T>(
18✔
190
    field: &__Field,
18✔
191
    query_field: &graphql_parser::query::Field<'a, T>,
18✔
192
    variables: &serde_json::Value,
18✔
193
    variable_definitions: &Vec<VariableDefinition<'a, T>>,
18✔
194
) -> Result<NodeIdInstance, String>
18✔
195
where
18✔
196
    T: Text<'a> + Eq + AsRef<str>,
18✔
197
{
198
    // nodeId is a base64 encoded string of [schema, table, pkey_val1, pkey_val2, ...]
199
    let node_id_base64_encoded_json_string: gson::Value = read_argument(
18✔
200
        "nodeId",
18✔
201
        field,
18✔
202
        query_field,
18✔
203
        variables,
18✔
204
        variable_definitions,
18✔
205
    )?;
1✔
206

207
    parse_node_id(node_id_base64_encoded_json_string)
17✔
208
}
18✔
209

210
fn read_argument_objects<'a, T>(
38✔
211
    field: &__Field,
38✔
212
    query_field: &graphql_parser::query::Field<'a, T>,
38✔
213
    variables: &serde_json::Value,
38✔
214
    variable_definitions: &Vec<VariableDefinition<'a, T>>,
38✔
215
) -> Result<Vec<InsertRowBuilder>, String>
38✔
216
where
38✔
217
    T: Text<'a> + Eq + AsRef<str>,
38✔
218
{
219
    // [{"name": "bob", "email": "a@b.com"}, {..}]
220
    let validated: gson::Value = read_argument(
38✔
221
        "objects",
38✔
222
        field,
38✔
223
        query_field,
38✔
224
        variables,
38✔
225
        variable_definitions,
38✔
226
    )?;
8✔
227

228
    // [<Table>OrderBy!]
229
    let insert_type: InsertInputType = match field
30✔
230
        .get_arg("objects")
30✔
231
        .expect("failed to get `objects` argument")
30✔
232
        .type_()
30✔
233
        .unmodified_type()
30✔
234
    {
235
        __Type::InsertInput(insert_type) => insert_type,
30✔
236
        _ => return Err("Could not locate Insert Entity type".to_string()),
×
237
    };
238

239
    let mut objects: Vec<InsertRowBuilder> = vec![];
30✔
240

241
    let insert_type_field_map = input_field_map(&__Type::InsertInput(insert_type));
30✔
242

243
    // validated user input kv map
244
    match validated {
30✔
245
        gson::Value::Absent | gson::Value::Null => (),
×
246
        gson::Value::Array(x_arr) => {
30✔
247
            for row in x_arr.iter() {
33✔
248
                let mut column_elems: HashMap<String, InsertElemValue> = HashMap::new();
33✔
249

250
                match row {
33✔
251
                    gson::Value::Absent | gson::Value::Null => continue,
×
252
                    gson::Value::Object(obj) => {
33✔
253
                        for (column_field_name, col_input_value) in obj.iter() {
65✔
254
                            let column_input_value: &__InputValue =
65✔
255
                                match insert_type_field_map.get(column_field_name) {
65✔
256
                                    Some(input_field) => input_field,
65✔
257
                                    None => return Err("Insert re-validation error 3".to_string()),
×
258
                                };
259

260
                            match &column_input_value.sql_type {
65✔
261
                                Some(NodeSQLType::Column(col)) => {
65✔
262
                                    let insert_col_builder = match col_input_value {
65✔
263
                                        gson::Value::Absent => InsertElemValue::Default,
1✔
264
                                        _ => InsertElemValue::Value(gson::gson_to_json(
64✔
265
                                            col_input_value,
64✔
UNCOV
266
                                        )?),
×
267
                                    };
268
                                    column_elems.insert(col.name.clone(), insert_col_builder);
65✔
269
                                }
270
                                _ => return Err("Insert re-validation error 4".to_string()),
×
271
                            }
272
                        }
273
                    }
274
                    _ => return Err("Insert re-validation errror 1".to_string()),
×
275
                }
276

277
                let insert_row_builder = InsertRowBuilder { row: column_elems };
33✔
278
                objects.push(insert_row_builder);
33✔
279
            }
280
        }
281
        _ => return Err("Insert re-validation errror".to_string()),
×
282
    };
283

284
    if objects.is_empty() {
30✔
285
        return Err("At least one record must be provided to objects".to_string());
1✔
286
    }
29✔
287
    Ok(objects)
29✔
288
}
38✔
289

290
pub fn to_insert_builder<'a, T>(
38✔
291
    field: &__Field,
38✔
292
    query_field: &graphql_parser::query::Field<'a, T>,
38✔
293
    fragment_definitions: &Vec<FragmentDefinition<'a, T>>,
38✔
294
    variables: &serde_json::Value,
38✔
295
    variable_definitions: &Vec<VariableDefinition<'a, T>>,
38✔
296
) -> Result<InsertBuilder, String>
38✔
297
where
38✔
298
    T: Text<'a> + Eq + AsRef<str> + Clone,
38✔
299
    T::Value: Hash,
38✔
300
{
301
    let type_ = field.type_().unmodified_type();
38✔
302
    let type_name = type_
38✔
303
        .name()
38✔
304
        .ok_or("Encountered type without name in connection builder")?;
38✔
305
    let field_map = field_map(&type_);
38✔
306

307
    match &type_ {
38✔
308
        __Type::InsertResponse(xtype) => {
38✔
309
            // Raise for disallowed arguments
310
            restrict_allowed_arguments(&["objects"], query_field)?;
38✔
311

312
            let objects: Vec<InsertRowBuilder> =
29✔
313
                read_argument_objects(field, query_field, variables, variable_definitions)?;
38✔
314

315
            let mut builder_fields: Vec<InsertSelection> = vec![];
29✔
316

317
            let selection_fields = normalize_selection_set(
29✔
318
                &query_field.selection_set,
29✔
319
                fragment_definitions,
29✔
320
                &type_name,
29✔
321
                variables,
29✔
UNCOV
322
            )?;
×
323

324
            for selection_field in selection_fields {
75✔
325
                match field_map.get(selection_field.name.as_ref()) {
46✔
326
                    None => return Err("unknown field in insert".to_string()),
×
327
                    Some(f) => builder_fields.push(match f.name().as_ref() {
46✔
328
                        "affectedCount" => InsertSelection::AffectedCount {
46✔
329
                            alias: alias_or_name(&selection_field),
18✔
330
                        },
18✔
331
                        "records" => {
28✔
332
                            let node_builder = to_node_builder(
27✔
333
                                f,
27✔
334
                                &selection_field,
27✔
335
                                fragment_definitions,
27✔
336
                                variables,
27✔
337
                                &[],
27✔
338
                                variable_definitions,
27✔
339
                            );
340
                            InsertSelection::Records(node_builder?)
27✔
341
                        }
342
                        "__typename" => InsertSelection::Typename {
1✔
343
                            alias: alias_or_name(&selection_field),
1✔
344
                            typename: xtype
1✔
345
                                .name()
1✔
346
                                .expect("insert response type should have a name"),
1✔
347
                        },
1✔
348
                        _ => return Err("unexpected field type on insert response".to_string()),
×
349
                    }),
350
                }
351
            }
352
            Ok(InsertBuilder {
29✔
353
                table: Arc::clone(&xtype.table),
29✔
354
                objects,
29✔
355
                selections: builder_fields,
29✔
356
            })
29✔
357
        }
358
        _ => Err(format!(
×
359
            "can not build query for non-insert type {:?}",
×
360
            type_.name()
×
361
        )),
×
362
    }
363
}
38✔
364

365
#[derive(Clone, Debug)]
366
pub struct UpdateBuilder {
367
    // args
368
    pub filter: FilterBuilder,
369
    pub set: SetBuilder,
370
    pub at_most: i64,
371

372
    // metadata
373
    pub table: Arc<Table>,
374

375
    //fields
376
    pub selections: Vec<UpdateSelection>,
377
}
378

379
#[derive(Clone, Debug)]
380
pub struct SetBuilder {
381
    // String is Column name
382
    pub set: HashMap<String, serde_json::Value>,
383
}
384

385
#[allow(clippy::large_enum_variant)]
386
#[derive(Clone, Debug)]
387
pub enum UpdateSelection {
388
    AffectedCount { alias: String },
389
    Records(NodeBuilder),
390
    Typename { alias: String, typename: String },
391
}
392

393
fn read_argument_set<'a, T>(
28✔
394
    field: &__Field,
28✔
395
    query_field: &graphql_parser::query::Field<'a, T>,
28✔
396
    variables: &serde_json::Value,
28✔
397
    variable_definitions: &Vec<VariableDefinition<'a, T>>,
28✔
398
) -> Result<SetBuilder, String>
28✔
399
where
28✔
400
    T: Text<'a> + Eq + AsRef<str>,
28✔
401
{
402
    let validated: gson::Value =
27✔
403
        read_argument("set", field, query_field, variables, variable_definitions)?;
28✔
404

405
    let update_type: UpdateInputType = match field
27✔
406
        .get_arg("set")
27✔
407
        .expect("failed to get `set` argument")
27✔
408
        .type_()
27✔
409
        .unmodified_type()
27✔
410
    {
411
        __Type::UpdateInput(type_) => type_,
27✔
412
        _ => return Err("Could not locate update entity type".to_string()),
×
413
    };
414

415
    let mut set: HashMap<String, serde_json::Value> = HashMap::new();
27✔
416

417
    let update_type_field_map = input_field_map(&__Type::UpdateInput(update_type));
27✔
418

419
    // validated user input kv map
420
    match validated {
27✔
421
        gson::Value::Absent | gson::Value::Null => (),
×
422
        gson::Value::Object(obj) => {
27✔
423
            for (column_field_name, col_input_value) in obj.iter() {
50✔
424
                // If value is absent, skip it. Nulls are handled as literals
425
                if col_input_value == &gson::Value::Absent {
50✔
426
                    continue;
2✔
427
                }
48✔
428
                let column_input_value: &__InputValue =
48✔
429
                    match update_type_field_map.get(column_field_name) {
48✔
430
                        Some(input_field) => input_field,
48✔
431
                        None => return Err("Update re-validation error 3".to_string()),
×
432
                    };
433

434
                match &column_input_value.sql_type {
48✔
435
                    Some(NodeSQLType::Column(col)) => {
48✔
436
                        set.insert(col.name.clone(), gson::gson_to_json(col_input_value)?);
48✔
437
                    }
438
                    _ => return Err("Update re-validation error 4".to_string()),
×
439
                }
440
            }
441
        }
442
        _ => return Err("Update re-validation errror".to_string()),
×
443
    };
444

445
    if set.is_empty() {
27✔
446
        return Err("At least one mapping must be provided to set argument".to_string());
1✔
447
    }
26✔
448

449
    Ok(SetBuilder { set })
26✔
450
}
28✔
451

452
pub fn to_update_builder<'a, T>(
28✔
453
    field: &__Field,
28✔
454
    query_field: &graphql_parser::query::Field<'a, T>,
28✔
455
    fragment_definitions: &Vec<FragmentDefinition<'a, T>>,
28✔
456
    variables: &serde_json::Value,
28✔
457
    variable_definitions: &Vec<VariableDefinition<'a, T>>,
28✔
458
) -> Result<UpdateBuilder, String>
28✔
459
where
28✔
460
    T: Text<'a> + Eq + AsRef<str> + Clone,
28✔
461
    T::Value: Hash,
28✔
462
{
463
    let type_ = field.type_().unmodified_type();
28✔
464
    let type_name = type_
28✔
465
        .name()
28✔
466
        .ok_or("Encountered type without name in update builder")?;
28✔
467
    let field_map = field_map(&type_);
28✔
468

469
    match &type_ {
28✔
470
        __Type::UpdateResponse(xtype) => {
28✔
471
            // Raise for disallowed arguments
472
            restrict_allowed_arguments(&["set", "filter", "atMost"], query_field)?;
28✔
473

474
            let set: SetBuilder =
26✔
475
                read_argument_set(field, query_field, variables, variable_definitions)?;
28✔
476
            let filter: FilterBuilder =
26✔
477
                read_argument_filter(field, query_field, variables, variable_definitions)?;
26✔
478
            let at_most: i64 =
26✔
479
                read_argument_at_most(field, query_field, variables, variable_definitions)?;
26✔
480

481
            let mut builder_fields: Vec<UpdateSelection> = vec![];
26✔
482

483
            let selection_fields = normalize_selection_set(
26✔
484
                &query_field.selection_set,
26✔
485
                fragment_definitions,
26✔
486
                &type_name,
26✔
487
                variables,
26✔
UNCOV
488
            )?;
×
489

490
            for selection_field in selection_fields {
60✔
491
                match field_map.get(selection_field.name.as_ref()) {
34✔
492
                    None => return Err("unknown field in update".to_string()),
×
493
                    Some(f) => builder_fields.push(match f.name().as_ref() {
34✔
494
                        "affectedCount" => UpdateSelection::AffectedCount {
34✔
495
                            alias: alias_or_name(&selection_field),
7✔
496
                        },
7✔
497
                        "records" => {
27✔
498
                            let node_builder = to_node_builder(
26✔
499
                                f,
26✔
500
                                &selection_field,
26✔
501
                                fragment_definitions,
26✔
502
                                variables,
26✔
503
                                &[],
26✔
504
                                variable_definitions,
26✔
505
                            );
506
                            UpdateSelection::Records(node_builder?)
26✔
507
                        }
508
                        "__typename" => UpdateSelection::Typename {
1✔
509
                            alias: alias_or_name(&selection_field),
1✔
510
                            typename: xtype
1✔
511
                                .name()
1✔
512
                                .expect("update response type should have a name"),
1✔
513
                        },
1✔
514
                        _ => return Err("unexpected field type on update response".to_string()),
×
515
                    }),
516
                }
517
            }
518
            Ok(UpdateBuilder {
26✔
519
                filter,
26✔
520
                set,
26✔
521
                at_most,
26✔
522
                table: Arc::clone(&xtype.table),
26✔
523
                selections: builder_fields,
26✔
524
            })
26✔
525
        }
526
        _ => Err(format!(
×
527
            "can not build query for non-update type {:?}",
×
528
            type_.name()
×
529
        )),
×
530
    }
531
}
28✔
532

533
#[derive(Clone, Debug)]
534
pub struct DeleteBuilder {
535
    // args
536
    pub filter: FilterBuilder,
537
    pub at_most: i64,
538

539
    // metadata
540
    pub table: Arc<Table>,
541

542
    //fields
543
    pub selections: Vec<DeleteSelection>,
544
}
545

546
#[allow(clippy::large_enum_variant)]
547
#[derive(Clone, Debug)]
548
pub enum DeleteSelection {
549
    AffectedCount { alias: String },
550
    Records(NodeBuilder),
551
    Typename { alias: String, typename: String },
552
}
553

554
pub fn to_delete_builder<'a, T>(
17✔
555
    field: &__Field,
17✔
556
    query_field: &graphql_parser::query::Field<'a, T>,
17✔
557
    fragment_definitions: &Vec<FragmentDefinition<'a, T>>,
17✔
558
    variables: &serde_json::Value,
17✔
559
    variable_definitions: &Vec<VariableDefinition<'a, T>>,
17✔
560
) -> Result<DeleteBuilder, String>
17✔
561
where
17✔
562
    T: Text<'a> + Eq + AsRef<str> + Clone,
17✔
563
    T::Value: Hash,
17✔
564
{
565
    let type_ = field.type_().unmodified_type();
17✔
566
    let type_name = type_
17✔
567
        .name()
17✔
568
        .ok_or("Encountered type without name in delete builder")?;
17✔
569
    let field_map = field_map(&type_);
17✔
570

571
    match &type_ {
17✔
572
        __Type::DeleteResponse(xtype) => {
17✔
573
            // Raise for disallowed arguments
574
            restrict_allowed_arguments(&["filter", "atMost"], query_field)?;
17✔
575

576
            let filter: FilterBuilder =
17✔
577
                read_argument_filter(field, query_field, variables, variable_definitions)?;
17✔
578
            let at_most: i64 =
17✔
579
                read_argument_at_most(field, query_field, variables, variable_definitions)?;
17✔
580

581
            let mut builder_fields: Vec<DeleteSelection> = vec![];
17✔
582

583
            let selection_fields = normalize_selection_set(
17✔
584
                &query_field.selection_set,
17✔
585
                fragment_definitions,
17✔
586
                &type_name,
17✔
587
                variables,
17✔
UNCOV
588
            )?;
×
589

590
            for selection_field in selection_fields {
42✔
591
                match field_map.get(selection_field.name.as_ref()) {
25✔
592
                    None => return Err("unknown field in delete".to_string()),
×
593
                    Some(f) => builder_fields.push(match f.name().as_ref() {
25✔
594
                        "affectedCount" => DeleteSelection::AffectedCount {
25✔
595
                            alias: alias_or_name(&selection_field),
7✔
596
                        },
7✔
597
                        "records" => {
18✔
598
                            let node_builder = to_node_builder(
17✔
599
                                f,
17✔
600
                                &selection_field,
17✔
601
                                fragment_definitions,
17✔
602
                                variables,
17✔
603
                                &[],
17✔
604
                                variable_definitions,
17✔
605
                            );
606
                            DeleteSelection::Records(node_builder?)
17✔
607
                        }
608
                        "__typename" => DeleteSelection::Typename {
1✔
609
                            alias: alias_or_name(&selection_field),
1✔
610
                            typename: xtype
1✔
611
                                .name()
1✔
612
                                .expect("delete response type should have a name"),
1✔
613
                        },
1✔
614
                        _ => return Err("unexpected field type on delete response".to_string()),
×
615
                    }),
616
                }
617
            }
618
            Ok(DeleteBuilder {
17✔
619
                filter,
17✔
620
                at_most,
17✔
621
                table: Arc::clone(&xtype.table),
17✔
622
                selections: builder_fields,
17✔
623
            })
17✔
624
        }
625
        _ => Err(format!(
×
626
            "can not build query for non-delete type {:?}",
×
627
            type_.name()
×
628
        )),
×
629
    }
630
}
17✔
631

632
pub struct FunctionCallBuilder {
633
    // metadata
634
    pub function: Arc<Function>,
635

636
    // args
637
    pub args_builder: FuncCallArgsBuilder,
638

639
    pub return_type_builder: FuncCallReturnTypeBuilder,
640
}
641

642
pub enum FuncCallReturnTypeBuilder {
643
    Scalar,
644
    List,
645
    Node(NodeBuilder),
646
    Connection(ConnectionBuilder),
647
}
648

649
#[derive(Clone, Debug)]
650
pub struct FuncCallArgsBuilder {
651
    pub args: Vec<(Option<FuncCallSqlArgName>, serde_json::Value)>,
652
}
653

654
#[derive(Clone, Debug)]
655
pub struct FuncCallSqlArgName {
656
    pub type_name: String,
657
    pub name: String,
658
}
659

660
pub fn to_function_call_builder<'a, T>(
94✔
661
    field: &__Field,
94✔
662
    query_field: &graphql_parser::query::Field<'a, T>,
94✔
663
    fragment_definitions: &Vec<FragmentDefinition<'a, T>>,
94✔
664
    variables: &serde_json::Value,
94✔
665
    variable_definitions: &Vec<VariableDefinition<'a, T>>,
94✔
666
) -> Result<FunctionCallBuilder, String>
94✔
667
where
94✔
668
    T: Text<'a> + Eq + AsRef<str> + Clone,
94✔
669
    T::Value: Hash,
94✔
670
{
671
    let type_ = field.type_().unmodified_type();
94✔
672

673
    match &type_ {
94✔
674
        __Type::FuncCallResponse(func_call_resp_type) => {
94✔
675
            let args = field.args();
94✔
676
            let allowed_args: Vec<&str> = args.iter().map(|a| a.name_.as_str()).collect();
165✔
677
            restrict_allowed_arguments(&allowed_args, query_field)?;
94✔
678
            let args = read_func_call_args(
94✔
679
                field,
94✔
680
                query_field,
94✔
681
                variables,
94✔
682
                func_call_resp_type,
94✔
683
                variable_definitions,
94✔
684
            )?;
1✔
685

686
            let return_type_builder = match func_call_resp_type.return_type.deref() {
93✔
687
                __Type::Scalar(_) => FuncCallReturnTypeBuilder::Scalar,
69✔
688
                __Type::List(_) => FuncCallReturnTypeBuilder::List,
14✔
689
                __Type::Node(_) => {
690
                    let node_builder = to_node_builder(
9✔
691
                        field,
9✔
692
                        query_field,
9✔
693
                        fragment_definitions,
9✔
694
                        variables,
9✔
695
                        &allowed_args,
9✔
696
                        variable_definitions,
9✔
UNCOV
697
                    )?;
×
698
                    FuncCallReturnTypeBuilder::Node(node_builder)
9✔
699
                }
700
                __Type::Connection(_) => {
701
                    let connection_builder = to_connection_builder(
1✔
702
                        field,
1✔
703
                        query_field,
1✔
704
                        fragment_definitions,
1✔
705
                        variables,
1✔
706
                        &allowed_args,
1✔
707
                        variable_definitions,
1✔
UNCOV
708
                    )?;
×
709
                    FuncCallReturnTypeBuilder::Connection(connection_builder)
1✔
710
                }
711
                _ => {
712
                    return Err(format!(
×
713
                        "unsupported return type: {}",
×
714
                        func_call_resp_type
×
715
                            .return_type
×
716
                            .unmodified_type()
×
717
                            .name()
×
718
                            .ok_or("Encountered type without name in function call builder")?
×
719
                    ));
720
                }
721
            };
722

723
            Ok(FunctionCallBuilder {
93✔
724
                function: Arc::clone(&func_call_resp_type.function),
93✔
725
                args_builder: args,
93✔
726
                return_type_builder,
93✔
727
            })
93✔
728
        }
729
        _ => Err(format!(
×
730
            "can not build query for non-function type {:?}",
×
731
            type_.name()
×
732
        )),
×
733
    }
734
}
94✔
735

736
fn read_func_call_args<'a, T>(
94✔
737
    field: &__Field,
94✔
738
    query_field: &graphql_parser::query::Field<'a, T>,
94✔
739
    variables: &serde_json::Value,
94✔
740
    func_call_resp_type: &FuncCallResponseType,
94✔
741
    variable_definitions: &Vec<VariableDefinition<'a, T>>,
94✔
742
) -> Result<FuncCallArgsBuilder, String>
94✔
743
where
94✔
744
    T: Text<'a> + Eq + AsRef<str>,
94✔
745
{
746
    let inflected_to_sql_args = func_call_resp_type.inflected_to_sql_args();
94✔
747
    let mut args = vec![];
94✔
748
    for arg in field.args() {
165✔
749
        let arg_value = read_argument(
165✔
750
            &arg.name(),
165✔
751
            field,
165✔
752
            query_field,
165✔
753
            variables,
165✔
754
            variable_definitions,
165✔
755
        )?;
1✔
756
        if !arg_value.is_absent() {
164✔
757
            let func_call_sql_arg_name =
127✔
758
                inflected_to_sql_args
127✔
759
                    .get(&arg.name())
127✔
760
                    .map(|(type_name, name)| FuncCallSqlArgName {
127✔
761
                        type_name: type_name.clone(),
126✔
762
                        name: name.clone(),
126✔
763
                    });
126✔
764
            args.push((func_call_sql_arg_name, gson::gson_to_json(&arg_value)?));
127✔
765
        };
37✔
766
    }
767
    Ok(FuncCallArgsBuilder { args })
93✔
768
}
94✔
769

770
#[derive(Clone, Debug)]
771
pub struct ConnectionBuilderSource {
772
    pub table: Arc<Table>,
773
    pub fkey: Option<ForeignKeyReversible>,
774
}
775

776
#[derive(Clone, Debug)]
777
pub struct ConnectionBuilder {
778
    pub alias: String,
779

780
    // args
781
    pub first: Option<u64>,
782
    pub last: Option<u64>,
783
    pub before: Option<Cursor>,
784
    pub after: Option<Cursor>,
785
    pub offset: Option<u64>,
786
    pub filter: FilterBuilder,
787
    pub order_by: OrderByBuilder,
788

789
    // metadata
790
    pub source: ConnectionBuilderSource,
791

792
    //fields
793
    pub selections: Vec<ConnectionSelection>,
794
    pub max_rows: u64,
795
}
796

797
#[derive(Clone, Debug)]
798
pub enum CompoundFilterBuilder {
799
    And(Vec<FilterBuilderElem>),
800
    Or(Vec<FilterBuilderElem>),
801
    Not(FilterBuilderElem),
802
}
803

804
#[derive(Clone, Debug)]
805
pub enum FilterBuilderElem {
806
    Column {
807
        column: Arc<Column>,
808
        op: FilterOp,
809
        value: serde_json::Value, //String, // string repr castable by postgres
810
    },
811
    NodeId(NodeIdInstance),
812
    Compound(Box<CompoundFilterBuilder>),
813
}
814

815
#[derive(Clone, Debug)]
816
pub struct FilterBuilder {
817
    pub elems: Vec<FilterBuilderElem>,
818
}
819

820
#[derive(Clone, Debug)]
821
pub enum OrderDirection {
822
    AscNullsFirst,
823
    AscNullsLast,
824
    DescNullsFirst,
825
    DescNullsLast,
826
}
827

828
impl OrderDirection {
829
    pub fn nulls_first(&self) -> bool {
24✔
830
        match self {
24✔
831
            Self::AscNullsFirst => true,
1✔
832
            Self::AscNullsLast => false,
13✔
833
            Self::DescNullsFirst => true,
9✔
834
            Self::DescNullsLast => false,
1✔
835
        }
836
    }
24✔
837

838
    pub fn is_asc(&self) -> bool {
24✔
839
        match self {
24✔
840
            Self::AscNullsFirst => true,
1✔
841
            Self::AscNullsLast => true,
13✔
842
            Self::DescNullsFirst => false,
9✔
843
            Self::DescNullsLast => false,
1✔
844
        }
845
    }
24✔
846
}
847

848
impl FromStr for OrderDirection {
849
    type Err = String;
850

851
    fn from_str(input: &str) -> Result<Self, Self::Err> {
40✔
852
        match input {
40✔
853
            "AscNullsFirst" => Ok(Self::AscNullsFirst),
40✔
854
            "AscNullsLast" => Ok(Self::AscNullsLast),
33✔
855
            "DescNullsFirst" => Ok(Self::DescNullsFirst),
14✔
856
            "DescNullsLast" => Ok(Self::DescNullsLast),
8✔
857
            _ => Err(format!("Invalid order operation {}", input)),
×
858
        }
859
    }
40✔
860
}
861
impl OrderDirection {
862
    pub fn reverse(&self) -> Self {
407✔
863
        match self {
407✔
864
            Self::AscNullsFirst => Self::DescNullsLast,
8✔
865
            Self::AscNullsLast => Self::DescNullsFirst,
385✔
866
            Self::DescNullsFirst => Self::AscNullsLast,
6✔
867
            Self::DescNullsLast => Self::AscNullsFirst,
8✔
868
        }
869
    }
407✔
870
}
871

872
impl OrderByBuilderElem {
873
    fn reverse(&self) -> Self {
407✔
874
        Self {
407✔
875
            column: Arc::clone(&self.column),
407✔
876
            direction: self.direction.reverse(),
407✔
877
        }
407✔
878
    }
407✔
879
}
880

881
impl OrderByBuilder {
882
    pub fn reverse(&self) -> Self {
336✔
883
        Self {
884
            elems: self.elems.iter().map(|x| x.reverse()).collect(),
407✔
885
        }
886
    }
336✔
887
}
888

889
#[derive(Clone, Debug)]
890
pub struct CursorElement {
891
    pub value: serde_json::Value,
892
}
893
#[derive(Clone, Debug)]
894
pub struct Cursor {
895
    pub elems: Vec<CursorElement>,
896
}
897

898
impl FromStr for Cursor {
899
    type Err = String;
900

901
    fn from_str(input: &str) -> Result<Self, Self::Err> {
27✔
902
        extern crate base64;
903
        use std::str;
904

905
        match base64::decode(input) {
27✔
906
            Ok(vec_u8) => match str::from_utf8(&vec_u8) {
26✔
907
                Ok(v) => {
26✔
908
                    let mut elems: Vec<CursorElement> = vec![];
26✔
909
                    match serde_json::from_str(v) {
26✔
910
                        Ok(json) => match json {
26✔
911
                            serde_json::Value::Array(x_arr) => {
26✔
912
                                for x in &x_arr {
56✔
913
                                    let element = CursorElement { value: x.clone() };
30✔
914
                                    elems.push(element);
30✔
915
                                }
30✔
916
                                Ok(Cursor { elems })
26✔
917
                            }
918
                            _ => Err("Failed to decode cursor, error 4".to_string()),
×
919
                        },
920
                        Err(_) => Err("Failed to decode cursor, error 3".to_string()),
×
921
                    }
922
                }
923
                Err(_) => Err("Failed to decode cursor, error 2".to_string()),
×
924
            },
925
            Err(_) => Err("Failed to decode cursor, error 1".to_string()),
1✔
926
        }
927
    }
27✔
928
}
929

930
#[derive(Clone, Debug)]
931
pub struct OrderByBuilderElem {
932
    pub column: Arc<Column>,
933
    pub direction: OrderDirection,
934
}
935

936
#[derive(Clone, Debug)]
937
pub struct OrderByBuilder {
938
    pub elems: Vec<OrderByBuilderElem>,
939
}
940

941
#[derive(Clone, Debug)]
942
pub struct PageInfoBuilder {
943
    pub alias: String,
944
    pub selections: Vec<PageInfoSelection>,
945
}
946

947
#[derive(Clone, Debug)]
948
pub enum PageInfoSelection {
949
    StartCursor { alias: String },
950
    EndCursor { alias: String },
951
    HasNextPage { alias: String },
952
    HasPreviousPage { alias: String },
953
    Typename { alias: String, typename: String },
954
}
955

956
#[derive(Clone, Debug)]
957
pub enum ConnectionSelection {
958
    TotalCount { alias: String },
959
    Edge(EdgeBuilder),
960
    PageInfo(PageInfoBuilder),
961
    Typename { alias: String, typename: String },
962
    Aggregate(AggregateBuilder),
963
}
964

965
#[derive(Clone, Debug)]
966
pub struct EdgeBuilder {
967
    pub alias: String,
968
    pub selections: Vec<EdgeSelection>,
969
}
970

971
#[allow(clippy::large_enum_variant)]
972
#[derive(Clone, Debug)]
973
pub enum EdgeSelection {
974
    Cursor { alias: String },
975
    Node(NodeBuilder),
976
    Typename { alias: String, typename: String },
977
}
978

979
#[derive(Clone, Debug)]
980
pub struct NodeBuilder {
981
    // args
982
    pub node_id: Option<NodeIdInstance>,
983

984
    pub alias: String,
985

986
    // metadata
987
    pub table: Arc<Table>,
988
    pub fkey: Option<Arc<ForeignKey>>,
989
    pub reverse_reference: Option<bool>,
990

991
    pub selections: Vec<NodeSelection>,
992
}
993

994
#[derive(Clone, Debug)]
995
pub struct NodeByPkBuilder {
996
    // args - map of column name to value
997
    pub pk_values: HashMap<String, serde_json::Value>,
998

999
    pub _alias: String,
1000

1001
    // metadata
1002
    pub table: Arc<Table>,
1003

1004
    pub selections: Vec<NodeSelection>,
1005
}
1006

1007
#[derive(Clone, Debug)]
1008
pub enum NodeSelection {
1009
    Connection(ConnectionBuilder),
1010
    Node(NodeBuilder),
1011
    Column(ColumnBuilder),
1012
    Function(FunctionBuilder),
1013
    NodeId(NodeIdBuilder),
1014
    Typename { alias: String, typename: String },
1015
}
1016

1017
#[derive(Clone, Debug)]
1018
pub struct NodeIdInstance {
1019
    pub schema_name: String,
1020
    pub table_name: String,
1021
    // Vec matching length of "columns" representing primary key values
1022
    pub values: Vec<serde_json::Value>,
1023
}
1024

1025
impl NodeIdInstance {
1026
    pub fn validate(&self, table: &Table) -> Result<(), String> {
13✔
1027
        // Validate that nodeId belongs to the table being queried
1028
        if self.schema_name != table.schema || self.table_name != table.name {
13✔
1029
            return Err("nodeId belongs to a different collection".to_string());
1✔
1030
        }
12✔
1031
        Ok(())
12✔
1032
    }
13✔
1033
}
1034

1035
#[derive(Clone, Debug)]
1036
pub struct NodeIdBuilder {
1037
    pub alias: String,
1038
    pub schema_name: String,
1039
    pub table_name: String,
1040
    pub columns: Vec<Arc<Column>>,
1041
}
1042

1043
#[derive(Clone, Debug)]
1044
pub struct ColumnBuilder {
1045
    pub alias: String,
1046
    pub column: Arc<Column>,
1047
}
1048

1049
#[derive(Clone, Debug)]
1050
pub struct FunctionBuilder {
1051
    pub alias: String,
1052
    pub function: Arc<Function>,
1053
    pub table: Arc<Table>,
1054
    pub selection: FunctionSelection,
1055
}
1056

1057
#[derive(Clone, Debug)]
1058
pub enum FunctionSelection {
1059
    ScalarSelf,
1060
    Array, // To suport non-scalars this will require an inner type
1061
    Connection(ConnectionBuilder),
1062
    Node(NodeBuilder),
1063
}
1064

1065
fn restrict_allowed_arguments<'a, T>(
1,182✔
1066
    arg_names: &[&str],
1,182✔
1067
    query_field: &graphql_parser::query::Field<'a, T>,
1,182✔
1068
) -> Result<(), String>
1,182✔
1069
where
1,182✔
1070
    T: Text<'a> + Eq + AsRef<str>,
1,182✔
1071
{
1072
    let extra_keys: Vec<&str> = query_field
1,182✔
1073
        .arguments
1,182✔
1074
        .iter()
1,182✔
1075
        .filter(|(input_arg_name, _)| !arg_names.contains(&input_arg_name.as_ref()))
1,182✔
1076
        .map(|(name, _)| name.as_ref())
1,182✔
1077
        .collect();
1,182✔
1078

1079
    match !extra_keys.is_empty() {
1,182✔
1080
        true => Err(format!("Input contains extra keys {:?}", extra_keys)),
1✔
1081
        false => Ok(()),
1,181✔
1082
    }
1083
}
1,182✔
1084

1085
/// Reads the "filter" argument
1086
fn read_argument_filter<'a, T>(
328✔
1087
    field: &__Field,
328✔
1088
    query_field: &graphql_parser::query::Field<'a, T>,
328✔
1089
    variables: &serde_json::Value,
328✔
1090
    variable_definitions: &Vec<VariableDefinition<'a, T>>,
328✔
1091
) -> Result<FilterBuilder, String>
328✔
1092
where
328✔
1093
    T: Text<'a> + Eq + AsRef<str>,
328✔
1094
{
1095
    let validated: gson::Value = read_argument(
328✔
1096
        "filter",
328✔
1097
        field,
328✔
1098
        query_field,
328✔
1099
        variables,
328✔
1100
        variable_definitions,
328✔
1101
    )?;
11✔
1102

1103
    let filter_type = field
317✔
1104
        .get_arg("filter")
317✔
1105
        .expect("failed to get filter argument")
317✔
1106
        .type_()
317✔
1107
        .unmodified_type();
317✔
1108
    if !matches!(filter_type, __Type::FilterEntity(_)) {
317✔
1109
        return Err("Could not locate Filter Entity type".to_string());
×
1110
    }
317✔
1111

1112
    let filter_field_map = input_field_map(&filter_type);
317✔
1113

1114
    let filters = create_filters(&validated, &filter_field_map)?;
317✔
1115

1116
    Ok(FilterBuilder { elems: filters })
317✔
1117
}
328✔
1118

1119
fn create_filters(
376✔
1120
    validated: &gson::Value,
376✔
1121
    filter_field_map: &HashMap<String, __InputValue>,
376✔
1122
) -> Result<Vec<FilterBuilderElem>, String> {
376✔
1123
    let mut filters = vec![];
376✔
1124
    // validated user input kv map
1125
    let kv_map = match validated {
376✔
1126
        gson::Value::Absent | gson::Value::Null => return Ok(filters),
199✔
1127
        gson::Value::Object(kv) => kv,
177✔
1128
        _ => return Err("Filter re-validation error".to_string()),
×
1129
    };
1130

1131
    for (k, op_to_v) in kv_map {
376✔
1132
        // k = str, v = {"eq": 1}
1133
        let filter_iv: &__InputValue = match filter_field_map.get(k) {
199✔
1134
            Some(filter_iv) => filter_iv,
199✔
1135
            None => return Err("Filter re-validation error in filter_iv".to_string()),
×
1136
        };
1137

1138
        match op_to_v {
24✔
1139
            gson::Value::Absent | gson::Value::Null => continue,
×
1140
            gson::Value::Object(filter_op_to_value_map) => {
175✔
1141
                // key `not` can either be a compound filter or a column. We can find out which it is by
1142
                // checking its type. If it is a `not` filter then its type will be __Type::FilterEntity(_)
1143
                // else its type will be __Type::FilterType(_). Refer to the the method
1144
                // crate::graphql::FilterEntityType::input_fields() method for details.
1145
                let is_a_not_filter_type = matches!(filter_iv.type_(), __Type::FilterEntity(_));
175✔
1146
                if k == NOT_FILTER_NAME && is_a_not_filter_type {
175✔
1147
                    if let gson::Value::Object(_) = op_to_v {
8✔
1148
                        let inner_filters = create_filters(op_to_v, filter_field_map)?;
8✔
1149
                        // If there are no inner filters we avoid creating an argumentless `not` expression. i.e. avoid `not()`
1150
                        if !inner_filters.is_empty() {
8✔
1151
                            // Multiple inner filters are implicitly `and`ed together
7✔
1152
                            let inner_filter = FilterBuilderElem::Compound(Box::new(
7✔
1153
                                CompoundFilterBuilder::And(inner_filters),
7✔
1154
                            ));
7✔
1155
                            let filter = FilterBuilderElem::Compound(Box::new(
7✔
1156
                                CompoundFilterBuilder::Not(inner_filter),
7✔
1157
                            ));
7✔
1158
                            filters.push(filter);
7✔
1159
                        }
7✔
1160
                    } else {
1161
                        return Err("Invalid `not` filter".to_string());
×
1162
                    }
1163
                } else {
1164
                    for (filter_op_str, filter_val) in filter_op_to_value_map {
334✔
1165
                        let filter_op = FilterOp::from_str(filter_op_str)?;
167✔
1166

1167
                        // Skip absent
1168
                        // Technically nulls should be treated as literals. It will always filter out all rows
1169
                        // val <op> null is never true
1170
                        if filter_val == &gson::Value::Absent {
167✔
1171
                            continue;
2✔
1172
                        }
165✔
1173

1174
                        let filter_builder =
165✔
1175
                            create_filter_builder_elem(filter_iv, filter_op, filter_val)?;
165✔
1176
                        filters.push(filter_builder);
165✔
1177
                    }
1178
                }
1179
            }
1180
            gson::Value::Array(values) if k == AND_FILTER_NAME || k == OR_FILTER_NAME => {
24✔
1181
                // If there are no inner filters we avoid creating an argumentless `and`/`or` expression
1182
                // which would have been anyways compiled away during transpilation
1183
                if !values.is_empty() {
24✔
1184
                    let mut compound_filters = Vec::with_capacity(values.len());
22✔
1185
                    for value in values {
73✔
1186
                        let inner_filters = create_filters(value, filter_field_map)?;
51✔
1187
                        // Avoid argumentless `and`
1188
                        if !inner_filters.is_empty() {
51✔
1189
                            // Multiple inner filters are implicitly `and`ed together
51✔
1190
                            let inner_filter = FilterBuilderElem::Compound(Box::new(
51✔
1191
                                CompoundFilterBuilder::And(inner_filters),
51✔
1192
                            ));
51✔
1193
                            compound_filters.push(inner_filter);
51✔
1194
                        }
51✔
1195
                    }
1196

1197
                    let filter_builder = if k == AND_FILTER_NAME {
22✔
1198
                        FilterBuilderElem::Compound(Box::new(CompoundFilterBuilder::And(
10✔
1199
                            compound_filters,
10✔
1200
                        )))
10✔
1201
                    } else if k == OR_FILTER_NAME {
12✔
1202
                        FilterBuilderElem::Compound(Box::new(CompoundFilterBuilder::Or(
12✔
1203
                            compound_filters,
12✔
1204
                        )))
12✔
1205
                    } else {
1206
                        return Err(
×
1207
                            "Only `and` and `or` filters are allowed to take an array as input."
×
1208
                                .to_string(),
×
1209
                        );
×
1210
                    };
1211

1212
                    filters.push(filter_builder);
22✔
1213
                }
2✔
1214
            }
1215
            _ => return Err("Filter re-validation errror op_to_value map".to_string()),
×
1216
        }
1217
    }
1218
    Ok(filters)
177✔
1219
}
376✔
1220

1221
fn create_filter_builder_elem(
165✔
1222
    filter_iv: &__InputValue,
165✔
1223
    filter_op: FilterOp,
165✔
1224
    filter_val: &gson::Value,
165✔
1225
) -> Result<FilterBuilderElem, String> {
165✔
1226
    Ok(match &filter_iv.sql_type {
165✔
1227
        Some(NodeSQLType::Column(col)) => FilterBuilderElem::Column {
160✔
1228
            column: Arc::clone(col),
160✔
1229
            op: filter_op,
160✔
1230
            value: gson::gson_to_json(filter_val)?,
160✔
1231
        },
1232
        Some(NodeSQLType::NodeId(_)) => {
1233
            FilterBuilderElem::NodeId(parse_node_id(filter_val.clone())?)
5✔
1234
        }
1235
        _ => return Err("Filter type error, attempted filter on non-column".to_string()),
×
1236
    })
1237
}
165✔
1238

1239
/// Reads the "orderBy" argument. Auto-appends the primary key
1240
fn read_argument_order_by<'a, T>(
274✔
1241
    field: &__Field,
274✔
1242
    query_field: &graphql_parser::query::Field<'a, T>,
274✔
1243
    variables: &serde_json::Value,
274✔
1244
    variable_definitions: &Vec<VariableDefinition<'a, T>>,
274✔
1245
) -> Result<OrderByBuilder, String>
274✔
1246
where
274✔
1247
    T: Text<'a> + Eq + AsRef<str>,
274✔
1248
{
1249
    // [{"id": "DescNullsLast"}]
1250
    let validated: gson::Value = read_argument(
274✔
1251
        "orderBy",
274✔
1252
        field,
274✔
1253
        query_field,
274✔
1254
        variables,
274✔
1255
        variable_definitions,
274✔
1256
    )?;
12✔
1257

1258
    // [<Table>OrderBy!]
1259
    let order_type: OrderByEntityType = match field
262✔
1260
        .get_arg("orderBy")
262✔
1261
        .expect("failed to get orderBy argument")
262✔
1262
        .type_()
262✔
1263
        .unmodified_type()
262✔
1264
    {
1265
        __Type::OrderByEntity(order_entity) => order_entity,
262✔
1266
        _ => return Err("Could not locate OrderBy Entity type".to_string()),
×
1267
    };
1268

1269
    let mut orders = vec![];
262✔
1270

1271
    let order_field_map = input_field_map(&__Type::OrderByEntity(order_type.clone()));
262✔
1272

1273
    // validated user input kv map
1274
    match validated {
262✔
1275
        gson::Value::Null | gson::Value::Absent => (),
234✔
1276
        gson::Value::Array(x_arr) => {
28✔
1277
            for elem in x_arr.iter() {
42✔
1278
                // {"id", DescNullsLast}
1279
                match elem {
42✔
1280
                    gson::Value::Absent | gson::Value::Null => continue,
×
1281
                    gson::Value::Object(obj) => {
42✔
1282
                        for (column_field_name, order_direction_json) in obj.iter() {
44✔
1283
                            let order_direction = match order_direction_json {
44✔
1284
                                gson::Value::Absent | gson::Value::Null => continue,
4✔
1285
                                gson::Value::String(x) => OrderDirection::from_str(x)?,
40✔
1286
                                _ => return Err("Order re-validation error 6".to_string()),
×
1287
                            };
1288
                            let column_input_value: &__InputValue =
40✔
1289
                                match order_field_map.get(column_field_name) {
40✔
1290
                                    Some(input_field) => input_field,
40✔
1291
                                    None => return Err("Order re-validation error 3".to_string()),
×
1292
                                };
1293

1294
                            match &column_input_value.sql_type {
40✔
1295
                                Some(NodeSQLType::Column(col)) => {
40✔
1296
                                    let order_rec = OrderByBuilderElem {
40✔
1297
                                        column: Arc::clone(col),
40✔
1298
                                        direction: order_direction,
40✔
1299
                                    };
40✔
1300
                                    orders.push(order_rec);
40✔
1301
                                }
40✔
1302
                                _ => return Err("Order re-validation error 4".to_string()),
×
1303
                            }
1304
                        }
1305
                    }
1306
                    _ => return Err("OrderBy re-validation errror 1".to_string()),
×
1307
                }
1308
            }
1309
        }
1310
        _ => return Err("OrderBy re-validation errror".to_string()),
×
1311
    };
1312

1313
    // To acheive consistent pagination, sorting should always include primary key
1314
    let pkey = &order_type
262✔
1315
        .table
262✔
1316
        .primary_key()
262✔
1317
        .ok_or_else(|| "Found table with no primary key".to_string())?;
262✔
1318

1319
    for col_name in &pkey.column_names {
527✔
1320
        for col in &order_type.table.columns {
268✔
1321
            if &col.name == col_name {
268✔
1322
                let order_rec = OrderByBuilderElem {
265✔
1323
                    column: Arc::clone(col),
265✔
1324
                    direction: OrderDirection::AscNullsLast,
265✔
1325
                };
265✔
1326
                orders.push(order_rec);
265✔
1327
                break;
265✔
1328
            }
3✔
1329
        }
1330
    }
1331
    Ok(OrderByBuilder { elems: orders })
262✔
1332
}
274✔
1333

1334
/// Reads "before" and "after" cursor arguments
1335
fn read_argument_cursor<'a, T>(
583✔
1336
    arg_name: &str,
583✔
1337
    field: &__Field,
583✔
1338
    query_field: &graphql_parser::query::Field<'a, T>,
583✔
1339
    variables: &serde_json::Value,
583✔
1340
    variable_definitions: &Vec<VariableDefinition<'a, T>>,
583✔
1341
) -> Result<Option<Cursor>, String>
583✔
1342
where
583✔
1343
    T: Text<'a> + Eq + AsRef<str>,
583✔
1344
{
1345
    let validated: gson::Value = read_argument(
583✔
1346
        arg_name,
583✔
1347
        field,
583✔
1348
        query_field,
583✔
1349
        variables,
583✔
1350
        variable_definitions,
583✔
UNCOV
1351
    )?;
×
1352
    let _: Scalar = match field
583✔
1353
        .get_arg(arg_name)
583✔
1354
        .unwrap_or_else(|| panic!("failed to get {} argument", arg_name))
583✔
1355
        .type_()
583✔
1356
        .unmodified_type()
583✔
1357
    {
1358
        __Type::Scalar(x) => x,
583✔
1359
        _ => return Err(format!("Could not argument {}", arg_name)),
×
1360
    };
1361

1362
    match validated {
583✔
1363
        // Technically null should be treated as a literal here causing no result to return
1364
        // however:
1365
        // - there is no reason to ever intentionally pass a null literal to this argument
1366
        // - alternate implementations treat null as absent for this argument
1367
        // - passing null appears to be a common mistake
1368
        // so for backwards compatibility and ease of use, we'll treat null literal as absent
1369
        gson::Value::Absent | gson::Value::Null => Ok(None),
556✔
1370
        gson::Value::String(x) => Ok(Some(Cursor::from_str(&x)?)),
27✔
1371
        _ => Err("Cursor re-validation errror".to_string()),
×
1372
    }
1373
}
583✔
1374

1375
pub fn to_connection_builder<'a, T>(
299✔
1376
    field: &__Field,
299✔
1377
    query_field: &graphql_parser::query::Field<'a, T>,
299✔
1378
    fragment_definitions: &Vec<FragmentDefinition<'a, T>>,
299✔
1379
    variables: &serde_json::Value,
299✔
1380
    extra_allowed_args: &[&str],
299✔
1381
    variable_definitions: &Vec<VariableDefinition<'a, T>>,
299✔
1382
) -> Result<ConnectionBuilder, String>
299✔
1383
where
299✔
1384
    T: Text<'a> + Eq + AsRef<str> + Clone,
299✔
1385
    T::Value: Hash,
299✔
1386
{
1387
    let type_ = field.type_().unmodified_type();
299✔
1388
    let type_ = type_.return_type();
299✔
1389
    let type_name = type_
299✔
1390
        .name()
299✔
1391
        .ok_or("Encountered type without name in connection builder")?;
299✔
1392
    let field_map = field_map(type_);
299✔
1393
    let alias = alias_or_name(query_field);
299✔
1394

1395
    match &type_ {
299✔
1396
        __Type::Connection(xtype) => {
299✔
1397
            // Raise for disallowed arguments
1398
            let mut allowed_args = vec![
299✔
1399
                "first", "last", "before", "after", "offset", "filter", "orderBy",
299✔
1400
            ];
1401
            allowed_args.extend(extra_allowed_args);
299✔
1402
            restrict_allowed_arguments(&allowed_args, query_field)?;
299✔
1403

1404
            // TODO: only one of first/last, before/after provided
1405
            let first: gson::Value =
296✔
1406
                read_argument("first", field, query_field, variables, variable_definitions)?;
298✔
1407
            let first: Option<u64> = match first {
295✔
1408
                gson::Value::Absent | gson::Value::Null => None,
251✔
1409
                gson::Value::Number(gson::Number::Integer(n)) if n < 0 => {
45✔
1410
                    return Err("`first` must be an unsigned integer".to_string())
1✔
1411
                }
1412
                gson::Value::Number(gson::Number::Integer(n)) => Some(n as u64),
44✔
1413
                _ => {
1414
                    return Err("Internal Error: failed to parse validated first".to_string());
×
1415
                }
1416
            };
1417

1418
            let last: gson::Value =
293✔
1419
                read_argument("last", field, query_field, variables, variable_definitions)?;
295✔
1420
            let last: Option<u64> = match last {
292✔
1421
                gson::Value::Absent | gson::Value::Null => None,
274✔
1422
                gson::Value::Number(gson::Number::Integer(n)) if n < 0 => {
19✔
1423
                    return Err("`last` must be an unsigned integer".to_string())
1✔
1424
                }
1425
                gson::Value::Number(gson::Number::Integer(n)) => Some(n as u64),
18✔
1426
                _ => {
1427
                    return Err("Internal Error: failed to parse validated last".to_string());
×
1428
                }
1429
            };
1430

1431
            let offset: gson::Value = read_argument(
292✔
1432
                "offset",
292✔
1433
                field,
292✔
1434
                query_field,
292✔
1435
                variables,
292✔
1436
                variable_definitions,
292✔
UNCOV
1437
            )?;
×
1438
            let offset: Option<u64> = match offset {
292✔
1439
                gson::Value::Absent | gson::Value::Null => None,
286✔
1440
                gson::Value::Number(gson::Number::Integer(n)) if n < 0 => {
6✔
1441
                    return Err("`offset` must be an unsigned integer".to_string())
×
1442
                }
1443
                gson::Value::Number(gson::Number::Integer(n)) => Some(n as u64),
6✔
1444
                _ => {
1445
                    return Err("Internal Error: failed to parse validated offset".to_string());
×
1446
                }
1447
            };
1448

1449
            let max_rows = xtype
292✔
1450
                .schema
292✔
1451
                .context
292✔
1452
                .schemas
292✔
1453
                .values()
292✔
1454
                .find(|s| s.oid == xtype.table.schema_oid)
292✔
1455
                .map(|schema| xtype.table.max_rows(schema))
292✔
1456
                .unwrap_or(30);
292✔
1457

1458
            let before: Option<Cursor> = read_argument_cursor(
292✔
1459
                "before",
292✔
1460
                field,
292✔
1461
                query_field,
292✔
1462
                variables,
292✔
1463
                variable_definitions,
292✔
1464
            )?;
1✔
1465
            let after: Option<Cursor> =
291✔
1466
                read_argument_cursor("after", field, query_field, variables, variable_definitions)?;
291✔
1467

1468
            // Validate compatible input arguments
1469
            if first.is_some() && last.is_some() {
291✔
1470
                return Err("only one of \"first\" and \"last\" may be provided".to_string());
1✔
1471
            } else if before.is_some() && after.is_some() {
290✔
1472
                return Err("only one of \"before\" and \"after\" may be provided".to_string());
1✔
1473
            } else if first.is_some() && before.is_some() {
289✔
1474
                return Err("\"first\" may only be used with \"after\"".to_string());
1✔
1475
            } else if last.is_some() && after.is_some() {
288✔
1476
                return Err("\"last\" may only be used with \"before\"".to_string());
1✔
1477
            } else if offset.is_some() && (last.is_some() || before.is_some()) {
287✔
1478
                // Only support forward pagination with offset
1479
                return Err("\"offset\" may only be used with \"first\" and \"after\"".to_string());
2✔
1480
            }
285✔
1481

1482
            let filter: FilterBuilder =
274✔
1483
                read_argument_filter(field, query_field, variables, variable_definitions)?;
285✔
1484
            let order_by: OrderByBuilder =
262✔
1485
                read_argument_order_by(field, query_field, variables, variable_definitions)?;
274✔
1486

1487
            let mut builder_fields: Vec<ConnectionSelection> = vec![];
262✔
1488

1489
            let selection_fields = normalize_selection_set(
262✔
1490
                &query_field.selection_set,
262✔
1491
                fragment_definitions,
262✔
1492
                &type_name,
262✔
1493
                variables,
262✔
1494
            )?;
1✔
1495

1496
            for selection_field in selection_fields {
541✔
1497
                match field_map.get(selection_field.name.as_ref()) {
293✔
1498
                    None => {
1499
                        let error = if selection_field.name.as_ref() == "aggregate" {
4✔
1500
                            "enable the aggregate directive to use aggregates"
1✔
1501
                        } else {
1502
                            "unknown field in connection"
3✔
1503
                        }
1504
                        .to_string();
4✔
1505
                        return Err(error);
4✔
1506
                    }
1507
                    Some(f) => builder_fields.push(match &f.type_.unmodified_type() {
289✔
1508
                        __Type::Edge(_) => ConnectionSelection::Edge(to_edge_builder(
229✔
1509
                            f,
229✔
1510
                            &selection_field,
229✔
1511
                            fragment_definitions,
229✔
1512
                            variables,
229✔
1513
                            variable_definitions,
229✔
1514
                        )?),
8✔
1515
                        __Type::PageInfo(_) => ConnectionSelection::PageInfo(to_page_info_builder(
23✔
1516
                            f,
23✔
1517
                            &selection_field,
23✔
1518
                            fragment_definitions,
23✔
1519
                            variables,
23✔
UNCOV
1520
                        )?),
×
1521
                        __Type::Aggregate(_) => {
1522
                            ConnectionSelection::Aggregate(to_aggregate_builder(
22✔
1523
                                f,
22✔
1524
                                &selection_field,
22✔
1525
                                fragment_definitions,
22✔
1526
                                variables,
22✔
1527
                            )?)
1✔
1528
                        }
1529
                        __Type::Scalar(Scalar::Int) => {
1530
                            if selection_field.name.as_ref() == "totalCount" {
13✔
1531
                                ConnectionSelection::TotalCount {
13✔
1532
                                    alias: alias_or_name(&selection_field),
13✔
1533
                                }
13✔
1534
                            } else {
1535
                                return Err(format!(
×
1536
                                    "Unsupported field type for connection field {}",
×
1537
                                    selection_field.name.as_ref()
×
1538
                                ));
×
1539
                            }
1540
                        }
1541
                        __Type::Scalar(Scalar::String(None)) => {
1542
                            if selection_field.name.as_ref() == "__typename" {
2✔
1543
                                ConnectionSelection::Typename {
2✔
1544
                                    alias: alias_or_name(&selection_field),
2✔
1545
                                    typename: xtype
2✔
1546
                                        .name()
2✔
1547
                                        .expect("connection type should have a name"),
2✔
1548
                                }
2✔
1549
                            } else {
1550
                                return Err(format!(
×
1551
                                    "Unsupported field type for connection field {}",
×
1552
                                    selection_field.name.as_ref()
×
1553
                                ));
×
1554
                            }
1555
                        }
1556
                        _ => {
1557
                            return Err(format!(
×
1558
                                "unknown field type on connection: {}",
×
1559
                                selection_field.name.as_ref()
×
1560
                            ))
×
1561
                        }
1562
                    }),
1563
                }
1564
            }
1565

1566
            Ok(ConnectionBuilder {
248✔
1567
                alias,
248✔
1568
                source: ConnectionBuilderSource {
248✔
1569
                    table: Arc::clone(&xtype.table),
248✔
1570
                    fkey: xtype.fkey.clone(),
248✔
1571
                },
248✔
1572
                first,
248✔
1573
                last,
248✔
1574
                before,
248✔
1575
                offset,
248✔
1576
                after,
248✔
1577
                filter,
248✔
1578
                order_by,
248✔
1579
                selections: builder_fields,
248✔
1580
                max_rows,
248✔
1581
            })
248✔
1582
        }
1583
        _ => Err(format!(
×
1584
            "can not build query for non-connection type {:?}",
×
1585
            type_.name()
×
1586
        )),
×
1587
    }
1588
}
299✔
1589

1590
fn to_aggregate_builder<'a, T>(
22✔
1591
    field: &__Field,
22✔
1592
    query_field: &graphql_parser::query::Field<'a, T>,
22✔
1593
    fragment_definitions: &Vec<FragmentDefinition<'a, T>>,
22✔
1594
    variables: &serde_json::Value,
22✔
1595
) -> Result<AggregateBuilder, String>
22✔
1596
where
22✔
1597
    T: Text<'a> + Eq + AsRef<str> + Clone,
22✔
1598
    T::Value: Hash,
22✔
1599
{
1600
    let type_ = field.type_().unmodified_type();
22✔
1601
    let __Type::Aggregate(ref _agg_type) = type_ else {
22✔
1602
        return Err("Internal Error: Expected AggregateType in to_aggregate_builder".to_string());
×
1603
    };
1604

1605
    let alias = alias_or_name(query_field);
22✔
1606
    let mut selections = Vec::new();
22✔
1607
    let field_map = field_map(&type_); // Get fields of the AggregateType (count, sum, avg, etc.)
22✔
1608

1609
    let type_name = type_.name().ok_or("Aggregate type has no name")?;
22✔
1610

1611
    let selection_fields = normalize_selection_set(
22✔
1612
        &query_field.selection_set,
22✔
1613
        fragment_definitions,
22✔
1614
        &type_name,
22✔
1615
        variables,
22✔
UNCOV
1616
    )?;
×
1617

1618
    for selection_field in selection_fields {
74✔
1619
        let field_name = selection_field.name.as_ref();
53✔
1620
        let sub_field = field_map.get(field_name).ok_or(format!(
53✔
1621
            "Unknown field \"{}\" selected on type \"{}\"",
53✔
1622
            field_name, type_name
UNCOV
1623
        ))?;
×
1624
        let sub_alias = alias_or_name(&selection_field);
53✔
1625

1626
        let col_selections = if field_name == "sum"
53✔
1627
            || field_name == "avg"
45✔
1628
            || field_name == "min"
39✔
1629
            || field_name == "max"
29✔
1630
        {
1631
            to_aggregate_column_builders(
33✔
1632
                sub_field,
33✔
1633
                &selection_field,
33✔
1634
                fragment_definitions,
33✔
1635
                variables,
33✔
1636
            )?
1✔
1637
        } else {
1638
            vec![]
20✔
1639
        };
1640

1641
        selections.push(match field_name {
52✔
1642
            "count" => AggregateSelection::Count { alias: sub_alias },
52✔
1643
            "sum" => AggregateSelection::Sum {
32✔
1644
                alias: sub_alias,
8✔
1645
                column_builders: col_selections,
8✔
1646
            },
8✔
1647
            "avg" => AggregateSelection::Avg {
24✔
1648
                alias: sub_alias,
6✔
1649
                column_builders: col_selections,
6✔
1650
            },
6✔
1651
            "min" => AggregateSelection::Min {
18✔
1652
                alias: sub_alias,
9✔
1653
                column_builders: col_selections,
9✔
1654
            },
9✔
1655
            "max" => AggregateSelection::Max {
9✔
1656
                alias: sub_alias,
9✔
1657
                column_builders: col_selections,
9✔
1658
            },
9✔
1659
            "__typename" => AggregateSelection::Typename {
×
1660
                alias: sub_alias,
×
1661
                typename: field
×
1662
                    .type_()
×
1663
                    .name()
×
1664
                    .ok_or("Name for aggregate field's type not found")?
×
1665
                    .to_string(),
×
1666
            },
1667
            _ => return Err(format!("Unknown aggregate field: {}", field_name)),
×
1668
        })
1669
    }
1670

1671
    Ok(AggregateBuilder { alias, selections })
21✔
1672
}
22✔
1673

1674
fn to_aggregate_column_builders<'a, T>(
33✔
1675
    field: &__Field,
33✔
1676
    query_field: &graphql_parser::query::Field<'a, T>,
33✔
1677
    fragment_definitions: &Vec<FragmentDefinition<'a, T>>,
33✔
1678
    variables: &serde_json::Value,
33✔
1679
) -> Result<Vec<ColumnBuilder>, String>
33✔
1680
where
33✔
1681
    T: Text<'a> + Eq + AsRef<str> + Clone,
33✔
1682
    T::Value: Hash,
33✔
1683
{
1684
    let type_ = field.type_().unmodified_type();
33✔
1685
    let __Type::AggregateNumeric(_) = type_ else {
33✔
1686
        return Err("Internal Error: Expected AggregateNumericType".to_string());
×
1687
    };
1688
    let mut column_builers = Vec::new();
33✔
1689
    let field_map = field_map(&type_);
33✔
1690
    let type_name = type_.name().ok_or("AggregateNumeric type has no name")?;
33✔
1691
    let selection_fields = normalize_selection_set(
33✔
1692
        &query_field.selection_set,
33✔
1693
        fragment_definitions,
33✔
1694
        &type_name,
33✔
1695
        variables,
33✔
UNCOV
1696
    )?;
×
1697

1698
    for selection_field in selection_fields {
73✔
1699
        let col_name = selection_field.name.as_ref();
41✔
1700
        let sub_field = field_map.get(col_name).ok_or_else(|| {
41✔
1701
            format!(
1✔
1702
                "Unknown or invalid field \"{}\" selected on type \"{}\"",
1✔
1703
                col_name, type_name
1704
            )
1705
        })?;
1✔
1706

1707
        let __Type::Scalar(_) = sub_field.type_().unmodified_type() else {
40✔
1708
            return Err(format!(
×
1709
                "Field \"{}\" on type \"{}\" is not a scalar column",
×
1710
                col_name, type_name
×
1711
            ));
×
1712
        };
1713
        let Some(NodeSQLType::Column(column)) = &sub_field.sql_type else {
40✔
1714
            return Err(format!(
×
1715
                "Internal error: Missing column info for aggregate field '{}'",
×
1716
                col_name
×
1717
            ));
×
1718
        };
1719

1720
        let alias = alias_or_name(&selection_field);
40✔
1721

1722
        column_builers.push(ColumnBuilder {
40✔
1723
            alias,
40✔
1724
            column: Arc::clone(column),
40✔
1725
        });
40✔
1726
    }
1727
    Ok(column_builers)
32✔
1728
}
33✔
1729

1730
fn to_page_info_builder<'a, T>(
23✔
1731
    field: &__Field,
23✔
1732
    query_field: &graphql_parser::query::Field<'a, T>,
23✔
1733
    fragment_definitions: &Vec<FragmentDefinition<'a, T>>,
23✔
1734
    variables: &serde_json::Value,
23✔
1735
) -> Result<PageInfoBuilder, String>
23✔
1736
where
23✔
1737
    T: Text<'a> + Eq + AsRef<str> + Clone,
23✔
1738
    T::Value: Hash,
23✔
1739
{
1740
    let type_ = field.type_().unmodified_type();
23✔
1741
    let type_name = type_.name().ok_or(format!(
23✔
1742
        "Encountered type without name in page info builder: {:?}",
23✔
1743
        type_
UNCOV
1744
    ))?;
×
1745
    let field_map = field_map(&type_);
23✔
1746
    let alias = alias_or_name(query_field);
23✔
1747

1748
    match type_ {
23✔
1749
        __Type::PageInfo(xtype) => {
23✔
1750
            let mut builder_fields: Vec<PageInfoSelection> = vec![];
23✔
1751

1752
            let selection_fields = normalize_selection_set(
23✔
1753
                &query_field.selection_set,
23✔
1754
                fragment_definitions,
23✔
1755
                &type_name,
23✔
1756
                variables,
23✔
UNCOV
1757
            )?;
×
1758

1759
            for selection_field in selection_fields {
98✔
1760
                match field_map.get(selection_field.name.as_ref()) {
75✔
1761
                    None => return Err("unknown field in pageInfo".to_string()),
×
1762
                    Some(f) => builder_fields.push(match f.name().as_ref() {
75✔
1763
                        "startCursor" => PageInfoSelection::StartCursor {
75✔
1764
                            alias: alias_or_name(&selection_field),
18✔
1765
                        },
18✔
1766
                        "endCursor" => PageInfoSelection::EndCursor {
57✔
1767
                            alias: alias_or_name(&selection_field),
18✔
1768
                        },
18✔
1769
                        "hasPreviousPage" => PageInfoSelection::HasPreviousPage {
39✔
1770
                            alias: alias_or_name(&selection_field),
19✔
1771
                        },
19✔
1772
                        "hasNextPage" => PageInfoSelection::HasNextPage {
20✔
1773
                            alias: alias_or_name(&selection_field),
19✔
1774
                        },
19✔
1775
                        "__typename" => PageInfoSelection::Typename {
1✔
1776
                            alias: alias_or_name(&selection_field),
1✔
1777
                            typename: xtype.name().expect("page info type should have a name"),
1✔
1778
                        },
1✔
1779
                        _ => return Err("unexpected field type on pageInfo".to_string()),
×
1780
                    }),
1781
                }
1782
            }
1783
            Ok(PageInfoBuilder {
23✔
1784
                alias,
23✔
1785
                selections: builder_fields,
23✔
1786
            })
23✔
1787
        }
1788
        _ => Err("can not build query for non-PageInfo type".to_string()),
×
1789
    }
1790
}
23✔
1791

1792
fn to_edge_builder<'a, T>(
229✔
1793
    field: &__Field,
229✔
1794
    query_field: &graphql_parser::query::Field<'a, T>,
229✔
1795
    fragment_definitions: &Vec<FragmentDefinition<'a, T>>,
229✔
1796
    variables: &serde_json::Value,
229✔
1797
    variable_definitions: &Vec<VariableDefinition<'a, T>>,
229✔
1798
) -> Result<EdgeBuilder, String>
229✔
1799
where
229✔
1800
    T: Text<'a> + Eq + AsRef<str> + Clone,
229✔
1801
    T::Value: Hash,
229✔
1802
{
1803
    let type_ = field.type_().unmodified_type();
229✔
1804
    let type_name = type_.name().ok_or(format!(
229✔
1805
        "Encountered type without name in edge builder: {:?}",
229✔
1806
        type_
UNCOV
1807
    ))?;
×
1808
    let field_map = field_map(&type_);
229✔
1809
    let alias = alias_or_name(query_field);
229✔
1810

1811
    match type_ {
229✔
1812
        __Type::Edge(xtype) => {
229✔
1813
            let mut builder_fields = vec![];
229✔
1814

1815
            let selection_fields = normalize_selection_set(
229✔
1816
                &query_field.selection_set,
229✔
1817
                fragment_definitions,
229✔
1818
                &type_name,
229✔
1819
                variables,
229✔
UNCOV
1820
            )?;
×
1821

1822
            for selection_field in selection_fields {
476✔
1823
                match field_map.get(selection_field.name.as_ref()) {
255✔
1824
                    None => return Err("unknown field in edge".to_string()),
×
1825
                    Some(f) => builder_fields.push(match &f.type_.unmodified_type() {
255✔
1826
                        __Type::Node(_) => {
1827
                            let node_builder = to_node_builder(
228✔
1828
                                f,
228✔
1829
                                &selection_field,
228✔
1830
                                fragment_definitions,
228✔
1831
                                variables,
228✔
1832
                                &[],
228✔
1833
                                variable_definitions,
228✔
1834
                            )?;
8✔
1835
                            EdgeSelection::Node(node_builder)
220✔
1836
                        }
1837
                        _ => match f.name().as_ref() {
27✔
1838
                            "cursor" => EdgeSelection::Cursor {
27✔
1839
                                alias: alias_or_name(&selection_field),
25✔
1840
                            },
25✔
1841
                            "__typename" => EdgeSelection::Typename {
2✔
1842
                                alias: alias_or_name(&selection_field),
2✔
1843
                                typename: xtype.name().expect("edge type should have a name"),
2✔
1844
                            },
2✔
1845
                            _ => return Err("unexpected field type on edge".to_string()),
×
1846
                        },
1847
                    }),
1848
                }
1849
            }
1850
            Ok(EdgeBuilder {
221✔
1851
                alias,
221✔
1852
                selections: builder_fields,
221✔
1853
            })
221✔
1854
        }
1855
        _ => Err("can not build query for non-edge type".to_string()),
×
1856
    }
1857
}
229✔
1858

1859
pub fn to_node_builder<'a, T>(
354✔
1860
    field: &__Field,
354✔
1861
    query_field: &graphql_parser::query::Field<'a, T>,
354✔
1862
    fragment_definitions: &Vec<FragmentDefinition<'a, T>>,
354✔
1863
    variables: &serde_json::Value,
354✔
1864
    extra_allowed_args: &[&str],
354✔
1865
    variable_definitions: &Vec<VariableDefinition<'a, T>>,
354✔
1866
) -> Result<NodeBuilder, String>
354✔
1867
where
354✔
1868
    T: Text<'a> + Eq + AsRef<str> + Clone,
354✔
1869
    T::Value: Hash,
354✔
1870
{
1871
    let type_ = field.type_().unmodified_type();
354✔
1872

1873
    let alias = alias_or_name(query_field);
354✔
1874

1875
    let xtype: NodeType = match type_.return_type() {
354✔
1876
        __Type::Node(xtype) => {
344✔
1877
            restrict_allowed_arguments(extra_allowed_args, query_field)?;
344✔
1878
            xtype.clone()
344✔
1879
        }
1880
        __Type::NodeInterface(node_interface) => {
10✔
1881
            restrict_allowed_arguments(&["nodeId"], query_field)?;
10✔
1882
            // The nodeId argument is only valid on the entrypoint field for Node
1883
            // relationships to "node" e.g. within edges, do not have any arguments
1884
            let node_id: NodeIdInstance =
8✔
1885
                read_argument_node_id(field, query_field, variables, variable_definitions)?;
10✔
1886

1887
            let possible_types: Vec<__Type> = node_interface.possible_types().unwrap_or(vec![]);
8✔
1888
            let xtype = possible_types.iter().find_map(|x| match x {
14✔
1889
                __Type::Node(node_type)
14✔
1890
                    if node_type.table.schema == node_id.schema_name
14✔
1891
                        && node_type.table.name == node_id.table_name =>
14✔
1892
                {
1893
                    Some(node_type)
8✔
1894
                }
1895
                _ => None,
6✔
1896
            });
14✔
1897

1898
            match xtype {
8✔
1899
                Some(x) => x.clone(),
8✔
1900
                None => {
1901
                    return Err(
×
1902
                        "Collection referenced by nodeId did not match any known collection"
×
1903
                            .to_string(),
×
1904
                    );
×
1905
                }
1906
            }
1907
        }
1908
        _ => {
1909
            return Err("can not build query for non-node type".to_string());
×
1910
        }
1911
    };
1912

1913
    let type_name = xtype
352✔
1914
        .name()
352✔
1915
        .ok_or("Encountered type without name in node builder")?;
352✔
1916

1917
    let field_map = field_map(&__Type::Node(xtype.clone()));
352✔
1918

1919
    let mut builder_fields = vec![];
352✔
1920
    let mut allowed_args = vec!["nodeId"];
352✔
1921
    allowed_args.extend(extra_allowed_args);
352✔
1922
    restrict_allowed_arguments(&allowed_args, query_field)?;
352✔
1923

1924
    // The nodeId argument is only valid on the entrypoint field for Node
1925
    // relationships to "node" e.g. within edges, do not have any arguments
1926
    let node_id: Option<NodeIdInstance> = match field.get_arg("nodeId").is_some() {
352✔
1927
        true => Some(read_argument_node_id(
8✔
1928
            field,
8✔
1929
            query_field,
8✔
1930
            variables,
8✔
1931
            variable_definitions,
8✔
UNCOV
1932
        )?),
×
1933
        false => None,
344✔
1934
    };
1935

1936
    let selection_fields = normalize_selection_set(
352✔
1937
        &query_field.selection_set,
352✔
1938
        fragment_definitions,
352✔
1939
        &type_name,
352✔
1940
        variables,
352✔
1941
    )?;
4✔
1942

1943
    for selection_field in selection_fields {
1,314✔
1944
        match field_map.get(selection_field.name.as_ref()) {
972✔
1945
            None => {
1946
                return Err(format!(
4✔
1947
                    "Unknown field '{}' on type '{}'",
4✔
1948
                    selection_field.name.as_ref(),
4✔
1949
                    &type_name
4✔
1950
                ))
4✔
1951
            }
1952
            Some(f) => {
968✔
1953
                let alias = alias_or_name(&selection_field);
968✔
1954

1955
                let node_selection = match &f.sql_type {
968✔
1956
                    Some(node_sql_type) => match node_sql_type {
902✔
1957
                        NodeSQLType::Column(col) => NodeSelection::Column(ColumnBuilder {
864✔
1958
                            alias,
864✔
1959
                            column: Arc::clone(col),
864✔
1960
                        }),
864✔
1961
                        NodeSQLType::Function(func) => {
17✔
1962
                            let function_selection = match &f.type_() {
17✔
1963
                                __Type::Scalar(_) => FunctionSelection::ScalarSelf,
12✔
1964
                                __Type::List(_) => FunctionSelection::Array,
1✔
1965
                                __Type::Node(_) => {
1966
                                    let node_builder = to_node_builder(
3✔
1967
                                        f,
3✔
1968
                                        &selection_field,
3✔
1969
                                        fragment_definitions,
3✔
1970
                                        variables,
3✔
1971
                                        &[],
3✔
1972
                                        variable_definitions,
3✔
1973
                                        // TODO need ref to fkey here
UNCOV
1974
                                    )?;
×
1975
                                    FunctionSelection::Node(node_builder)
3✔
1976
                                }
1977
                                __Type::Connection(_) => {
1978
                                    let connection_builder = to_connection_builder(
1✔
1979
                                        f,
1✔
1980
                                        &selection_field,
1✔
1981
                                        fragment_definitions,
1✔
1982
                                        variables,
1✔
1983
                                        &[], // TODO need ref to fkey here
1✔
1984
                                        variable_definitions,
1✔
UNCOV
1985
                                    )?;
×
1986
                                    FunctionSelection::Connection(connection_builder)
1✔
1987
                                }
1988
                                _ => return Err("invalid return type from function".to_string()),
×
1989
                            };
1990
                            NodeSelection::Function(FunctionBuilder {
17✔
1991
                                alias,
17✔
1992
                                function: Arc::clone(func),
17✔
1993
                                table: Arc::clone(&xtype.table),
17✔
1994
                                selection: function_selection,
17✔
1995
                            })
17✔
1996
                        }
1997
                        NodeSQLType::NodeId(pkey_columns) => {
21✔
1998
                            NodeSelection::NodeId(NodeIdBuilder {
21✔
1999
                                alias,
21✔
2000
                                columns: pkey_columns.clone(), // interior is arc
21✔
2001
                                table_name: xtype.table.name.clone(),
21✔
2002
                                schema_name: xtype.table.schema.clone(),
21✔
2003
                            })
21✔
2004
                        }
2005
                    },
2006
                    _ => match f.name().as_ref() {
66✔
2007
                        "__typename" => NodeSelection::Typename {
66✔
2008
                            alias: alias_or_name(&selection_field),
10✔
2009
                            typename: xtype.name().expect("node type should have a name"),
10✔
2010
                        },
10✔
2011
                        _ => match f.type_().unmodified_type() {
56✔
2012
                            __Type::Connection(_) => {
2013
                                let con_builder = to_connection_builder(
22✔
2014
                                    f,
22✔
2015
                                    &selection_field,
22✔
2016
                                    fragment_definitions,
22✔
2017
                                    variables,
22✔
2018
                                    &[],
22✔
2019
                                    variable_definitions,
22✔
2020
                                );
2021
                                NodeSelection::Connection(con_builder?)
22✔
2022
                            }
2023
                            __Type::Node(_) => {
2024
                                let node_builder = to_node_builder(
34✔
2025
                                    f,
34✔
2026
                                    &selection_field,
34✔
2027
                                    fragment_definitions,
34✔
2028
                                    variables,
34✔
2029
                                    &[],
34✔
2030
                                    variable_definitions,
34✔
2031
                                );
2032
                                NodeSelection::Node(node_builder?)
34✔
2033
                            }
2034
                            _ => {
2035
                                return Err(format!("unexpected field type on node {}", f.name()));
×
2036
                            }
2037
                        },
2038
                    },
2039
                };
2040
                builder_fields.push(node_selection);
966✔
2041
            }
2042
        }
2043
    }
2044
    Ok(NodeBuilder {
342✔
2045
        node_id,
342✔
2046
        alias,
342✔
2047
        table: Arc::clone(&xtype.table),
342✔
2048
        fkey: xtype.fkey.clone(),
342✔
2049
        reverse_reference: xtype.reverse_reference,
342✔
2050
        selections: builder_fields,
342✔
2051
    })
342✔
2052
}
354✔
2053

2054
pub fn to_node_by_pk_builder<'a, T>(
11✔
2055
    field: &__Field,
11✔
2056
    query_field: &graphql_parser::query::Field<'a, T>,
11✔
2057
    fragment_definitions: &Vec<FragmentDefinition<'a, T>>,
11✔
2058
    variables: &serde_json::Value,
11✔
2059
    variable_definitions: &Vec<VariableDefinition<'a, T>>,
11✔
2060
) -> Result<NodeByPkBuilder, String>
11✔
2061
where
11✔
2062
    T: Text<'a> + Eq + AsRef<str> + Clone,
11✔
2063
    T::Value: Hash,
11✔
2064
{
2065
    let type_ = field.type_().unmodified_type();
11✔
2066
    let alias = alias_or_name(query_field);
11✔
2067

2068
    match type_ {
11✔
2069
        __Type::Node(xtype) => {
11✔
2070
            let type_name = xtype
11✔
2071
                .name()
11✔
2072
                .ok_or("Encountered type without name in node_by_pk builder")?;
11✔
2073

2074
            let field_map = field_map(&__Type::Node(xtype.clone()));
11✔
2075

2076
            // Get primary key columns from the table
2077
            let pkey = xtype
11✔
2078
                .table
11✔
2079
                .primary_key()
11✔
2080
                .ok_or("Table has no primary key".to_string())?;
11✔
2081

2082
            // Create a map of expected field arguments based on the field's arg definitions
2083
            let mut pk_arg_map = HashMap::new();
11✔
2084
            for arg in field.args() {
15✔
2085
                if let Some(NodeSQLType::Column(col)) = &arg.sql_type {
15✔
2086
                    pk_arg_map.insert(arg.name().to_string(), col.name.clone());
15✔
2087
                }
15✔
2088
            }
2089

2090
            let mut pk_values = HashMap::new();
11✔
2091

2092
            // Process each argument in the query
2093
            for arg in &query_field.arguments {
25✔
2094
                let arg_name = arg.0.as_ref();
14✔
2095

2096
                // Find the corresponding column name from our argument map
2097
                if let Some(col_name) = pk_arg_map.get(arg_name) {
14✔
2098
                    let value = to_gson(&arg.1, variables, variable_definitions)?;
14✔
2099
                    let json_value = gson::gson_to_json(&value)?;
14✔
2100
                    pk_values.insert(col_name.clone(), json_value);
14✔
NEW
2101
                }
×
2102
            }
2103

2104
            // Need values for all primary key columns
2105
            if pk_values.len() != pkey.column_names.len() {
11✔
2106
                return Err("All primary key columns must be provided".to_string());
1✔
2107
            }
10✔
2108

2109
            let mut builder_fields = vec![];
10✔
2110
            let selection_fields = normalize_selection_set(
10✔
2111
                &query_field.selection_set,
10✔
2112
                fragment_definitions,
10✔
2113
                &type_name,
10✔
2114
                variables,
10✔
NEW
2115
            )?;
×
2116

2117
            for selection_field in selection_fields {
43✔
2118
                match field_map.get(selection_field.name.as_ref()) {
33✔
2119
                    None => {
NEW
2120
                        return Err(format!(
×
NEW
2121
                            "Unknown field '{}' on type '{}'",
×
NEW
2122
                            selection_field.name.as_ref(),
×
NEW
2123
                            &type_name
×
NEW
2124
                        ))
×
2125
                    }
2126
                    Some(f) => {
33✔
2127
                        let alias = alias_or_name(&selection_field);
33✔
2128

2129
                        let node_selection = match &f.sql_type {
33✔
2130
                            Some(node_sql_type) => match node_sql_type {
33✔
2131
                                NodeSQLType::Column(col) => NodeSelection::Column(ColumnBuilder {
32✔
2132
                                    alias,
32✔
2133
                                    column: Arc::clone(col),
32✔
2134
                                }),
32✔
NEW
2135
                                NodeSQLType::Function(func) => {
×
NEW
2136
                                    let function_selection = match &f.type_() {
×
NEW
2137
                                        __Type::Scalar(_) => FunctionSelection::ScalarSelf,
×
NEW
2138
                                        __Type::List(_) => FunctionSelection::Array,
×
2139
                                        __Type::Node(_) => {
NEW
2140
                                            let node_builder = to_node_builder(
×
NEW
2141
                                                f,
×
NEW
2142
                                                &selection_field,
×
NEW
2143
                                                fragment_definitions,
×
NEW
2144
                                                variables,
×
NEW
2145
                                                &[],
×
NEW
2146
                                                variable_definitions,
×
NEW
2147
                                            )?;
×
NEW
2148
                                            FunctionSelection::Node(node_builder)
×
2149
                                        }
2150
                                        __Type::Connection(_) => {
NEW
2151
                                            let connection_builder = to_connection_builder(
×
NEW
2152
                                                f,
×
NEW
2153
                                                &selection_field,
×
NEW
2154
                                                fragment_definitions,
×
NEW
2155
                                                variables,
×
NEW
2156
                                                &[],
×
NEW
2157
                                                variable_definitions,
×
NEW
2158
                                            )?;
×
NEW
2159
                                            FunctionSelection::Connection(connection_builder)
×
2160
                                        }
2161
                                        _ => {
NEW
2162
                                            return Err(
×
NEW
2163
                                                "invalid return type from function".to_string()
×
NEW
2164
                                            )
×
2165
                                        }
2166
                                    };
NEW
2167
                                    NodeSelection::Function(FunctionBuilder {
×
NEW
2168
                                        alias,
×
NEW
2169
                                        function: Arc::clone(func),
×
NEW
2170
                                        table: Arc::clone(&xtype.table),
×
NEW
2171
                                        selection: function_selection,
×
NEW
2172
                                    })
×
2173
                                }
2174
                                NodeSQLType::NodeId(pkey_columns) => {
1✔
2175
                                    NodeSelection::NodeId(NodeIdBuilder {
1✔
2176
                                        alias,
1✔
2177
                                        columns: pkey_columns.clone(),
1✔
2178
                                        table_name: xtype.table.name.clone(),
1✔
2179
                                        schema_name: xtype.table.schema.clone(),
1✔
2180
                                    })
1✔
2181
                                }
2182
                            },
NEW
2183
                            _ => match f.name().as_ref() {
×
NEW
2184
                                "__typename" => NodeSelection::Typename {
×
NEW
2185
                                    alias: alias_or_name(&selection_field),
×
NEW
2186
                                    typename: xtype.name().expect("node type should have a name"),
×
NEW
2187
                                },
×
NEW
2188
                                _ => match f.type_().unmodified_type() {
×
2189
                                    __Type::Connection(_) => {
NEW
2190
                                        let con_builder = to_connection_builder(
×
NEW
2191
                                            f,
×
NEW
2192
                                            &selection_field,
×
NEW
2193
                                            fragment_definitions,
×
NEW
2194
                                            variables,
×
NEW
2195
                                            &[],
×
NEW
2196
                                            variable_definitions,
×
2197
                                        );
NEW
2198
                                        NodeSelection::Connection(con_builder?)
×
2199
                                    }
2200
                                    __Type::Node(_) => {
NEW
2201
                                        let node_builder = to_node_builder(
×
NEW
2202
                                            f,
×
NEW
2203
                                            &selection_field,
×
NEW
2204
                                            fragment_definitions,
×
NEW
2205
                                            variables,
×
NEW
2206
                                            &[],
×
NEW
2207
                                            variable_definitions,
×
2208
                                        );
NEW
2209
                                        NodeSelection::Node(node_builder?)
×
2210
                                    }
2211
                                    _ => {
NEW
2212
                                        return Err(format!(
×
NEW
2213
                                            "unexpected field type on node {}",
×
NEW
2214
                                            f.name()
×
NEW
2215
                                        ));
×
2216
                                    }
2217
                                },
2218
                            },
2219
                        };
2220
                        builder_fields.push(node_selection);
33✔
2221
                    }
2222
                }
2223
            }
2224

2225
            Ok(NodeByPkBuilder {
10✔
2226
                pk_values,
10✔
2227
                _alias: alias,
10✔
2228
                table: Arc::clone(&xtype.table),
10✔
2229
                selections: builder_fields,
10✔
2230
            })
10✔
2231
        }
NEW
2232
        _ => Err("cannot build query for non-node type".to_string()),
×
2233
    }
2234
}
11✔
2235

2236
// Introspection
2237

2238
#[allow(clippy::large_enum_variant)]
2239
#[derive(Serialize, Clone, Debug)]
2240
pub enum __FieldField {
2241
    Name,
2242
    Description,
2243
    Arguments(Vec<__InputValueBuilder>),
2244
    Type(__TypeBuilder),
2245
    IsDeprecated,
2246
    DeprecationReason,
2247
    Typename { alias: String, typename: String },
2248
}
2249

2250
#[derive(Serialize, Clone, Debug)]
2251
pub struct __FieldSelection {
2252
    pub alias: String,
2253
    pub selection: __FieldField,
2254
}
2255
#[derive(Clone, Debug)]
2256
pub struct __FieldBuilder {
2257
    pub field: __Field,
2258
    //pub type_: __Type,
2259
    pub selections: Vec<__FieldSelection>,
2260
}
2261

2262
#[derive(Serialize, Clone, Debug)]
2263
pub enum __EnumValueField {
2264
    Name,
2265
    Description,
2266
    IsDeprecated,
2267
    DeprecationReason,
2268
    Typename { alias: String, typename: String },
2269
}
2270

2271
#[derive(Serialize, Clone, Debug)]
2272
pub struct __EnumValueSelection {
2273
    pub alias: String,
2274
    pub selection: __EnumValueField,
2275
}
2276

2277
#[derive(Clone, Debug)]
2278
pub struct __EnumValueBuilder {
2279
    pub enum_value: __EnumValue,
2280
    pub selections: Vec<__EnumValueSelection>,
2281
}
2282

2283
#[allow(clippy::large_enum_variant)]
2284
#[derive(Serialize, Clone, Debug)]
2285
pub enum __InputValueField {
2286
    Name,
2287
    Description,
2288
    Type(__TypeBuilder),
2289
    DefaultValue,
2290
    IsDeprecated,
2291
    DeprecationReason,
2292
    Typename { alias: String, typename: String },
2293
}
2294

2295
#[derive(Serialize, Clone, Debug)]
2296
pub struct __InputValueSelection {
2297
    pub alias: String,
2298
    pub selection: __InputValueField,
2299
}
2300

2301
#[derive(Clone, Debug)]
2302
pub struct __InputValueBuilder {
2303
    pub input_value: __InputValue,
2304
    pub selections: Vec<__InputValueSelection>,
2305
}
2306

2307
#[allow(clippy::large_enum_variant)]
2308
#[derive(Clone, Debug)]
2309
pub enum __TypeField {
2310
    Kind,
2311
    Name,
2312
    Description,
2313
    // More
2314
    Fields(Option<Vec<__FieldBuilder>>),
2315
    InputFields(Option<Vec<__InputValueBuilder>>),
2316

2317
    Interfaces(Vec<__TypeBuilder>),
2318
    EnumValues(Option<Vec<__EnumValueBuilder>>),
2319
    PossibleTypes(Option<Vec<__TypeBuilder>>),
2320
    OfType(Option<__TypeBuilder>),
2321
    Typename {
2322
        alias: String,
2323
        typename: Option<String>,
2324
    },
2325
}
2326

2327
#[derive(Clone, Debug)]
2328
pub struct __TypeSelection {
2329
    pub alias: String,
2330
    pub selection: __TypeField,
2331
}
2332

2333
#[derive(Clone, Debug)]
2334
pub struct __TypeBuilder {
2335
    pub type_: __Type,
2336
    pub selections: Vec<__TypeSelection>,
2337
}
2338

2339
#[derive(Clone, Debug)]
2340
pub enum __DirectiveField {
2341
    Name,
2342
    Description,
2343
    Locations,
2344
    Args(Vec<__InputValueBuilder>),
2345
    IsRepeatable,
2346
    Typename { alias: String, typename: String },
2347
}
2348

2349
#[derive(Clone, Debug)]
2350
pub struct __DirectiveSelection {
2351
    pub alias: String,
2352
    pub selection: __DirectiveField,
2353
}
2354

2355
#[derive(Clone, Debug)]
2356
pub struct __DirectiveBuilder {
2357
    pub directive: __Directive,
2358
    pub selections: Vec<__DirectiveSelection>,
2359
}
2360

2361
#[derive(Serialize, Clone, Debug)]
2362
#[allow(dead_code)]
2363
#[serde(untagged)]
2364
pub enum __SchemaField {
2365
    Description,
2366
    Types(Vec<__TypeBuilder>),
2367
    QueryType(__TypeBuilder),
2368
    MutationType(Option<__TypeBuilder>),
2369
    SubscriptionType(Option<__TypeBuilder>),
2370
    Directives(Vec<__DirectiveBuilder>),
2371
    Typename { alias: String, typename: String },
2372
}
2373

2374
#[derive(Serialize, Clone, Debug)]
2375
pub struct __SchemaSelection {
2376
    pub alias: String,
2377
    pub selection: __SchemaField,
2378
}
2379

2380
#[derive(Clone)]
2381
pub struct __SchemaBuilder {
2382
    pub description: String,
2383
    pub selections: Vec<__SchemaSelection>,
2384
}
2385

2386
impl __Schema {
2387
    pub fn to_enum_value_builder<'a, T>(
74✔
2388
        &self,
74✔
2389
        enum_value: &__EnumValue,
74✔
2390
        query_field: &graphql_parser::query::Field<'a, T>,
74✔
2391
        fragment_definitions: &Vec<FragmentDefinition<'a, T>>,
74✔
2392
        variables: &serde_json::Value,
74✔
2393
    ) -> Result<__EnumValueBuilder, String>
74✔
2394
    where
74✔
2395
        T: Text<'a> + Eq + AsRef<str> + Clone,
74✔
2396
        T::Value: Hash,
74✔
2397
    {
2398
        let selection_fields = normalize_selection_set(
74✔
2399
            &query_field.selection_set,
74✔
2400
            fragment_definitions,
74✔
2401
            &"__EnumValue".to_string(),
74✔
2402
            variables,
74✔
UNCOV
2403
        )?;
×
2404

2405
        let mut builder_fields = vec![];
74✔
2406

2407
        for selection_field in selection_fields {
352✔
2408
            let enum_value_field_name = selection_field.name.as_ref();
278✔
2409

2410
            let __enum_value_field = match enum_value_field_name {
278✔
2411
                "name" => __EnumValueField::Name,
278✔
2412
                "description" => __EnumValueField::Description,
204✔
2413
                "isDeprecated" => __EnumValueField::IsDeprecated,
136✔
2414
                "deprecationReason" => __EnumValueField::DeprecationReason,
68✔
2415
                "__typename" => __EnumValueField::Typename {
×
2416
                    alias: alias_or_name(&selection_field),
×
2417
                    typename: enum_value.name(),
×
2418
                },
×
2419
                _ => {
2420
                    return Err(format!(
×
2421
                        "unknown field in __EnumValue: {}",
×
2422
                        enum_value_field_name
×
2423
                    ))
×
2424
                }
2425
            };
2426

2427
            builder_fields.push(__EnumValueSelection {
278✔
2428
                alias: alias_or_name(&selection_field),
278✔
2429
                selection: __enum_value_field,
278✔
2430
            });
278✔
2431
        }
2432

2433
        Ok(__EnumValueBuilder {
74✔
2434
            enum_value: enum_value.clone(),
74✔
2435
            selections: builder_fields,
74✔
2436
        })
74✔
2437
    }
74✔
2438

2439
    pub fn to_input_value_builder<'a, T>(
827✔
2440
        &self,
827✔
2441
        input_value: &__InputValue,
827✔
2442
        query_field: &graphql_parser::query::Field<'a, T>,
827✔
2443
        fragment_definitions: &Vec<FragmentDefinition<'a, T>>,
827✔
2444
        variables: &serde_json::Value,
827✔
2445
        variable_definitions: &Vec<VariableDefinition<'a, T>>,
827✔
2446
    ) -> Result<__InputValueBuilder, String>
827✔
2447
    where
827✔
2448
        T: Text<'a> + Eq + AsRef<str> + Clone,
827✔
2449
        T::Value: Hash,
827✔
2450
    {
2451
        let selection_fields = normalize_selection_set(
827✔
2452
            &query_field.selection_set,
827✔
2453
            fragment_definitions,
827✔
2454
            &"__InputValue".to_string(),
827✔
2455
            variables,
827✔
UNCOV
2456
        )?;
×
2457

2458
        let mut builder_fields = vec![];
827✔
2459

2460
        for selection_field in selection_fields {
3,575✔
2461
            let input_value_field_name = selection_field.name.as_ref();
2,748✔
2462

2463
            let __input_value_field = match input_value_field_name {
2,748✔
2464
                "name" => __InputValueField::Name,
2,748✔
2465
                "description" => __InputValueField::Description,
1,921✔
2466
                "type" => {
1,459✔
2467
                    let t = input_value.type_.clone();
682✔
2468

2469
                    let t_builder = self.to_type_builder_from_type(
682✔
2470
                        &t,
682✔
2471
                        &selection_field,
682✔
2472
                        fragment_definitions,
682✔
2473
                        variables,
682✔
2474
                        variable_definitions,
682✔
UNCOV
2475
                    )?;
×
2476
                    __InputValueField::Type(t_builder)
682✔
2477
                }
2478
                "defaultValue" => __InputValueField::DefaultValue,
777✔
2479
                "isDeprecated" => __InputValueField::IsDeprecated,
274✔
2480
                "deprecationReason" => __InputValueField::DeprecationReason,
137✔
2481
                "__typename" => __InputValueField::Typename {
×
2482
                    alias: alias_or_name(&selection_field),
×
2483
                    typename: input_value.name(),
×
2484
                },
×
2485
                _ => {
2486
                    return Err(format!(
×
2487
                        "unknown field in __InputValue: {}",
×
2488
                        input_value_field_name
×
2489
                    ))
×
2490
                }
2491
            };
2492

2493
            builder_fields.push(__InputValueSelection {
2,748✔
2494
                alias: alias_or_name(&selection_field),
2,748✔
2495
                selection: __input_value_field,
2,748✔
2496
            });
2,748✔
2497
        }
2498

2499
        Ok(__InputValueBuilder {
827✔
2500
            input_value: input_value.clone(),
827✔
2501
            selections: builder_fields,
827✔
2502
        })
827✔
2503
    }
827✔
2504

2505
    pub fn to_field_builder<'a, T>(
630✔
2506
        &self,
630✔
2507
        field: &__Field,
630✔
2508
        query_field: &graphql_parser::query::Field<'a, T>,
630✔
2509
        fragment_definitions: &Vec<FragmentDefinition<'a, T>>,
630✔
2510
        variables: &serde_json::Value,
630✔
2511
        variable_definitions: &Vec<VariableDefinition<'a, T>>,
630✔
2512
    ) -> Result<__FieldBuilder, String>
630✔
2513
    where
630✔
2514
        T: Text<'a> + Eq + AsRef<str> + Clone,
630✔
2515
        T::Value: Hash,
630✔
2516
    {
2517
        let selection_fields = normalize_selection_set(
630✔
2518
            &query_field.selection_set,
630✔
2519
            fragment_definitions,
630✔
2520
            &"__Field".to_string(),
630✔
2521
            variables,
630✔
UNCOV
2522
        )?;
×
2523

2524
        let mut builder_fields = vec![];
630✔
2525

2526
        for selection_field in selection_fields {
2,618✔
2527
            let type_field_name = selection_field.name.as_ref();
1,988✔
2528

2529
            let __field_field = match type_field_name {
1,988✔
2530
                "name" => __FieldField::Name,
1,988✔
2531
                "description" => __FieldField::Description,
1,358✔
2532
                "args" => {
1,054✔
2533
                    let mut f_builders: Vec<__InputValueBuilder> = vec![];
301✔
2534
                    let args = field.args();
301✔
2535

2536
                    for arg in args {
580✔
2537
                        let f_builder = self.to_input_value_builder(
279✔
2538
                            &arg,
279✔
2539
                            &selection_field,
279✔
2540
                            fragment_definitions,
279✔
2541
                            variables,
279✔
2542
                            variable_definitions,
279✔
UNCOV
2543
                        )?;
×
2544
                        f_builders.push(f_builder)
279✔
2545
                    }
2546
                    __FieldField::Arguments(f_builders)
301✔
2547
                }
2548
                "type" => {
753✔
2549
                    let t = field.type_();
391✔
2550

2551
                    let t_builder = self.to_type_builder_from_type(
391✔
2552
                        &t,
391✔
2553
                        &selection_field,
391✔
2554
                        fragment_definitions,
391✔
2555
                        variables,
391✔
2556
                        variable_definitions,
391✔
UNCOV
2557
                    )?;
×
2558
                    __FieldField::Type(t_builder)
391✔
2559
                }
2560
                "isDeprecated" => __FieldField::IsDeprecated,
362✔
2561
                "deprecationReason" => __FieldField::DeprecationReason,
181✔
2562
                "__typename" => __FieldField::Typename {
×
2563
                    alias: alias_or_name(&selection_field),
×
2564
                    typename: field.name(),
×
2565
                },
×
2566
                _ => return Err(format!("unknown field in __Field {}", type_field_name)),
×
2567
            };
2568

2569
            builder_fields.push(__FieldSelection {
1,988✔
2570
                alias: alias_or_name(&selection_field),
1,988✔
2571
                selection: __field_field,
1,988✔
2572
            });
1,988✔
2573
        }
2574

2575
        Ok(__FieldBuilder {
630✔
2576
            field: field.clone(),
630✔
2577
            selections: builder_fields,
630✔
2578
        })
630✔
2579
    }
630✔
2580

2581
    pub fn to_type_builder<'a, T>(
742✔
2582
        &self,
742✔
2583
        field: &__Field,
742✔
2584
        query_field: &graphql_parser::query::Field<'a, T>,
742✔
2585
        fragment_definitions: &Vec<FragmentDefinition<'a, T>>,
742✔
2586
        mut type_name: Option<String>,
742✔
2587
        variables: &serde_json::Value,
742✔
2588
        variable_definitions: &Vec<VariableDefinition<'a, T>>,
742✔
2589
    ) -> Result<Option<__TypeBuilder>, String>
742✔
2590
    where
742✔
2591
        T: Text<'a> + Eq + AsRef<str> + Clone,
742✔
2592
        T::Value: Hash,
742✔
2593
    {
2594
        if field.type_.unmodified_type() != __Type::__Type(__TypeType {}) {
742✔
2595
            return Err("can not build query for non-__type type".to_string());
×
2596
        }
742✔
2597

2598
        let name_arg_result: Result<gson::Value, String> =
742✔
2599
            read_argument("name", field, query_field, variables, variable_definitions);
742✔
2600
        let name_arg: Option<String> = match name_arg_result {
742✔
2601
            // This builder (too) is overloaded and the arg is not present in all uses
2602
            Err(_) => None,
658✔
2603
            Ok(name_arg) => match name_arg {
84✔
2604
                gson::Value::String(narg) => Some(narg),
84✔
2605
                _ => {
2606
                    return Err("Internal Error: failed to parse validated name".to_string());
×
2607
                }
2608
            },
2609
        };
2610

2611
        if name_arg.is_some() {
742✔
2612
            type_name = name_arg;
84✔
2613
        }
658✔
2614
        let type_name = type_name.ok_or("no name found for __type".to_string())?;
742✔
2615

2616
        let type_map = type_map(self);
742✔
2617
        let requested_type: Option<&__Type> = type_map.get(&type_name);
742✔
2618

2619
        match requested_type {
742✔
2620
            Some(requested_type) => {
731✔
2621
                // Result<> to Result<Option<>>
2622
                self.to_type_builder_from_type(
731✔
2623
                    requested_type,
731✔
2624
                    query_field,
731✔
2625
                    fragment_definitions,
731✔
2626
                    variables,
731✔
2627
                    variable_definitions,
731✔
2628
                )
2629
                .map(Some)
731✔
2630
            }
2631
            None => Ok(None),
11✔
2632
        }
2633
    }
742✔
2634

2635
    pub fn to_type_builder_from_type<'a, T>(
2,514✔
2636
        &self,
2,514✔
2637
        type_: &__Type,
2,514✔
2638
        query_field: &graphql_parser::query::Field<'a, T>,
2,514✔
2639
        fragment_definitions: &Vec<FragmentDefinition<'a, T>>,
2,514✔
2640
        variables: &serde_json::Value,
2,514✔
2641
        variable_definitions: &Vec<VariableDefinition<'a, T>>,
2,514✔
2642
    ) -> Result<__TypeBuilder, String>
2,514✔
2643
    where
2,514✔
2644
        T: Text<'a> + Eq + AsRef<str> + Clone,
2,514✔
2645
        T::Value: Hash,
2,514✔
2646
    {
2647
        let field_map = field_map(&__Type::__Type(__TypeType {}));
2,514✔
2648

2649
        let selection_fields = normalize_selection_set(
2,514✔
2650
            &query_field.selection_set,
2,514✔
2651
            fragment_definitions,
2,514✔
2652
            &"__Type".to_string(),
2,514✔
2653
            variables,
2,514✔
UNCOV
2654
        )?;
×
2655

2656
        let mut builder_fields = vec![];
2,514✔
2657

2658
        for selection_field in selection_fields {
9,497✔
2659
            let type_field_name = selection_field.name.as_ref();
6,983✔
2660
            // ex: type_field_field  = 'name'
2661
            match field_map.get(type_field_name) {
6,983✔
2662
                None => return Err(format!("unknown field on __Type: {}", type_field_name)),
×
2663
                Some(f) => builder_fields.push(__TypeSelection {
6,983✔
2664
                    alias: alias_or_name(&selection_field),
6,983✔
2665
                    selection: match f.name().as_str() {
6,983✔
2666
                        "kind" => __TypeField::Kind,
6,983✔
2667
                        "name" => __TypeField::Name,
4,991✔
2668
                        "description" => __TypeField::Description,
2,613✔
2669
                        "fields" => {
2,446✔
2670
                            // TODO read "include_deprecated" arg.
2671
                            let type_fields = type_.fields(true);
282✔
2672
                            match type_fields {
282✔
2673
                                None => __TypeField::Fields(None),
142✔
2674
                                Some(vec_fields) => {
140✔
2675
                                    let mut f_builders: Vec<__FieldBuilder> = vec![];
140✔
2676

2677
                                    for vec_field in vec_fields {
824✔
2678
                                        if ["__type".to_string(), "__schema".to_string()]
684✔
2679
                                            .contains(&vec_field.name())
684✔
2680
                                        {
2681
                                            continue;
54✔
2682
                                        }
630✔
2683

2684
                                        let f_builder = self.to_field_builder(
630✔
2685
                                            &vec_field,
630✔
2686
                                            &selection_field,
630✔
2687
                                            fragment_definitions,
630✔
2688
                                            variables,
630✔
2689
                                            variable_definitions,
630✔
UNCOV
2690
                                        )?;
×
2691
                                        f_builders.push(f_builder)
630✔
2692
                                    }
2693
                                    __TypeField::Fields(Some(f_builders))
140✔
2694
                                }
2695
                            }
2696
                        }
2697
                        "inputFields" => {
2,164✔
2698
                            let type_inputs = type_.input_fields();
204✔
2699
                            match type_inputs {
204✔
2700
                                None => __TypeField::InputFields(None),
114✔
2701
                                Some(vec_fields) => {
90✔
2702
                                    let mut f_builders: Vec<__InputValueBuilder> = vec![];
90✔
2703

2704
                                    for vec_field in vec_fields {
634✔
2705
                                        let f_builder = self.to_input_value_builder(
544✔
2706
                                            &vec_field,
544✔
2707
                                            &selection_field,
544✔
2708
                                            fragment_definitions,
544✔
2709
                                            variables,
544✔
2710
                                            variable_definitions,
544✔
UNCOV
2711
                                        )?;
×
2712
                                        f_builders.push(f_builder)
544✔
2713
                                    }
2714
                                    __TypeField::InputFields(Some(f_builders))
90✔
2715
                                }
2716
                            }
2717
                        }
2718
                        "interfaces" => {
1,960✔
2719
                            match type_.interfaces() {
141✔
2720
                                Some(interfaces) => {
4✔
2721
                                    let mut interface_builders = vec![];
4✔
2722
                                    for interface in &interfaces {
8✔
2723
                                        let interface_builder = self.to_type_builder_from_type(
4✔
2724
                                            interface,
4✔
2725
                                            &selection_field,
4✔
2726
                                            fragment_definitions,
4✔
2727
                                            variables,
4✔
2728
                                            variable_definitions,
4✔
UNCOV
2729
                                        )?;
×
2730
                                        interface_builders.push(interface_builder);
4✔
2731
                                    }
2732
                                    __TypeField::Interfaces(interface_builders)
4✔
2733
                                }
2734
                                None => {
2735
                                    // Declares as nullable, but breaks graphiql
2736
                                    __TypeField::Interfaces(vec![])
137✔
2737
                                }
2738
                            }
2739
                        }
2740
                        "enumValues" => {
1,819✔
2741
                            let enum_value_builders = match type_.enum_values(true) {
144✔
2742
                                Some(enum_values) => {
144✔
2743
                                    let mut f_builders: Vec<__EnumValueBuilder> = vec![];
144✔
2744
                                    for enum_value in &enum_values {
218✔
2745
                                        let f_builder = self.to_enum_value_builder(
74✔
2746
                                            enum_value,
74✔
2747
                                            &selection_field,
74✔
2748
                                            fragment_definitions,
74✔
2749
                                            variables,
74✔
UNCOV
2750
                                        )?;
×
2751
                                        f_builders.push(f_builder)
74✔
2752
                                    }
2753
                                    Some(f_builders)
144✔
2754
                                }
2755
                                None => None,
×
2756
                            };
2757
                            __TypeField::EnumValues(enum_value_builders)
144✔
2758
                        }
2759
                        "possibleTypes" => match type_.possible_types() {
1,675✔
2760
                            Some(types) => {
2✔
2761
                                let mut type_builders = vec![];
2✔
2762
                                for ty in &types {
6✔
2763
                                    let type_builder = self.to_type_builder_from_type(
4✔
2764
                                        ty,
4✔
2765
                                        &selection_field,
4✔
2766
                                        fragment_definitions,
4✔
2767
                                        variables,
4✔
2768
                                        variable_definitions,
4✔
UNCOV
2769
                                    )?;
×
2770

2771
                                    type_builders.push(type_builder);
4✔
2772
                                }
2773
                                __TypeField::PossibleTypes(Some(type_builders))
2✔
2774
                            }
2775
                            None => __TypeField::PossibleTypes(None),
139✔
2776
                        },
2777
                        "ofType" => {
1,534✔
2778
                            let field_type =
1,532✔
2779
                                if let __Type::FuncCallResponse(func_call_resp_type) = type_ {
1,532✔
2780
                                    func_call_resp_type.return_type.deref()
56✔
2781
                                } else {
2782
                                    type_
1,476✔
2783
                                };
2784
                            let unwrapped_type_builder = match field_type {
1,532✔
2785
                                __Type::List(list_type) => {
222✔
2786
                                    let inner_type: __Type = (*(list_type.type_)).clone();
222✔
2787
                                    Some(self.to_type_builder_from_type(
222✔
2788
                                        &inner_type,
222✔
2789
                                        &selection_field,
222✔
2790
                                        fragment_definitions,
222✔
2791
                                        variables,
222✔
2792
                                        variable_definitions,
222✔
UNCOV
2793
                                    )?)
×
2794
                                }
2795
                                __Type::NonNull(non_null_type) => {
480✔
2796
                                    let inner_type = (*(non_null_type.type_)).clone();
480✔
2797
                                    Some(self.to_type_builder_from_type(
480✔
2798
                                        &inner_type,
480✔
2799
                                        &selection_field,
480✔
2800
                                        fragment_definitions,
480✔
2801
                                        variables,
480✔
2802
                                        variable_definitions,
480✔
UNCOV
2803
                                    )?)
×
2804
                                }
2805
                                _ => None,
830✔
2806
                            };
2807
                            __TypeField::OfType(unwrapped_type_builder)
1,532✔
2808
                        }
2809
                        "__typename" => __TypeField::Typename {
2✔
2810
                            alias: alias_or_name(&selection_field),
2✔
2811
                            typename: type_.name(),
2✔
2812
                        },
2✔
2813
                        _ => {
2814
                            return Err(format!(
×
2815
                                "unexpected field {} type on __Type",
×
2816
                                type_field_name
×
2817
                            ))
×
2818
                        }
2819
                    },
2820
                }),
2821
            }
2822
        }
2823

2824
        Ok(__TypeBuilder {
2,514✔
2825
            type_: type_.clone(),
2,514✔
2826
            selections: builder_fields,
2,514✔
2827
        })
2,514✔
2828
    }
2,514✔
2829

2830
    pub fn to_directive_builder<'a, T>(
6✔
2831
        &self,
6✔
2832
        directive: &__Directive,
6✔
2833
        query_field: &graphql_parser::query::Field<'a, T>,
6✔
2834
        fragment_definitions: &Vec<FragmentDefinition<'a, T>>,
6✔
2835
        variables: &serde_json::Value,
6✔
2836
        variable_definitions: &Vec<VariableDefinition<'a, T>>,
6✔
2837
    ) -> Result<__DirectiveBuilder, String>
6✔
2838
    where
6✔
2839
        T: Text<'a> + Eq + AsRef<str> + Clone,
6✔
2840
        T::Value: Hash,
6✔
2841
    {
2842
        let selection_fields = normalize_selection_set(
6✔
2843
            &query_field.selection_set,
6✔
2844
            fragment_definitions,
6✔
2845
            &__Directive::TYPE.to_string(),
6✔
2846
            variables,
6✔
UNCOV
2847
        )?;
×
2848

2849
        let mut builder_fields = vec![];
6✔
2850

2851
        for selection_field in selection_fields {
32✔
2852
            let field_name = selection_field.name.as_ref();
26✔
2853

2854
            let directive_field = match field_name {
26✔
2855
                "name" => __DirectiveField::Name,
26✔
2856
                "description" => __DirectiveField::Description,
20✔
2857
                "locations" => __DirectiveField::Locations,
14✔
2858
                "args" => {
8✔
2859
                    let mut builders: Vec<__InputValueBuilder> = vec![];
4✔
2860
                    let args = directive.args();
4✔
2861

2862
                    for arg in args {
8✔
2863
                        let builder = self.to_input_value_builder(
4✔
2864
                            arg,
4✔
2865
                            &selection_field,
4✔
2866
                            fragment_definitions,
4✔
2867
                            variables,
4✔
2868
                            variable_definitions,
4✔
UNCOV
2869
                        )?;
×
2870
                        builders.push(builder)
4✔
2871
                    }
2872
                    __DirectiveField::Args(builders)
4✔
2873
                }
2874
                "isRepeatable" => __DirectiveField::IsRepeatable,
4✔
2875
                "__typename" => __DirectiveField::Typename {
2✔
2876
                    alias: alias_or_name(&selection_field),
2✔
2877
                    typename: __Directive::TYPE.to_string(),
2✔
2878
                },
2✔
2879
                _ => {
2880
                    return Err(format!(
×
2881
                        "unknown field {} in {}",
×
2882
                        field_name,
×
2883
                        __Directive::TYPE,
×
2884
                    ))
×
2885
                }
2886
            };
2887

2888
            builder_fields.push(__DirectiveSelection {
26✔
2889
                alias: alias_or_name(&selection_field),
26✔
2890
                selection: directive_field,
26✔
2891
            });
26✔
2892
        }
2893

2894
        Ok(__DirectiveBuilder {
6✔
2895
            directive: directive.clone(),
6✔
2896
            selections: builder_fields,
6✔
2897
        })
6✔
2898
    }
6✔
2899

2900
    pub fn to_schema_builder<'a, T>(
28✔
2901
        &self,
28✔
2902
        field: &__Field,
28✔
2903
        query_field: &graphql_parser::query::Field<'a, T>,
28✔
2904
        fragment_definitions: &Vec<FragmentDefinition<'a, T>>,
28✔
2905
        variables: &serde_json::Value,
28✔
2906
        variable_definitions: &Vec<VariableDefinition<'a, T>>,
28✔
2907
    ) -> Result<__SchemaBuilder, String>
28✔
2908
    where
28✔
2909
        T: Text<'a> + Eq + AsRef<str> + Clone,
28✔
2910
        T::Value: Hash,
28✔
2911
    {
2912
        let type_ = field.type_.unmodified_type();
28✔
2913
        let type_name = type_
28✔
2914
            .name()
28✔
2915
            .ok_or("Encountered type without name in schema builder")?;
28✔
2916
        let field_map = field_map(&type_);
28✔
2917

2918
        match type_ {
28✔
2919
            __Type::__Schema(_) => {
2920
                let mut builder_fields: Vec<__SchemaSelection> = vec![];
28✔
2921

2922
                let selection_fields = normalize_selection_set(
28✔
2923
                    &query_field.selection_set,
28✔
2924
                    fragment_definitions,
28✔
2925
                    &type_name,
28✔
2926
                    variables,
28✔
UNCOV
2927
                )?;
×
2928

2929
                for selection_field in selection_fields {
70✔
2930
                    let field_name = selection_field.name.as_ref();
42✔
2931

2932
                    match field_map.get(field_name) {
42✔
2933
                        None => return Err(format!("unknown field in __Schema: {}", field_name)),
×
2934
                        Some(f) => {
42✔
2935
                            builder_fields.push(__SchemaSelection {
42✔
2936
                                alias: alias_or_name(&selection_field),
42✔
2937
                                selection: match f.name().as_str() {
42✔
2938
                                    "description" => __SchemaField::Description,
42✔
2939
                                    "types" => {
41✔
2940
                                        let builders = self
10✔
2941
                                            .types()
10✔
2942
                                            .iter()
10✔
2943
                                            // Filter out intropsection meta-types
2944
                                            //.filter(|x| {
2945
                                            // !x.name().unwrap_or("".to_string()).starts_with("__")
2946
                                            //})
2947
                                            .map(|t| {
632✔
2948
                                                self.to_type_builder(
632✔
2949
                                                    f,
632✔
2950
                                                    &selection_field,
632✔
2951
                                                    fragment_definitions,
632✔
2952
                                                    t.name(),
632✔
2953
                                                    variables,
632✔
2954
                                                    variable_definitions,
632✔
2955
                                                )
2956
                                                .map(|x| {
632✔
2957
                                                    x.expect(
632✔
2958
                                                        "type builder should exist for types field",
632✔
2959
                                                    )
2960
                                                })
632✔
2961
                                            })
632✔
2962
                                            // from Vec<Result> to Result<Vec>
2963
                                            .collect::<Result<Vec<_>, _>>()?;
10✔
2964
                                        __SchemaField::Types(builders)
10✔
2965
                                    }
2966
                                    "queryType" => {
31✔
2967
                                        let builder = self.to_type_builder(
19✔
2968
                                            f,
19✔
2969
                                            &selection_field,
19✔
2970
                                            fragment_definitions,
19✔
2971
                                            Some("Query".to_string()),
19✔
2972
                                            variables,
19✔
2973
                                            variable_definitions,
19✔
UNCOV
2974
                                        )?;
×
2975
                                        __SchemaField::QueryType(builder.expect(
19✔
2976
                                            "type builder should exist for queryType field",
19✔
2977
                                        ))
19✔
2978
                                    }
2979
                                    "mutationType" => {
12✔
2980
                                        let builder = self.to_type_builder(
7✔
2981
                                            f,
7✔
2982
                                            &selection_field,
7✔
2983
                                            fragment_definitions,
7✔
2984
                                            Some("Mutation".to_string()),
7✔
2985
                                            variables,
7✔
2986
                                            variable_definitions,
7✔
UNCOV
2987
                                        )?;
×
2988
                                        __SchemaField::MutationType(builder)
7✔
2989
                                    }
2990
                                    "subscriptionType" => __SchemaField::SubscriptionType(None),
5✔
2991
                                    "directives" => {
3✔
2992
                                        let builders = self
3✔
2993
                                            .directives()
3✔
2994
                                            .iter()
3✔
2995
                                            .map(|directive| {
6✔
2996
                                                self.to_directive_builder(
6✔
2997
                                                    directive,
6✔
2998
                                                    &selection_field,
6✔
2999
                                                    fragment_definitions,
6✔
3000
                                                    variables,
6✔
3001
                                                    variable_definitions,
6✔
3002
                                                )
3003
                                            })
6✔
3004
                                            .collect::<Result<Vec<_>, _>>()?;
3✔
3005
                                        __SchemaField::Directives(builders)
3✔
3006
                                    }
3007
                                    "__typename" => __SchemaField::Typename {
×
3008
                                        alias: alias_or_name(&selection_field),
×
3009
                                        typename: field.name(),
×
3010
                                    },
×
3011
                                    _ => {
3012
                                        return Err(format!(
×
3013
                                            "unexpected field {} type on __Schema",
×
3014
                                            field_name
×
3015
                                        ))
×
3016
                                    }
3017
                                },
3018
                            })
3019
                        }
3020
                    }
3021
                }
3022

3023
                Ok(__SchemaBuilder {
28✔
3024
                    description: "Represents the GraphQL schema of the database".to_string(),
28✔
3025
                    selections: builder_fields,
28✔
3026
                })
28✔
3027
            }
3028
            _ => Err("can not build query for non-__schema type".to_string()),
×
3029
        }
3030
    }
28✔
3031
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc