1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
use super::{utils::get_relation_load_strategy, *};
use crate::{query_document::*, QueryOption, QueryOptions, ReadQuery, RecordQuery};
use query_structure::Model;
use schema::{constants::args, QuerySchema};
use std::convert::TryInto;

pub(crate) fn find_unique(
    field: ParsedField<'_>,
    model: Model,
    query_schema: &QuerySchema,
) -> QueryGraphBuilderResult<ReadQuery> {
    find_unique_with_options(field, model, QueryOptions::none(), query_schema)
}

pub(crate) fn find_unique_or_throw(
    field: ParsedField<'_>,
    model: Model,
    query_schema: &QuerySchema,
) -> QueryGraphBuilderResult<ReadQuery> {
    find_unique_with_options(field, model, QueryOption::ThrowOnEmpty.into(), query_schema)
}

/// Builds a read query from a parsed incoming read query field.
#[inline]
fn find_unique_with_options(
    mut field: ParsedField<'_>,
    model: Model,
    options: QueryOptions,
    query_schema: &QuerySchema,
) -> QueryGraphBuilderResult<ReadQuery> {
    let filter = match field.arguments.lookup(args::WHERE) {
        Some(where_arg) => {
            let arg: ParsedInputMap<'_> = where_arg.value.try_into()?;
            Some(extractors::extract_unique_filter(arg, &model)?)
        }
        None => None,
    };

    let requested_rel_load_strategy = field
        .arguments
        .lookup(args::RELATION_LOAD_STRATEGY)
        .map(|arg| arg.value.try_into())
        .transpose()?;

    let name = field.name;
    let alias = field.alias;
    let nested_fields = field.nested_fields.unwrap().fields;
    let selection_order = utils::collect_selection_order(&nested_fields);
    let selected_fields = utils::collect_selected_fields(&nested_fields, None, &model, query_schema)?;
    let nested = utils::collect_nested_queries(nested_fields, &model, query_schema)?;
    let selected_fields = utils::merge_relation_selections(selected_fields, None, &nested);

    let relation_load_strategy =
        get_relation_load_strategy(requested_rel_load_strategy, None, None, &nested, query_schema);

    Ok(ReadQuery::RecordQuery(RecordQuery {
        name,
        alias,
        model,
        filter,
        selected_fields,
        nested,
        selection_order,
        options,
        relation_load_strategy,
    }))
}