subgraph/data_sources/sql/create_query/create_nested_query_recursive/
mod.rs1use bson::{doc, Bson};
2use log::{debug, trace};
3
4use crate::{
5 configuration::subgraph::{
6 data_sources::sql::DialectEnum, entities::ServiceEntityConfig, SubGraphConfig,
7 },
8 data_sources::sql::SqlDataSource,
9 filter_operator::FilterOperator,
10 resolver_type::ResolverType,
11 sql_value::SqlValue,
12};
13
14use super::JoinClauses;
15
16impl SqlDataSource {
17 pub fn create_nested_query_recursive(
18 inputs: &Vec<Bson>,
19 entity: &ServiceEntityConfig,
20 dialect: &DialectEnum,
21 filter_by_operator: FilterOperator,
22 has_more: bool,
23 pg_param_offset: Option<i32>,
24 subgraph_config: &SubGraphConfig,
25 join_clauses: Option<JoinClauses>,
26 disable_eager_loading: bool,
27 ) -> Result<
28 (
29 Option<String>,
30 Vec<SqlValue>,
31 JoinClauses,
32 Vec<String>,
33 Option<i32>,
34 ),
35 async_graphql::Error,
36 > {
37 debug!("Creating Recursive Nested Query");
38 trace!("Initial Inputs: {:?}", inputs);
39 trace!("Initial Join Clauses: {:?}", join_clauses);
40 trace!("Pg Param Offset: {:?}", pg_param_offset);
41 let mut nested_query = String::new();
42 let mut combined_where_values = vec![];
43 let mut combined_where_keys = vec![];
44 let mut combined_join_clauses = join_clauses.unwrap_or(JoinClauses(Vec::new()));
45
46 nested_query.push_str(" (");
47
48 let mut pg_param_offset = Some(pg_param_offset.unwrap_or(0));
49 trace!("Pg Param Offset Init: {:?}", pg_param_offset);
50
51 for (i, filter) in inputs.iter().enumerate() {
52 let mut recursive_filters = vec![];
54 for filter_operator in FilterOperator::list() {
55 let filter = filter.as_document().unwrap().get(filter_operator.as_str());
56 recursive_filters.push((filter_operator, filter));
57 }
58
59 let mut initial_input = filter.clone().as_document().unwrap().clone();
60 let mut is_nested = false;
61
62 for filter_operator in FilterOperator::list() {
65 if initial_input.contains_key(filter_operator.as_str()) {
66 initial_input.remove(filter_operator.as_str());
67 is_nested = true;
68 }
69 }
70
71 let query_input = doc! { "query": initial_input };
73
74 let (where_keys, where_values, _value_keys, _values, join_clauses) =
76 SqlDataSource::get_key_data(
77 &query_input,
78 entity,
79 &ResolverType::FindOne,
80 &dialect,
81 &subgraph_config,
82 disable_eager_loading,
83 )?;
84 combined_join_clauses.0.extend(join_clauses.0);
85 combined_where_values.extend(where_values.clone());
86 combined_where_keys.extend(where_keys.clone());
87
88 let (parameterized_query, offset) = SqlDataSource::create_where_clause(
89 &where_keys,
90 dialect,
91 pg_param_offset,
92 &where_values,
93 filter_by_operator.clone(),
94 )?;
95
96 pg_param_offset = Some(offset);
97
98 nested_query.push_str(¶meterized_query);
99
100 if is_nested && i == 0 && !has_more && nested_query != " (" {
101 nested_query.push_str(" AND ");
102 }
103
104 for (i, recursive_filter) in recursive_filters.iter().enumerate() {
105 if recursive_filter.1.is_none() {
106 continue;
107 }
108
109 let filters = match recursive_filter.0 {
110 FilterOperator::And | FilterOperator::Or => recursive_filter
111 .1
112 .clone()
113 .unwrap()
114 .as_array()
115 .unwrap()
116 .clone(),
117 _ => {
118 let doc = recursive_filter.1.clone().unwrap().as_document().unwrap();
119 let mut array = vec![];
120 array.push(Bson::Document(doc.clone()));
121 array
122 }
123 };
124 let is_last = i == recursive_filters.len() - 1;
125 let has_more = if !is_last && recursive_filters[i + 1].1.is_some() {
126 true
127 } else {
128 false
129 };
130 let (
131 recursive_query,
132 recursive_where_values,
133 recursive_join_clauses,
134 recursive_where_keys,
135 offset,
136 ) = SqlDataSource::create_nested_query_recursive(
137 &filters,
138 entity,
139 dialect,
140 recursive_filter.0.clone(),
141 has_more,
142 pg_param_offset,
143 subgraph_config,
144 Some(combined_join_clauses.clone()),
145 disable_eager_loading,
146 )?;
147
148 combined_where_values.extend(recursive_where_values);
149 combined_where_keys.extend(recursive_where_keys);
150 combined_join_clauses.0.extend(recursive_join_clauses.0);
151 if offset.is_some() {
152 pg_param_offset = offset;
153 }
154
155 if recursive_query.is_some() {
156 nested_query.push_str(&recursive_query.unwrap());
157 }
158 }
159
160 if i != inputs.len() - 1 {
161 match filter_by_operator {
162 FilterOperator::And => nested_query.push_str(" AND "),
163 FilterOperator::Or => nested_query.push_str(" OR "),
164 _ => (),
165 }
166 }
167 }
168
169 nested_query.push_str(")");
170
171 if has_more {
172 nested_query.push_str(" AND ");
173 }
174
175 let is_empty = nested_query.contains("()");
176 let is_empty_and =
177 nested_query.contains(FilterOperator::And.as_str()) && nested_query.contains("()");
178 if is_empty || nested_query.is_empty() || is_empty_and {
179 return Ok((
180 None,
181 combined_where_values,
182 combined_join_clauses,
183 combined_where_keys,
184 pg_param_offset,
185 ));
186 }
187
188 combined_join_clauses.0.sort();
190 combined_join_clauses.0.dedup();
191
192 trace!("Nested query: {}", nested_query);
193 trace!("Combined Where Values: {:?}", combined_where_values);
194 trace!("Combined Join Clauses: {:?}", combined_join_clauses);
195 trace!("Combined Where Keys: {:?}", combined_where_keys);
196
197 Ok((
198 Some(nested_query),
199 combined_where_values,
200 combined_join_clauses,
201 combined_where_keys,
202 pg_param_offset,
203 ))
204 }
205}