subgraph/data_sources/sql/create_query/create_find_many_query/
mod.rs1use std::str::FromStr;
2
3use bson::Document;
4use log::{debug, trace};
5
6use crate::{
7 configuration::subgraph::{
8 data_sources::sql::DialectEnum, entities::ServiceEntityConfig, SubGraphConfig,
9 },
10 data_sources::sql::SqlDataSource,
11 filter_operator::FilterOperator,
12 graphql::schema::create_options_input::{DirectionEnum, SortInput},
13 sql_value::SqlValue,
14};
15
16use super::JoinClauses;
17
18impl SqlDataSource {
19 pub fn create_find_many_query(
20 entity: &ServiceEntityConfig,
21 table_name: &str,
22 dialect: &DialectEnum,
23 input: &Document,
24 subgraph_config: &SubGraphConfig,
25 join_clauses: Option<JoinClauses>,
26 disable_eager_loading: bool,
27 ) -> Result<(String, Vec<SqlValue>, String, Vec<String>), async_graphql::Error> {
28 debug!("Creating Find Many Query");
29
30 let mut query = String::new();
31 let mut count_query = String::new();
32 let entity_table_name = if let Some(entity_ds) = entity.data_source.clone() {
33 if entity_ds.table.is_some() {
34 entity_ds.table.unwrap()
35 } else {
36 entity.name.clone()
37 }
38 } else {
39 entity.name.clone()
40 };
41 let select_statement = format!("SELECT {}.* FROM ", entity_table_name);
42 query.push_str(&select_statement);
43 query.push_str(table_name);
44
45 let count_statement = format!("SELECT COUNT(*) as total_count FROM {}", table_name);
46 count_query.push_str(&count_statement);
47
48 let query_input = input.get("query").unwrap();
49 let (
50 nested_query,
51 combined_where_values,
52 combined_join_clauses,
53 combined_where_keys,
54 _offset,
55 ) = SqlDataSource::create_nested_query_recursive(
56 &vec![query_input.clone()],
57 entity,
58 dialect,
59 FilterOperator::And,
60 false,
61 None,
62 subgraph_config,
63 join_clauses,
64 disable_eager_loading,
65 )?;
66
67 for join_clause in combined_join_clauses.0 {
68 trace!("Adding Join Clause: {}", join_clause);
69 query.push_str(&join_clause);
70 count_query.push_str(&join_clause);
71 }
72
73 query.push_str(" WHERE ");
74 count_query.push_str(" WHERE ");
75
76 if let Some(nested_query) = nested_query {
77 query.push_str(&nested_query);
78 count_query.push_str(&nested_query);
79 } else {
80 query.push_str("1=1");
81 count_query.push_str("1=1");
82 }
83
84 let opts_input = input.get("opts");
85 let mut per_page = 10;
86 let mut page = 1;
87 let mut sort_vec = Vec::new();
88
89 if let Some(opts_input) = opts_input {
90 let opts = opts_input.as_document().unwrap();
91 if let Some(per_page_input) = opts.get("per_page") {
92 per_page = per_page_input
93 .as_i32()
94 .unwrap_or(per_page_input.as_i64().unwrap_or(10) as i32);
95 }
96 if let Some(page_input) = opts.get("page") {
97 page = page_input
98 .as_i32()
99 .unwrap_or(page_input.as_i64().unwrap_or(1) as i32);
100 }
101
102 if let Some(sort_input) = opts.get("sort") {
103 let sort_input = sort_input.as_array();
104 if sort_input.is_none() {
105 return Err(async_graphql::Error::new("Sort input must be an array"));
106 }
107 let sort_input = sort_input.unwrap();
108 for sort_item in sort_input {
109 let sort_item = sort_item.as_document().unwrap();
110 let field = sort_item.get("field").unwrap();
111 let field = field.as_str().unwrap();
112 let direction = sort_item.get("direction").unwrap();
113 let direction = DirectionEnum::from_str(direction.as_str().unwrap()).unwrap();
114
115 sort_vec.push(SortInput {
116 field: field.to_string(),
117 direction,
118 });
119 }
120 }
121 }
122
123 if sort_vec.len() > 0 {
124 if dialect == &DialectEnum::POSTGRES {
126 query.push_str(" GROUP BY ");
127 for (i, sort_item) in sort_vec.iter().enumerate() {
128 if i > 0 {
129 query.push_str(", ");
130 }
131 query.push_str(&format!("{} ", sort_item.field));
132 }
133 }
134 query.push_str(" ORDER BY ");
135 for (i, sort_item) in sort_vec.iter().enumerate() {
136 if i > 0 {
137 query.push_str(", ");
138 }
139 query.push_str(&format!(
140 "{} {}",
141 sort_item.field,
142 sort_item.direction.to_string()
143 ));
144 }
145 }
146
147 if per_page != -1 {
148 let offset = (page - 1) * per_page;
149 query.push_str(&format!(" LIMIT {} OFFSET {}", per_page, offset));
150 }
151
152 if !query.ends_with(';') {
153 query.push(';');
154 }
155
156 if !count_query.ends_with(';') {
157 count_query.push(';');
158 }
159
160 Ok((
161 query,
162 combined_where_values,
163 count_query,
164 combined_where_keys,
165 ))
166 }
167}