1use std::collections::HashMap;
10use std::marker::PhantomData;
11use std::sync::Arc;
12
13use crate::entity::{
14 IEntitySnapshot, IEntityType, IFromRow, IGetKeyValues, ILazyInit, INavigationSetter,
15};
16use crate::error::EFResult;
17use crate::provider::{DbValue, DbValueConvertError, IDatabaseProvider};
18
19use super::ast::{
20 AggKind, BoolExpr, CompareOp, CompiledFilter, FilterCondition, HavingExpr, InSubquerySpec,
21 IncludePath, JoinSpec, OrderBy, OrderDirection, SubquerySpec,
22};
23use super::compile::{
24 build_where_clauses, collect_bool_expr_values, compile_bool_expr, convert_aggregate_cell,
25 filters_to_and_expr, has_subqueries, resolve_subqueries,
26};
27use super::cte::{CteSpec, SetOpSpec, SetOperator};
28use super::execute_update::ExecuteUpdateBuilder;
29use super::select::SelectQueryBuilder;
30use super::state::QueryState;
31use super::window::{WindowFuncKind, WindowSpec};
32
33#[derive(Clone)]
42pub struct QueryBuilder<T: IEntityType> {
43 state: QueryState,
44 provider: Option<Arc<dyn IDatabaseProvider>>,
45 filter_map: Option<Arc<HashMap<String, CompiledFilter>>>,
46 lazy_loading_enabled: bool,
47 _phantom: PhantomData<T>,
48}
49
50impl<T: IEntityType> QueryBuilder<T> {
51 pub fn new(table_name: impl Into<String>) -> Self {
53 Self {
54 state: QueryState::new(table_name),
55 provider: None,
56 filter_map: None,
57 lazy_loading_enabled: false,
58 _phantom: PhantomData,
59 }
60 }
61
62 pub fn with_provider(
64 table_name: impl Into<String>,
65 provider: Arc<dyn IDatabaseProvider>,
66 ) -> Self {
67 Self {
68 state: QueryState::new(table_name),
69 provider: Some(provider),
70 filter_map: None,
71 lazy_loading_enabled: false,
72 _phantom: PhantomData,
73 }
74 }
75
76 pub(crate) fn with_filter_map(
78 mut self,
79 map: Option<Arc<HashMap<String, CompiledFilter>>>,
80 ) -> Self {
81 self.filter_map = map;
82 self
83 }
84
85 pub(crate) fn with_lazy_loading(mut self, enabled: bool) -> Self {
87 self.lazy_loading_enabled = enabled;
88 self
89 }
90
91 pub fn state(&self) -> &QueryState {
93 &self.state
94 }
95
96 pub fn filter(self, f: impl FnOnce(Self) -> Self) -> Self {
98 f(self)
99 }
100
101 #[doc(hidden)]
106 pub fn filter_column(
107 mut self,
108 column: &str,
109 operator: &str,
110 value: impl Into<DbValue>,
111 ) -> Self {
112 let db_val = value.into();
113 self.state.parameters.push(db_val);
114 self.state
115 .append_filter(FilterCondition::new(column, operator, 1));
116 self
117 }
118
119 #[doc(hidden)]
120 pub fn filter_not(mut self, column: &str, operator: &str, value: impl Into<DbValue>) -> Self {
121 let db_val = value.into();
122 self.state.parameters.push(db_val);
123 self.state
124 .append_bool_expr(BoolExpr::Not(Box::new(BoolExpr::Filter(
125 FilterCondition::new(column, operator, 1),
126 ))));
127 self
128 }
129
130 #[doc(hidden)]
131 pub fn filter_in(mut self, column: &str, values: Vec<DbValue>) -> Self {
132 let count = values.len();
133 for v in values {
134 self.state.parameters.push(v);
135 }
136 self.state
137 .append_filter(FilterCondition::new(column, "IN", count));
138 self
139 }
140
141 #[doc(hidden)]
142 pub fn filter_not_in(mut self, column: &str, values: Vec<DbValue>) -> Self {
143 let count = values.len();
144 for v in values {
145 self.state.parameters.push(v);
146 }
147 self.state
148 .append_bool_expr(BoolExpr::Not(Box::new(BoolExpr::Filter(
149 FilterCondition::new(column, "IN", count),
150 ))));
151 self
152 }
153
154 #[doc(hidden)]
155 pub fn filter_is_null(mut self, column: &str) -> Self {
156 self.state
157 .append_filter(FilterCondition::new(column, "IS NULL", 0));
158 self
159 }
160
161 #[doc(hidden)]
162 pub fn filter_is_not_null(mut self, column: &str) -> Self {
163 self.state
164 .append_filter(FilterCondition::new(column, "IS NOT NULL", 0));
165 self
166 }
167
168 #[doc(hidden)]
169 pub fn filter_between(
170 mut self,
171 column: &str,
172 low: impl Into<DbValue>,
173 high: impl Into<DbValue>,
174 ) -> Self {
175 let lo: DbValue = low.into();
176 let hi: DbValue = high.into();
177 self.state.parameters.push(lo);
178 self.state.parameters.push(hi);
179 self.state
180 .append_filter(FilterCondition::new(column, "BETWEEN", 2));
181 self
182 }
183
184 #[doc(hidden)]
185 pub fn filter_like(self, column: &str, pattern: impl Into<DbValue>) -> Self {
186 self.filter_column(column, "LIKE", pattern)
187 }
188
189 #[doc(hidden)]
190 pub fn filter_not_like(self, column: &str, pattern: impl Into<DbValue>) -> Self {
191 self.filter_not(column, "LIKE", pattern)
192 }
193
194 #[doc(hidden)]
195 pub fn order_by_column(mut self, column: &str) -> Self {
196 self.state
197 .orderings
198 .push(OrderBy::new(column, OrderDirection::Ascending));
199 self
200 }
201
202 #[doc(hidden)]
203 pub fn order_by_desc_column(mut self, column: &str) -> Self {
204 self.state
205 .orderings
206 .push(OrderBy::new(column, OrderDirection::Descending));
207 self
208 }
209
210 pub(crate) fn apply_query_filter(mut self, filter: BoolExpr) -> Self {
214 let values = collect_bool_expr_values(&filter);
215 self.state.parameters.extend(values);
216 self.state.append_bool_expr(filter);
217 self
218 }
219
220 pub fn distinct(mut self) -> Self {
222 self.state.distinct = true;
223 self
224 }
225
226 #[doc(hidden)]
227 pub fn or_where(mut self, f: impl FnOnce(QueryBuilder<T>) -> QueryBuilder<T>) -> Self {
228 let sub = f(QueryBuilder {
229 state: QueryState::new(&self.state.from),
230 provider: self.provider.clone(),
231 filter_map: None,
232 lazy_loading_enabled: false,
233 _phantom: PhantomData,
234 });
235 let right = sub.state.where_expr.or_else(|| {
236 if sub.state.filters.is_empty() {
237 None
238 } else {
239 Some(filters_to_and_expr(&sub.state.filters))
240 }
241 });
242 if let Some(right_expr) = right {
243 self.state.where_expr = Some(match self.state.where_expr.take() {
244 None => right_expr,
245 Some(left) => BoolExpr::Or(Box::new(left), Box::new(right_expr)),
246 });
247 self.state.parameters.extend(sub.state.parameters);
248 self.state.filters.extend(sub.state.filters);
249 }
250 self
251 }
252
253 pub fn where_exists_internal(
263 mut self,
264 nav_field: &'static str,
265 related_type: &'static str,
266 predicate: Option<BoolExpr>,
267 negated: bool,
268 ) -> Self {
269 let mut spec = SubquerySpec::new(nav_field, related_type);
270 if let Some(pred) = predicate {
271 let values = collect_bool_expr_values(&pred);
276 self.state.parameters.extend(values);
277 spec.predicate = Some(Box::new(pred));
278 }
279 let expr = if negated {
280 BoolExpr::NotExists(Box::new(spec))
281 } else {
282 BoolExpr::Exists(Box::new(spec))
283 };
284 self.state.append_bool_expr(expr);
285 self
286 }
287
288 pub fn where_in_subquery_internal(
300 mut self,
301 outer_column: &'static str,
302 source_table: &'static str,
303 projection_column: &'static str,
304 predicate: Option<BoolExpr>,
305 negated: bool,
306 ) -> Self {
307 let mut spec = InSubquerySpec::new(outer_column, source_table, projection_column);
308 if let Some(pred) = predicate {
309 let values = collect_bool_expr_values(&pred);
310 self.state.parameters.extend(values);
311 spec.predicate = Some(Box::new(pred));
312 }
313 let expr = if negated {
314 BoolExpr::NotInSubquery(Box::new(spec))
315 } else {
316 BoolExpr::InSubquery(Box::new(spec))
317 };
318 self.state.append_bool_expr(expr);
319 self
320 }
321
322 pub async fn find(self, id: impl Into<DbValue>) -> EFResult<Option<T>>
329 where
330 T: IFromRow + INavigationSetter + IGetKeyValues + IEntitySnapshot + ILazyInit,
331 {
332 let meta = T::entity_meta();
333 let pk_col = meta
334 .primary_keys
335 .first()
336 .map(|s| s.as_ref())
337 .or_else(|| {
338 meta.properties
339 .iter()
340 .find(|p| p.is_primary_key)
341 .map(|p| p.column_name.as_ref())
342 })
343 .ok_or_else(|| {
344 crate::error::EFError::query(format!(
345 "entity {} has no primary key defined",
346 std::any::type_name::<T>()
347 ))
348 })?;
349 let col_const = pk_col.to_string();
350 self.filter_column(&col_const, "=", id)
351 .first_or_default()
352 .await
353 }
354
355 pub async fn find_by_key(mut self, keys: &[(&str, DbValue)]) -> EFResult<Option<T>>
358 where
359 T: IFromRow + INavigationSetter + IGetKeyValues + IEntitySnapshot + ILazyInit,
360 {
361 for (col, val) in keys {
362 self = self.filter_column(col, "=", val.clone());
363 }
364 self.first_or_default().await
365 }
366
367 pub async fn exists_by_id(self, id: impl Into<DbValue>) -> EFResult<bool> {
373 let meta = T::entity_meta();
374 let pk_col = meta
375 .primary_keys
376 .first()
377 .map(|s| s.as_ref())
378 .or_else(|| {
379 meta.properties
380 .iter()
381 .find(|p| p.is_primary_key)
382 .map(|p| p.column_name.as_ref())
383 })
384 .ok_or_else(|| {
385 crate::error::EFError::query(format!(
386 "entity {} has no primary key defined",
387 std::any::type_name::<T>()
388 ))
389 })?;
390 let col_const = pk_col.to_string();
391 self.filter_column(&col_const, "=", id).any().await
392 }
393
394 pub async fn exists_by_key(mut self, keys: &[(&str, DbValue)]) -> EFResult<bool> {
398 for (col, val) in keys {
399 self = self.filter_column(col, "=", val.clone());
400 }
401 self.any().await
402 }
403
404 pub fn skip(mut self, count: usize) -> Self {
406 self.state.offset = Some(count);
407 self
408 }
409
410 pub fn take(mut self, count: usize) -> Self {
412 self.state.limit = Some(count);
413 self
414 }
415
416 #[doc(hidden)]
421 pub fn include_internal(mut self, navigation: &'static str) -> Self {
422 let meta = T::entity_meta();
423 let nav_meta = meta.find_navigation(navigation);
424 let (related_table, fk_col, ref_col) = nav_meta
425 .map(|n| {
426 (
427 n.related_table.as_ref().map(|s| s.to_string()),
428 n.fk_column.as_ref().map(|s| s.to_string()),
429 n.referenced_key_column.as_ref().map(|s| s.to_string()),
430 )
431 })
432 .unwrap_or((None, None, None));
433
434 self.state.includes.push(IncludePath {
435 navigation: navigation.to_string(),
436 nested: Vec::new(),
437 related_table,
438 foreign_key_column: fk_col,
439 referenced_key_column: ref_col,
440 });
441 self
442 }
443
444 #[doc(hidden)]
450 pub fn then_include_internal(mut self, navigation: &'static str) -> Self {
451 if let Some(last) = self.state.includes.last_mut() {
452 let parent_meta = T::entity_meta();
453 if let Some(parent_nav) = parent_meta.find_navigation(&last.navigation) {
454 if let Some(meta_fn) = parent_nav.related_entity_meta {
455 let related_meta = meta_fn();
456 if let Some(nav_meta) = related_meta.find_navigation(navigation) {
457 last.nested.push(IncludePath {
458 navigation: navigation.to_string(),
459 nested: Vec::new(),
460 related_table: nav_meta.related_table.as_ref().map(|s| s.to_string()),
461 foreign_key_column: nav_meta.fk_column.as_ref().map(|s| s.to_string()),
462 referenced_key_column: nav_meta
463 .referenced_key_column
464 .as_ref()
465 .map(|s| s.to_string()),
466 });
467 }
468 }
469 }
470 }
471 self
472 }
473
474 #[doc(hidden)]
479 pub fn inner_join_internal(
480 mut self,
481 table: &'static str,
482 left_column: &'static str,
483 right_column: &'static str,
484 ) -> Self {
485 let on_clause = format!(
486 "{}.{} = {}.{}",
487 self.state.from, left_column, table, right_column
488 );
489 self.state.joins.push(JoinSpec {
490 join_type: "INNER".to_string(),
491 table: table.to_string(),
492 on_clause,
493 });
494 self
495 }
496
497 #[doc(hidden)]
502 pub fn left_join_internal(
503 mut self,
504 table: &'static str,
505 left_column: &'static str,
506 right_column: &'static str,
507 ) -> Self {
508 let on_clause = format!(
509 "{}.{} = {}.{}",
510 self.state.from, left_column, table, right_column
511 );
512 self.state.joins.push(JoinSpec {
513 join_type: "LEFT".to_string(),
514 table: table.to_string(),
515 on_clause,
516 });
517 self
518 }
519
520 #[doc(hidden)]
525 pub fn right_join_internal(
526 mut self,
527 table: &'static str,
528 left_column: &'static str,
529 right_column: &'static str,
530 ) -> Self {
531 let on_clause = format!(
532 "{}.{} = {}.{}",
533 self.state.from, left_column, table, right_column
534 );
535 self.state.joins.push(JoinSpec {
536 join_type: "RIGHT".to_string(),
537 table: table.to_string(),
538 on_clause,
539 });
540 self
541 }
542
543 #[doc(hidden)]
551 pub fn full_join_internal(
552 mut self,
553 table: &'static str,
554 left_column: &'static str,
555 right_column: &'static str,
556 ) -> Self {
557 let on_clause = format!(
558 "{}.{} = {}.{}",
559 self.state.from, left_column, table, right_column
560 );
561 self.state.joins.push(JoinSpec {
562 join_type: "FULL".to_string(),
563 table: table.to_string(),
564 on_clause,
565 });
566 self
567 }
568
569 #[doc(hidden)]
573 pub fn cross_join_internal(mut self, table: &'static str) -> Self {
574 self.state.joins.push(JoinSpec {
575 join_type: "CROSS".to_string(),
576 table: table.to_string(),
577 on_clause: String::new(),
578 });
579 self
580 }
581
582 #[doc(hidden)]
586 pub fn group_by_internal(mut self, columns: &'static [&'static str]) -> Self {
587 self.state.group_bys = columns.iter().map(|s| s.to_string()).collect();
588 self
589 }
590
591 #[doc(hidden)]
596 pub fn having_internal(
597 mut self,
598 agg: &str,
599 column: &str,
600 op: &str,
601 value: impl Into<DbValue>,
602 ) -> Self {
603 let agg_kind = AggKind::from_name(agg)
604 .unwrap_or_else(|| panic!("invalid aggregate name in having_internal: {agg}"));
605 let cmp_op = CompareOp::from_symbol(op)
606 .unwrap_or_else(|| panic!("invalid operator in having_internal: {op}"));
607 let db_val = value.into();
608 self.state.parameters.push(db_val.clone());
609 self.state.havings.push(HavingExpr::Compare {
610 agg: agg_kind,
611 col: column.to_string(),
612 op: cmp_op,
613 value: db_val,
614 });
615 self
616 }
617
618 #[doc(hidden)]
627 pub fn having_expr_internal(mut self, expr: HavingExpr) -> Self {
628 self.state.parameters.extend(expr.collect_params());
629 self.state.havings.push(expr);
630 self
631 }
632
633 #[doc(hidden)]
647 pub fn window_internal(
648 mut self,
649 func: &str,
650 column: Option<&str>,
651 partition_by: &'static [&'static str],
652 order_by: &'static [(&'static str, bool)],
653 alias: &str,
654 ) -> Self {
655 let kind = WindowFuncKind::from_name(func)
656 .unwrap_or_else(|| panic!("invalid window function name: {func}"));
657 if kind.takes_column() && column.is_none() {
658 panic!("window function `{func}` requires a column argument");
659 }
660 let spec = WindowSpec {
661 func: kind,
662 column: column.map(|s| s.to_string()),
663 partition_by: partition_by.iter().map(|s| s.to_string()).collect(),
664 order_by: order_by
665 .iter()
666 .map(|(c, d)| {
667 (
668 c.to_string(),
669 if *d {
670 OrderDirection::Descending
671 } else {
672 OrderDirection::Ascending
673 },
674 )
675 })
676 .collect(),
677 alias: alias.to_string(),
678 };
679 self.state.windows.push(spec);
680 self
681 }
682
683 #[doc(hidden)]
696 pub fn with_cte_internal(
697 mut self,
698 name: &str,
699 sql: &str,
700 params: Vec<DbValue>,
701 columns: &'static [&'static str],
702 ) -> Self {
703 let cte = CteSpec {
704 name: name.to_string(),
705 sql: sql.to_string(),
706 table: String::new(),
707 where_expr: None,
708 params,
709 columns: columns.iter().map(|s| s.to_string()).collect(),
710 is_recursive: false,
711 recursive_link: None,
712 };
713 self.state.ctes.push(cte);
714 self
715 }
716
717 #[doc(hidden)]
729 pub fn with_cte_typed(mut self, name: &str, table: &str, where_expr: BoolExpr) -> Self {
730 let params = collect_bool_expr_values(&where_expr);
731 let cte = CteSpec {
732 name: name.to_string(),
733 sql: String::new(),
734 table: table.to_string(),
735 where_expr: Some(where_expr),
736 params,
737 columns: Vec::new(),
738 is_recursive: false,
739 recursive_link: None,
740 };
741 self.state.ctes.push(cte);
742 self
743 }
744
745 #[doc(hidden)]
755 pub fn with_recursive_cte_typed(
756 mut self,
757 name: &str,
758 table: &str,
759 link_fk: &str,
760 link_pk: &str,
761 where_expr: BoolExpr,
762 ) -> Self {
763 let params = collect_bool_expr_values(&where_expr);
764 let cte = CteSpec {
765 name: name.to_string(),
766 sql: String::new(),
767 table: table.to_string(),
768 where_expr: Some(where_expr),
769 params,
770 columns: Vec::new(),
771 is_recursive: true,
772 recursive_link: Some((link_fk.to_string(), link_pk.to_string())),
773 };
774 self.state.ctes.push(cte);
775 self
776 }
777
778 #[doc(hidden)]
786 pub fn from_cte(mut self, name: &str) -> Self {
787 self.state.from = name.to_string();
788 self
789 }
790
791 #[doc(hidden)]
800 pub fn union_internal(mut self, operand: (String, Vec<DbValue>)) -> Self {
801 self.state.set_operations.push(SetOpSpec {
802 operator: SetOperator::Union,
803 operand_sql: operand.0,
804 operand_params: operand.1,
805 });
806 self
807 }
808
809 #[doc(hidden)]
811 pub fn union_all_internal(mut self, operand: (String, Vec<DbValue>)) -> Self {
812 self.state.set_operations.push(SetOpSpec {
813 operator: SetOperator::UnionAll,
814 operand_sql: operand.0,
815 operand_params: operand.1,
816 });
817 self
818 }
819
820 #[doc(hidden)]
822 pub fn intersect_internal(mut self, operand: (String, Vec<DbValue>)) -> Self {
823 self.state.set_operations.push(SetOpSpec {
824 operator: SetOperator::Intersect,
825 operand_sql: operand.0,
826 operand_params: operand.1,
827 });
828 self
829 }
830
831 #[doc(hidden)]
833 pub fn except_internal(mut self, operand: (String, Vec<DbValue>)) -> Self {
834 self.state.set_operations.push(SetOpSpec {
835 operator: SetOperator::Except,
836 operand_sql: operand.0,
837 operand_params: operand.1,
838 });
839 self
840 }
841
842 #[doc(hidden)]
850 pub async fn sum_internal(self, column: &'static str) -> EFResult<f64> {
851 let mut state = self.state.clone();
852 state.aggregate = Some("SUM".to_string());
853 state.aggregate_column = Some(column.to_string());
854 let provider = self.provider.as_ref().ok_or_else(|| {
855 crate::error::EFError::configuration(
856 "No provider attached to QueryBuilder.".to_string(),
857 )
858 })?;
859 let sql = Self::compile_state_sql(&state, provider);
860 let params = state.all_params();
861 let mut conn = provider.get_connection().await?;
862 let rows = conn.query(&sql, ¶ms).await?;
863 if let Some(first) = rows.first().and_then(|r| r.first()) {
864 f64::try_from(first.clone()).map_err(|_| {
865 crate::error::EFError::type_conversion("SUM result is not f64".to_string())
866 })
867 } else {
868 Ok(0.0)
869 }
870 }
871
872 #[doc(hidden)]
876 pub async fn avg_internal(self, column: &'static str) -> EFResult<f64> {
877 let mut state = self.state.clone();
878 state.aggregate = Some("AVG".to_string());
879 state.aggregate_column = Some(column.to_string());
880 let provider = self.provider.as_ref().ok_or_else(|| {
881 crate::error::EFError::configuration(
882 "No provider attached to QueryBuilder.".to_string(),
883 )
884 })?;
885 let sql = Self::compile_state_sql(&state, provider);
886 let params = state.all_params();
887 let mut conn = provider.get_connection().await?;
888 let rows = conn.query(&sql, ¶ms).await?;
889 if let Some(first) = rows.first().and_then(|r| r.first()) {
890 f64::try_from(first.clone()).map_err(|_| {
891 crate::error::EFError::type_conversion("AVG result is not f64".to_string())
892 })
893 } else {
894 Ok(0.0)
895 }
896 }
897
898 #[doc(hidden)]
903 pub async fn min_internal<V>(self, column: &'static str) -> EFResult<Option<V>>
904 where
905 V: TryFrom<DbValue, Error = DbValueConvertError>,
906 {
907 let mut state = self.state.clone();
908 state.aggregate = Some("MIN".to_string());
909 state.aggregate_column = Some(column.to_string());
910 let provider = self.provider.as_ref().ok_or_else(|| {
911 crate::error::EFError::configuration(
912 "No provider attached to QueryBuilder.".to_string(),
913 )
914 })?;
915 let sql = Self::compile_state_sql(&state, provider);
916 let params = state.all_params();
917 let mut conn = provider.get_connection().await?;
918 let rows = conn.query(&sql, ¶ms).await?;
919 convert_aggregate_cell::<V>(rows)
920 }
921
922 #[doc(hidden)]
927 pub async fn max_internal<V>(self, column: &'static str) -> EFResult<Option<V>>
928 where
929 V: TryFrom<DbValue, Error = DbValueConvertError>,
930 {
931 let mut state = self.state.clone();
932 state.aggregate = Some("MAX".to_string());
933 state.aggregate_column = Some(column.to_string());
934 let provider = self.provider.as_ref().ok_or_else(|| {
935 crate::error::EFError::configuration(
936 "No provider attached to QueryBuilder.".to_string(),
937 )
938 })?;
939 let sql = Self::compile_state_sql(&state, provider);
940 let params = state.all_params();
941 let mut conn = provider.get_connection().await?;
942 let rows = conn.query(&sql, ¶ms).await?;
943 convert_aggregate_cell::<V>(rows)
944 }
945
946 #[doc(hidden)]
954 pub fn select_internal(self, columns: &'static [&'static str]) -> SelectQueryBuilder<T> {
955 let mut state = self.state.clone();
956 state.projected_columns = Some(columns.iter().map(|s| s.to_string()).collect());
957 SelectQueryBuilder {
958 state,
959 provider: self.provider,
960 _phantom: PhantomData,
961 }
962 }
963
964 pub fn to_sql(&self) -> String {
970 let mut state = self.state.clone();
972 if let Some(ref mut expr) = state.where_expr {
973 if has_subqueries(expr) {
974 let meta = T::entity_meta();
975 resolve_subqueries(expr, &meta);
976 }
977 }
978 if let Some(provider) = &self.provider {
979 let gen = provider.sql_generator();
980 state.to_sql_with(gen)
981 } else {
982 state.to_sql()
983 }
984 }
985
986 pub fn compile_sql(&self) -> (String, Vec<DbValue>) {
987 (self.to_sql(), self.state.all_params())
988 }
989
990 fn compile_state_sql(state: &QueryState, provider: &Arc<dyn IDatabaseProvider>) -> String {
991 let gen = provider.sql_generator();
992 let mut resolved = state.clone();
994 if let Some(ref mut expr) = resolved.where_expr {
995 if has_subqueries(expr) {
996 let meta = T::entity_meta();
997 resolve_subqueries(expr, &meta);
998 }
999 }
1000 resolved.to_sql_with(gen)
1001 }
1002
1003 pub async fn to_list(self) -> EFResult<Vec<T>>
1005 where
1006 T: IFromRow + INavigationSetter + IGetKeyValues + IEntitySnapshot + ILazyInit,
1007 {
1008 let includes = self.state.includes.clone();
1009 let lazy_loading = self.lazy_loading_enabled;
1010 let (sql, params) = self.compile_sql();
1011 let provider = self.provider.as_ref().ok_or_else(|| {
1012 crate::error::EFError::configuration(
1013 "No provider attached to QueryBuilder. Use DbSet::query() or attach a provider."
1014 .to_string(),
1015 )
1016 })?;
1017 let mut conn = provider.get_connection().await?;
1018 let rows = conn.query(&sql, ¶ms).await?;
1019 let mut entities = crate::entity::materialize_entities::<T>(&rows)?;
1020 if !includes.is_empty() {
1021 crate::navigation_loader::load_includes(
1022 &mut entities,
1023 &includes,
1024 &**provider,
1025 self.filter_map.as_deref(),
1026 )
1027 .await?;
1028 }
1029 if lazy_loading && includes.is_empty() {
1034 let provider_arc = Arc::clone(provider);
1035 let filter_map = self.filter_map.clone();
1036 for entity in &mut entities {
1037 entity.attach_lazy_contexts(Arc::clone(&provider_arc), filter_map.clone(), 0);
1038 }
1039 }
1040 Ok(entities)
1041 }
1042
1043 pub async fn to_list_with_includes(self) -> EFResult<Vec<T>>
1045 where
1046 T: IFromRow + INavigationSetter + IGetKeyValues + IEntitySnapshot + ILazyInit,
1047 {
1048 self.to_list().await
1049 }
1050
1051 pub async fn first(self) -> EFResult<T>
1053 where
1054 T: IFromRow + INavigationSetter + IGetKeyValues + IEntitySnapshot + ILazyInit,
1055 {
1056 let mut results = self.take(1).to_list().await?;
1057 results
1058 .pop()
1059 .ok_or_else(|| crate::error::EFError::not_found("Entity not found".to_string()))
1060 }
1061
1062 pub async fn first_or_default(self) -> EFResult<Option<T>>
1064 where
1065 T: IFromRow + INavigationSetter + IGetKeyValues + IEntitySnapshot + ILazyInit,
1066 {
1067 let mut results = self.take(1).to_list().await?;
1068 Ok(results.pop())
1069 }
1070
1071 pub async fn count(self) -> EFResult<i64> {
1073 let mut state = self.state.clone();
1074 state.is_count = true;
1075 let provider = self.provider.as_ref().ok_or_else(|| {
1076 crate::error::EFError::configuration(
1077 "No provider attached to QueryBuilder.".to_string(),
1078 )
1079 })?;
1080 let sql = Self::compile_state_sql(&state, provider);
1081 let params = state.all_params();
1082 let mut conn = provider.get_connection().await?;
1083 let rows = conn.query(&sql, ¶ms).await?;
1084 if let Some(first_row) = rows.first() {
1085 if let Some(first_val) = first_row.first() {
1086 if matches!(first_val, crate::provider::DbValue::Null) {
1087 return Ok(0);
1088 }
1089 return i64::try_from(first_val.clone()).map_err(|e| {
1090 crate::error::EFError::type_conversion(format!(
1091 "COUNT result is not i64: {}",
1092 e
1093 ))
1094 });
1095 }
1096 }
1097 Ok(0)
1098 }
1099
1100 pub async fn any(self) -> EFResult<bool> {
1102 let mut state = self.state.clone();
1103 state.is_exists = true;
1104 state.limit = Some(1);
1105 let provider = self.provider.as_ref().ok_or_else(|| {
1106 crate::error::EFError::configuration(
1107 "No provider attached to QueryBuilder.".to_string(),
1108 )
1109 })?;
1110 let sql = Self::compile_state_sql(&state, provider);
1111 let params = state.all_params();
1112 let mut conn = provider.get_connection().await?;
1113 let rows = conn.query(&sql, ¶ms).await?;
1114 Ok(!rows.is_empty())
1115 }
1116
1117 pub async fn last(self) -> EFResult<T>
1124 where
1125 T: IFromRow + INavigationSetter + IGetKeyValues + IEntitySnapshot + ILazyInit,
1126 {
1127 let mut results = self.last_or_default().await?;
1128 results
1129 .take()
1130 .ok_or_else(|| crate::error::EFError::not_found("Entity not found".to_string()))
1131 }
1132
1133 pub async fn last_or_default(mut self) -> EFResult<Option<T>>
1142 where
1143 T: IFromRow + INavigationSetter + IGetKeyValues + IEntitySnapshot + ILazyInit,
1144 {
1145 if self.state.orderings.is_empty() {
1146 let meta = T::entity_meta();
1147 let pk_col = meta
1148 .primary_keys
1149 .first()
1150 .map(|s| s.as_ref())
1151 .or_else(|| {
1152 meta.properties
1153 .iter()
1154 .find(|p| p.is_primary_key)
1155 .map(|p| p.column_name.as_ref())
1156 })
1157 .ok_or_else(|| {
1158 crate::error::EFError::query(format!(
1159 "last_or_default requires a primary key on {} when no explicit ordering is set",
1160 std::any::type_name::<T>()
1161 ))
1162 })?;
1163 self.state
1164 .orderings
1165 .push(OrderBy::new(pk_col.to_string(), OrderDirection::Descending));
1166 } else {
1167 for o in &mut self.state.orderings {
1169 o.direction = match o.direction {
1170 OrderDirection::Ascending => OrderDirection::Descending,
1171 OrderDirection::Descending => OrderDirection::Ascending,
1172 };
1173 }
1174 }
1175 let mut results = self.take(1).to_list().await?;
1176 Ok(results.pop())
1177 }
1178
1179 pub async fn single(self) -> EFResult<T>
1182 where
1183 T: IFromRow + INavigationSetter + IGetKeyValues + IEntitySnapshot + ILazyInit,
1184 {
1185 let mut results = self.take(2).to_list().await?;
1186 if results.len() > 1 {
1187 return Err(crate::error::EFError::query(
1188 "Sequence contains more than one element".to_string(),
1189 ));
1190 }
1191 results.pop().ok_or_else(|| {
1192 crate::error::EFError::not_found("Sequence contains no elements".to_string())
1193 })
1194 }
1195
1196 pub async fn single_or_default(self) -> EFResult<Option<T>>
1199 where
1200 T: IFromRow + INavigationSetter + IGetKeyValues + IEntitySnapshot + ILazyInit,
1201 {
1202 let mut results = self.take(2).to_list().await?;
1203 if results.len() > 1 {
1204 return Err(crate::error::EFError::query(
1205 "Sequence contains more than one element".to_string(),
1206 ));
1207 }
1208 Ok(results.pop())
1209 }
1210
1211 pub async fn long_count(self) -> EFResult<i64> {
1215 self.count().await
1216 }
1217
1218 pub async fn all<F>(self, predicate: F) -> EFResult<bool>
1221 where
1222 T: IFromRow + INavigationSetter + IGetKeyValues + IEntitySnapshot + ILazyInit,
1223 F: Fn(&T) -> bool,
1224 {
1225 let items = self.to_list().await?;
1226 Ok(items.iter().all(predicate))
1227 }
1228
1229 pub async fn contains(self, id: impl Into<DbValue>) -> EFResult<bool>
1232 where
1233 T: IFromRow + INavigationSetter + IGetKeyValues + IEntitySnapshot + ILazyInit,
1234 {
1235 self.find(id).await.map(|opt| opt.is_some())
1236 }
1237
1238 pub async fn to_dictionary<K, F>(
1242 self,
1243 key_selector: F,
1244 ) -> EFResult<std::collections::HashMap<K, T>>
1245 where
1246 T: IFromRow + INavigationSetter + IGetKeyValues + IEntitySnapshot + ILazyInit,
1247 K: std::hash::Hash + Eq,
1248 F: Fn(&T) -> K,
1249 {
1250 let items = self.to_list().await?;
1251 let mut map = std::collections::HashMap::with_capacity(items.len());
1252 for item in items {
1253 let key = key_selector(&item);
1254 map.insert(key, item);
1255 }
1256 Ok(map)
1257 }
1258
1259 pub fn execute_update(self) -> ExecuteUpdateBuilder<T> {
1265 ExecuteUpdateBuilder {
1266 state: self.state.clone(),
1267 updates: Vec::new(),
1268 provider: self.provider.clone(),
1269 _phantom: PhantomData,
1270 }
1271 }
1272
1273 pub async fn execute_delete(self) -> EFResult<u64> {
1275 let provider = self.provider.as_ref().ok_or_else(|| {
1276 crate::error::EFError::configuration(
1277 "No provider attached to QueryBuilder.".to_string(),
1278 )
1279 })?;
1280 let gen = provider.sql_generator();
1281 let mut resolved_expr = self.state.where_expr.clone();
1283 if let Some(ref mut expr) = resolved_expr {
1284 if has_subqueries(expr) {
1285 let meta = T::entity_meta();
1286 resolve_subqueries(expr, &meta);
1287 }
1288 }
1289 let where_clause = if let Some(ref expr) = resolved_expr {
1290 let mut param_idx = 1usize;
1291 compile_bool_expr(expr, gen, &mut param_idx)
1292 } else {
1293 build_where_clauses(&self.state.filters, gen)
1294 };
1295 let sql = if where_clause.is_empty() {
1296 format!("DELETE FROM {}", self.state.from)
1297 } else {
1298 format!("DELETE FROM {} WHERE {}", self.state.from, where_clause)
1299 };
1300 let params = self.state.all_params();
1301 let mut conn = provider.get_connection().await?;
1302 conn.execute(&sql, ¶ms).await
1303 }
1304}