wundergraph/query_builder/selection/fields/
field_list.rs1use super::{FieldListExtractor, NonTableFieldExtractor, WundergraphResolveAssociations};
2use crate::context::WundergraphContext;
3use crate::error::Result;
4use crate::helper::tuple::TupleIndex;
5use crate::query_builder::selection::query_resolver::WundergraphResolvePlaceHolderList;
6use crate::query_builder::types::placeholder::PlaceHolderMarker;
7use crate::query_builder::types::WundergraphValue;
8use crate::scalar::WundergraphScalarValue;
9use diesel::backend::Backend;
10use diesel::{Connection, Queryable};
11use juniper::{Executor, Selection};
12use std::hash::Hash;
13
14pub trait WundergraphFieldList<DB: Backend, Key, Table, Ctx> {
16 type PlaceHolder: Queryable<Self::SqlType, DB> + 'static;
21 type SqlType: 'static;
25
26 const TABLE_FIELD_COUNT: usize;
28 const NON_TABLE_FIELD_COUNT: usize;
30
31 fn resolve(
35 placeholder: Vec<Self::PlaceHolder>,
36 global_args: &[juniper::LookAheadArgument<WundergraphScalarValue>],
37 select: &juniper::LookAheadSelection<'_, WundergraphScalarValue>,
38 selection: Option<&'_ [Selection<'_, WundergraphScalarValue>]>,
39 name_list: &'static [&'static str],
40 executor: &Executor<'_, Ctx, WundergraphScalarValue>,
41 ) -> Result<Vec<juniper::Value<WundergraphScalarValue>>>;
42
43 #[doc(hidden)]
44 fn map_table_field<F: Fn(usize) -> R, R>(local_index: usize, callback: F) -> Option<R>;
45 #[doc(hidden)]
46 fn map_non_table_field<Func: Fn(usize) -> Ret, Ret>(
47 local_index: usize,
48 callback: Func,
49 ) -> Option<Ret>;
50}
51
52macro_rules! wundergraph_impl_field_list {
53 ($(
54 $Tuple:tt {
55 $(($idx:tt) -> $T:ident, $ST: ident, $TT: ident,) +
56 }
57 )+) => {
58 $(
59
60 impl<Back, Key, Table, Ctx, $($T,)*> WundergraphFieldList<Back, Key, Table, Ctx> for ($($T,)*)
61 where Back: Backend,
62 ($($T,)*): FieldListExtractor + NonTableFieldExtractor,
63 <($($T,)*) as FieldListExtractor>::Out: WundergraphValue,
64 <<($($T,)*) as FieldListExtractor>::Out as WundergraphValue>::PlaceHolder: TupleIndex<Key> +
65 Queryable<<<($($T,)*) as FieldListExtractor>::Out as WundergraphValue>::SqlType, Back> + 'static,
66 Vec<<<($($T,)*) as FieldListExtractor>::Out as WundergraphValue>::PlaceHolder>:
67 WundergraphResolvePlaceHolderList<<($($T,)*) as FieldListExtractor>::Out, Back, Ctx>,
68 <<<($($T,)*) as FieldListExtractor>::Out as WundergraphValue>::PlaceHolder as TupleIndex<Key>>::Value: PlaceHolderMarker,
69 <<<<($($T,)*) as FieldListExtractor>::Out as WundergraphValue>::PlaceHolder as TupleIndex<Key>>::Value as PlaceHolderMarker>::InnerType: Eq + Hash + Clone,
70 <($($T,)*) as NonTableFieldExtractor>::Out: WundergraphResolveAssociations<<<<<($($T,)*) as FieldListExtractor>::Out as WundergraphValue>::PlaceHolder as TupleIndex<Key>>::Value as PlaceHolderMarker>::InnerType, Table, Back, Ctx>,
71 Ctx: WundergraphContext,
72 Ctx::Connection: Connection<Backend = Back>,
73 {
74 type PlaceHolder = <<($($T,)*) as FieldListExtractor>::Out as WundergraphValue>::PlaceHolder;
75 type SqlType = <<($($T,)*) as FieldListExtractor>::Out as WundergraphValue>::SqlType;
76
77 const TABLE_FIELD_COUNT: usize = <($($T,)*) as FieldListExtractor>::FIELD_COUNT;
78 const NON_TABLE_FIELD_COUNT: usize = <($($T,)*) as NonTableFieldExtractor>::FIELD_COUNT;
79
80 fn resolve(
81 placeholder: Vec<Self::PlaceHolder>,
82 global_args: &[juniper::LookAheadArgument<WundergraphScalarValue>],
83 look_ahead: &juniper::LookAheadSelection<'_, WundergraphScalarValue>,
84 selection: Option<&'_ [Selection<'_, WundergraphScalarValue>]>,
85 name_list: &'static [&'static str],
86 executor: &Executor<'_, Ctx, WundergraphScalarValue>,
87 ) -> Result<Vec<juniper::Value<WundergraphScalarValue>>> {
88 let extern_values = {
89 let keys = || {
90 placeholder.iter()
91 .map(TupleIndex::<Key>::get)
92 .map(<_ as PlaceHolderMarker>::into_inner)
93 .collect::<Vec<_>>()
94 };
95
96 let name = |local_pos| {
97 <($($T,)*) as NonTableFieldExtractor>::map(
98 local_pos,
99 |pos| name_list[pos]
100 ).expect("Name is there")
101 };
102 <($($T,)*) as NonTableFieldExtractor>::Out::resolve(
103 global_args, look_ahead, selection, name, keys, executor,
104 )?
105 };
106 let name = |local_pos| {
107 <($($T,)*) as FieldListExtractor>::map(local_pos, |pos| {
108 name_list[pos]
109 }).expect("Name is there")
110 };
111 let objs = placeholder.resolve(
112 name,
113 global_args,
114 look_ahead,
115 selection,
116 executor,
117 )?;
118
119 Ok(extern_values.merge_with_object_list(objs))
120 }
121
122 #[inline(always)]
123 fn map_table_field<Func: Fn(usize) -> Ret, Ret>(local_index: usize, callback: Func) -> Option<Ret> {
124 <($($T,)*) as FieldListExtractor>::map(local_index, callback)
125 }
126
127 #[inline(always)]
128 fn map_non_table_field<Func: Fn(usize) -> Ret, Ret>(local_index: usize, callback: Func) -> Option<Ret> {
129 <($($T,)*) as NonTableFieldExtractor>::map(local_index, callback)
130 }
131 }
132 )*
133 }
134}
135__diesel_for_each_tuple!(wundergraph_impl_field_list);