Skip to main content

reinhardt_db/orm/
query.rs

1//! Unified query interface facade
2//!
3//! This module provides a unified entry point for querying functionality.
4//! By default, it exports the expression-based query API (SQLAlchemy-style).
5
6use super::FieldSelector;
7use crate::backends::types::QueryValue;
8use crate::naming::to_snake_case;
9use crate::orm::query_fields::GroupByFields;
10use crate::orm::query_fields::aggregate::{AggregateExpr, ComparisonExpr};
11use crate::orm::query_fields::comparison::FieldComparison;
12use crate::orm::query_fields::compiler::QueryFieldCompiler;
13use reinhardt_query::prelude::{
14	Alias, BinOper, ColumnRef, Condition, Expr, ExprTrait, Func, JoinType as SeaJoinType,
15	MySqlQueryBuilder, Order, PostgresQueryBuilder, Query, QueryBuilder, QueryStatementBuilder,
16	SelectStatement, SimpleExpr, SqliteQueryBuilder, UpdateStatement,
17};
18use reinhardt_query::types::PgBinOper;
19use reinhardt_query::value::Value;
20use serde::{Deserialize, Serialize};
21use smallvec::SmallVec;
22use std::collections::HashMap;
23use std::time::Instant;
24use uuid::Uuid;
25
26// Django QuerySet API types
27#[derive(Debug, Clone, Serialize, Deserialize)]
28/// Defines possible filter operator values.
29pub enum FilterOperator {
30	/// Eq variant.
31	Eq,
32	/// Case-insensitive exact match.
33	IExact,
34	/// Ne variant.
35	Ne,
36	/// Gt variant.
37	Gt,
38	/// Gte variant.
39	Gte,
40	/// Lt variant.
41	Lt,
42	/// Lte variant.
43	Lte,
44	/// In variant.
45	In,
46	/// NotIn variant.
47	NotIn,
48	/// Contains variant.
49	Contains,
50	/// Case-insensitive contains variant.
51	IContains,
52	/// StartsWith variant.
53	StartsWith,
54	/// Case-insensitive starts-with variant.
55	IStartsWith,
56	/// EndsWith variant.
57	EndsWith,
58	/// Case-insensitive ends-with variant.
59	IEndsWith,
60	/// Regular expression match.
61	Regex,
62	/// Case-insensitive regular expression match.
63	IRegex,
64	/// BETWEEN range lookup.
65	Range,
66	// PostgreSQL array operators
67	/// Array contains all elements (@>)
68	ArrayContains,
69	/// Array is contained by (<@)
70	ArrayContainedBy,
71	/// Arrays overlap (&&) - at least one common element
72	ArrayOverlap,
73	// PostgreSQL full-text search
74	/// Full-text search match (@@)
75	FullTextMatch,
76	// PostgreSQL JSONB operators
77	/// JSONB contains (@>)
78	JsonbContains,
79	/// JSONB is contained by (<@)
80	JsonbContainedBy,
81	/// JSONB key exists (?)
82	JsonbKeyExists,
83	/// JSONB any key exists (?|)
84	JsonbAnyKeyExists,
85	/// JSONB all keys exist (?&)
86	JsonbAllKeysExist,
87	/// JSONB path exists (@?)
88	JsonbPathExists,
89	// Other operators
90	/// Is null check
91	IsNull,
92	/// Is not null check
93	IsNotNull,
94	/// Range contains value (@>)
95	RangeContains,
96	/// Value is within range (<@)
97	RangeContainedBy,
98	/// Range overlaps (&&)
99	RangeOverlaps,
100}
101
102#[derive(Debug, Clone, Serialize, Deserialize)]
103/// Defines possible filter value values.
104pub enum FilterValue {
105	/// String variant.
106	String(String),
107	/// UTC timestamp variant.
108	Timestamp(chrono::DateTime<chrono::Utc>),
109	/// Calendar date variant.
110	Date(chrono::NaiveDate),
111	/// Time-of-day variant.
112	Time(chrono::NaiveTime),
113	/// Timezone-naive timestamp variant.
114	NaiveDateTime(chrono::NaiveDateTime),
115	/// Fixed-precision decimal variant.
116	Decimal(rust_decimal::Decimal),
117	/// UUID variant.
118	Uuid(uuid::Uuid),
119	/// Integer variant.
120	Integer(i64),
121	/// Alias for Integer (for compatibility with test code)
122	Int(i64),
123	/// Float variant.
124	Float(f64),
125	/// Boolean variant.
126	Boolean(bool),
127	/// Alias for Boolean (for compatibility with test code)
128	Bool(bool),
129	/// Null variant.
130	Null,
131	/// Array variant.
132	Array(Vec<String>),
133	/// Typed list variant for IN and NOT IN lookups.
134	List(Vec<FilterValue>),
135	/// Two-value range for BETWEEN lookups.
136	Range(Box<FilterValue>, Box<FilterValue>),
137	/// Field reference for field-to-field comparisons (e.g., WHERE discount_price < total_price)
138	FieldRef(super::expressions::F),
139	/// Arithmetic expression (e.g., WHERE total != unit_price * quantity)
140	Expression(super::annotation::Expression),
141	/// Outer query reference for correlated subqueries (e.g., WHERE books.author_id = OuterRef("authors.id"))
142	OuterRef(super::expressions::OuterRef),
143}
144
145impl FilterValue {
146	/// Return whether this value compiles as an empty `IN` / `NOT IN` collection.
147	fn is_empty_membership_collection(&self) -> bool {
148		match self {
149			Self::List(values) => values.is_empty(),
150			Self::Array(values) => values.is_empty(),
151			Self::String(s) => parse_membership_string(s).is_empty(),
152			_ => false,
153		}
154	}
155}
156
157#[derive(Debug, Clone)]
158enum FilterField {
159	Column,
160	Expression { sql: String, source: Option<String> },
161}
162
163#[derive(Debug, Clone)]
164/// Represents a filter.
165pub struct Filter {
166	/// The field.
167	pub field: String,
168	field_source: FilterField,
169	/// The operator.
170	pub operator: FilterOperator,
171	/// The value.
172	pub value: FilterValue,
173}
174
175impl Filter {
176	/// Creates a new instance.
177	pub fn new(field: impl Into<String>, operator: FilterOperator, value: FilterValue) -> Self {
178		let field = field.into();
179		Self {
180			field,
181			field_source: FilterField::Column,
182			operator,
183			value,
184		}
185	}
186
187	/// Rewrite an expression-backed filter after normalizing its column names.
188	pub fn map_expression_source<F>(&mut self, mapper: F)
189	where
190		F: FnOnce(&str) -> String,
191	{
192		if let FilterField::Expression { sql, .. } = &mut self.field_source {
193			let mapped = mapper(sql);
194			self.field = mapped.clone();
195			*sql = mapped;
196		}
197	}
198
199	/// Returns the model field that produced this filter, when it is known.
200	pub fn source_field_name(&self) -> Option<&str> {
201		match &self.field_source {
202			FilterField::Column => Some(&self.field),
203			FilterField::Expression { source, .. } => source.as_deref(),
204		}
205	}
206
207	/// Returns the SQL expression used on the left side of this filter.
208	pub fn lhs_expr(&self) -> Expr {
209		filter_lhs_expr(self)
210	}
211
212	/// Returns the SQL text used on the left side of this filter.
213	pub fn lhs_sql(&self) -> String {
214		filter_lhs_sql(self)
215	}
216
217	/// Combine this filter with another condition using AND.
218	pub fn and(self, other: impl Into<FilterCondition>) -> FilterCondition {
219		FilterCondition::And(vec![FilterCondition::from(self), other.into()])
220	}
221
222	/// Combine this filter with another condition using OR.
223	pub fn or(self, other: impl Into<FilterCondition>) -> FilterCondition {
224		FilterCondition::Or(vec![FilterCondition::from(self), other.into()])
225	}
226
227	/// Negate this filter.
228	// This method mirrors Django-style query combinators and returns FilterCondition,
229	// so implementing std::ops::Not would not provide the same fluent API.
230	#[allow(clippy::should_implement_trait)]
231	pub fn not(self) -> FilterCondition {
232		FilterCondition::not(self)
233	}
234
235	#[cfg(test)]
236	pub(crate) fn expression(
237		sql: impl Into<String>,
238		operator: FilterOperator,
239		value: FilterValue,
240	) -> Self {
241		Self::expression_with_source(sql, None, operator, value)
242	}
243
244	pub(crate) fn expression_with_source(
245		sql: impl Into<String>,
246		source: Option<String>,
247		operator: FilterOperator,
248		value: FilterValue,
249	) -> Self {
250		let sql = sql.into();
251		Self {
252			field: sql.clone(),
253			field_source: FilterField::Expression { sql, source },
254			operator,
255			value,
256		}
257	}
258
259	/// Return whether this filter compiles to a tautology (`TRUE`).
260	///
261	/// Empty `NOT IN` collections are rewritten as `TRUE` because `x NOT IN ()`
262	/// is invalid SQL and logically matches every row.
263	fn is_always_true(&self) -> bool {
264		matches!(self.operator, FilterOperator::NotIn)
265			&& self.value.is_empty_membership_collection()
266	}
267
268	/// Return whether this filter compiles to a contradiction (`FALSE`).
269	///
270	/// Empty `IN` collections are rewritten as `FALSE` because `x IN ()` is
271	/// invalid SQL and logically matches no rows.
272	fn is_always_false(&self) -> bool {
273		matches!(self.operator, FilterOperator::In) && self.value.is_empty_membership_collection()
274	}
275}
276
277/// Values that can be used in UPDATE statements
278#[derive(Debug, Clone)]
279pub enum UpdateValue {
280	/// String variant.
281	String(String),
282	/// Integer variant.
283	Integer(i64),
284	/// Float variant.
285	Float(f64),
286	/// Boolean variant.
287	Boolean(bool),
288	/// Null variant.
289	Null,
290	/// Timestamp variant.
291	Timestamp(chrono::DateTime<chrono::Utc>),
292	/// UUID variant.
293	Uuid(Uuid),
294	/// Field reference for field-to-field updates (e.g., SET discount_price = total_price)
295	FieldRef(super::expressions::F),
296	/// Arithmetic expression (e.g., SET total = unit_price * quantity)
297	Expression(super::annotation::Expression),
298}
299
300impl From<String> for UpdateValue {
301	fn from(value: String) -> Self {
302		Self::String(value)
303	}
304}
305
306impl From<&str> for UpdateValue {
307	fn from(value: &str) -> Self {
308		Self::String(value.to_string())
309	}
310}
311
312impl From<i64> for UpdateValue {
313	fn from(value: i64) -> Self {
314		Self::Integer(value)
315	}
316}
317
318impl From<i32> for UpdateValue {
319	fn from(value: i32) -> Self {
320		Self::Integer(value as i64)
321	}
322}
323
324impl From<f64> for UpdateValue {
325	fn from(value: f64) -> Self {
326		Self::Float(value)
327	}
328}
329
330impl From<f32> for UpdateValue {
331	fn from(value: f32) -> Self {
332		Self::Float(value as f64)
333	}
334}
335
336impl From<bool> for UpdateValue {
337	fn from(value: bool) -> Self {
338		Self::Boolean(value)
339	}
340}
341
342impl From<chrono::DateTime<chrono::Utc>> for UpdateValue {
343	fn from(value: chrono::DateTime<chrono::Utc>) -> Self {
344		Self::Timestamp(value)
345	}
346}
347
348impl From<Uuid> for UpdateValue {
349	fn from(value: Uuid) -> Self {
350		Self::Uuid(value)
351	}
352}
353
354impl<T> From<Option<T>> for UpdateValue
355where
356	T: Into<UpdateValue>,
357{
358	fn from(value: Option<T>) -> Self {
359		value.map_or(Self::Null, Into::into)
360	}
361}
362
363/// One field assignment for a partial `QuerySet` update.
364#[derive(Debug, Clone)]
365pub struct FieldAssignment {
366	field: String,
367	value: UpdateValue,
368}
369
370impl FieldAssignment {
371	/// Creates a new field assignment.
372	pub fn new(field: impl Into<String>, value: impl Into<UpdateValue>) -> Self {
373		Self {
374			field: field.into(),
375			value: value.into(),
376		}
377	}
378
379	/// Returns the assigned field name.
380	pub fn field(&self) -> &str {
381		&self.field
382	}
383
384	/// Returns the assigned value.
385	pub fn value(&self) -> &UpdateValue {
386		&self.value
387	}
388}
389
390impl<M, T, V> From<(super::expressions::FieldRef<M, T>, V)> for FieldAssignment
391where
392	V: Into<UpdateValue>,
393{
394	fn from((field, value): (super::expressions::FieldRef<M, T>, V)) -> Self {
395		Self::new(field.name(), value)
396	}
397}
398
399impl<V> From<(&str, V)> for FieldAssignment
400where
401	V: Into<UpdateValue>,
402{
403	fn from((field, value): (&str, V)) -> Self {
404		Self::new(field, value)
405	}
406}
407
408impl<V> From<(String, V)> for FieldAssignment
409where
410	V: Into<UpdateValue>,
411{
412	fn from((field, value): (String, V)) -> Self {
413		Self::new(field, value)
414	}
415}
416
417/// Composite filter condition supporting AND/OR logic
418///
419/// This enum allows building complex filter expressions with nested AND/OR conditions.
420/// It's particularly useful for search functionality that needs to match across
421/// multiple fields using OR logic.
422///
423/// # Examples
424///
425/// ```
426/// use reinhardt_db::orm::{Filter, FilterCondition, FilterOperator, FilterValue};
427///
428/// // Simple single filter
429/// let single = FilterCondition::Single(Filter::new(
430///     "name".to_string(),
431///     FilterOperator::Eq,
432///     FilterValue::String("Alice".to_string()),
433/// ));
434///
435/// // OR condition across multiple fields (useful for search)
436/// let search = FilterCondition::Or(vec![
437///     FilterCondition::Single(Filter::new(
438///         "name".to_string(),
439///         FilterOperator::Contains,
440///         FilterValue::String("alice".to_string()),
441///     )),
442///     FilterCondition::Single(Filter::new(
443///         "email".to_string(),
444///         FilterOperator::Contains,
445///         FilterValue::String("alice".to_string()),
446///     )),
447/// ]);
448///
449/// // Complex nested condition: (status = 'active') AND (name LIKE '%alice%' OR email LIKE '%alice%')
450/// let complex = Filter::new(
451///     "status".to_string(),
452///     FilterOperator::Eq,
453///     FilterValue::String("active".to_string()),
454/// ).and(search);
455/// ```
456#[derive(Debug, Clone)]
457pub enum FilterCondition {
458	/// A single filter expression
459	Single(Filter),
460	/// All conditions must match (AND logic)
461	And(Vec<FilterCondition>),
462	/// Any condition must match (OR logic)
463	Or(Vec<FilterCondition>),
464	/// Negates the inner condition (NOT logic)
465	Not(Box<FilterCondition>),
466}
467
468impl FilterCondition {
469	/// Create a single filter condition
470	pub fn single(filter: Filter) -> Self {
471		Self::Single(filter)
472	}
473
474	/// Create an AND condition from multiple conditions
475	pub fn and(conditions: Vec<FilterCondition>) -> Self {
476		Self::And(conditions)
477	}
478
479	/// Create an OR condition from multiple conditions
480	pub fn or(conditions: Vec<FilterCondition>) -> Self {
481		Self::Or(conditions)
482	}
483
484	/// Create a NOT condition that negates the given condition
485	///
486	/// # Examples
487	///
488	/// ```
489	/// use reinhardt_db::orm::{Filter, FilterCondition, FilterOperator, FilterValue};
490	///
491	/// let condition = Filter::new(
492	///     "is_active".to_string(),
493	///     FilterOperator::Eq,
494	///     FilterValue::Boolean(true),
495	/// ).not();
496	/// ```
497	// This method is intentionally named `not` for API consistency with Django's Q object.
498	// It does not implement std::ops::Not because it constructs a FilterCondition variant,
499	// not a boolean negation.
500	#[allow(clippy::should_implement_trait)]
501	pub fn not(condition: impl Into<FilterCondition>) -> Self {
502		Self::Not(Box::new(condition.into()))
503	}
504
505	/// Create an AND condition from multiple conditions.
506	pub fn all(conditions: Vec<FilterCondition>) -> Self {
507		Self::and(conditions)
508	}
509
510	/// Create an OR condition from multiple conditions.
511	pub fn any(conditions: Vec<FilterCondition>) -> Self {
512		Self::or(conditions)
513	}
514
515	/// Create a NOT condition that negates the given condition.
516	pub fn negate(condition: impl Into<FilterCondition>) -> Self {
517		Self::not(condition)
518	}
519
520	/// Create an OR condition from multiple filters (convenience method for search)
521	///
522	/// This is particularly useful for implementing search across multiple fields.
523	///
524	/// # Examples
525	///
526	/// ```
527	/// use reinhardt_db::orm::{Filter, FilterCondition, FilterOperator, FilterValue};
528	///
529	/// let search_filters = vec![
530	///     Filter::new("name".to_string(), FilterOperator::Contains, FilterValue::String("test".to_string())),
531	///     Filter::new("email".to_string(), FilterOperator::Contains, FilterValue::String("test".to_string())),
532	/// ];
533	/// let or_condition = FilterCondition::or_filters(search_filters);
534	/// ```
535	pub fn or_filters(filters: Vec<Filter>) -> Self {
536		Self::Or(filters.into_iter().map(FilterCondition::Single).collect())
537	}
538
539	/// Create an AND condition from multiple filters
540	pub fn and_filters(filters: Vec<Filter>) -> Self {
541		Self::And(filters.into_iter().map(FilterCondition::Single).collect())
542	}
543
544	/// Check if this condition is empty (no actual filters)
545	pub fn is_empty(&self) -> bool {
546		match self {
547			FilterCondition::Single(_) => false,
548			FilterCondition::And(conditions) | FilterCondition::Or(conditions) => {
549				conditions.is_empty() || conditions.iter().all(|c| c.is_empty())
550			}
551			FilterCondition::Not(condition) => condition.is_empty(),
552		}
553	}
554
555	/// Return whether this condition is a tautology (matches every row).
556	///
557	/// Empty `AND` is vacuously true. Empty `OR` is false. `NOT` of a contradiction
558	/// is a tautology. Empty `NOT IN` collections compile to `TRUE` and are treated
559	/// as tautologies, including when wrapped in [`FilterCondition::Single`].
560	fn is_always_true(&self) -> bool {
561		match self {
562			FilterCondition::Single(filter) => filter.is_always_true(),
563			FilterCondition::And(conditions) => conditions.iter().all(Self::is_always_true),
564			FilterCondition::Or(conditions) => {
565				!conditions.is_empty() && conditions.iter().any(Self::is_always_true)
566			}
567			FilterCondition::Not(condition) => condition.is_always_false(),
568		}
569	}
570
571	/// Return whether this condition is a contradiction (matches no rows).
572	fn is_always_false(&self) -> bool {
573		match self {
574			FilterCondition::Single(filter) => filter.is_always_false(),
575			FilterCondition::And(conditions) => {
576				!conditions.is_empty() && conditions.iter().any(Self::is_always_false)
577			}
578			FilterCondition::Or(conditions) => conditions.iter().all(Self::is_always_false),
579			FilterCondition::Not(condition) => condition.is_always_true(),
580		}
581	}
582}
583
584fn map_filter_condition_columns<F>(condition: &mut FilterCondition, mapper: &mut F)
585where
586	F: FnMut(&mut Filter),
587{
588	match condition {
589		FilterCondition::Single(filter) => mapper(filter),
590		FilterCondition::And(conditions) | FilterCondition::Or(conditions) => {
591			for condition in conditions {
592				map_filter_condition_columns(condition, mapper);
593			}
594		}
595		FilterCondition::Not(condition) => map_filter_condition_columns(condition, mapper),
596	}
597}
598
599impl From<Filter> for FilterCondition {
600	fn from(filter: Filter) -> Self {
601		Self::Single(filter)
602	}
603}
604
605/// Parse a membership-list string into query values.
606///
607/// Supports JSON arrays and comma-separated values. An empty result compiles to
608/// `FALSE` for `IN` and `TRUE` for `NOT IN`.
609pub(crate) fn parse_membership_string(s: &str) -> Vec<reinhardt_query::value::Value> {
610	let trimmed = s.trim();
611
612	// Try parsing as JSON array first
613	if trimmed.starts_with('[')
614		&& trimmed.ends_with(']')
615		&& let Ok(arr) = serde_json::from_str::<Vec<serde_json::Value>>(trimmed)
616	{
617		return arr
618			.iter()
619			.map(|v| match v {
620				serde_json::Value::String(s) => s.clone().into(),
621				serde_json::Value::Number(n) => {
622					if let Some(i) = n.as_i64() {
623						i.into()
624					} else if let Some(f) = n.as_f64() {
625						f.into()
626					} else {
627						n.to_string().into()
628					}
629				}
630				serde_json::Value::Bool(b) => (*b).into(),
631				_ => v.to_string().into(),
632			})
633			.collect();
634	}
635
636	// Fallback to comma-separated parsing
637	let trimmed = trimmed
638		.strip_prefix('(')
639		.and_then(|value| value.strip_suffix(')'))
640		.unwrap_or(trimmed);
641	trimmed
642		.split(',')
643		.map(|s| s.trim())
644		.filter(|s| !s.is_empty())
645		.map(|s| s.to_string().into())
646		.collect()
647}
648
649// From implementations for FilterValue
650impl From<String> for FilterValue {
651	fn from(s: String) -> Self {
652		FilterValue::String(s)
653	}
654}
655
656impl From<&str> for FilterValue {
657	fn from(s: &str) -> Self {
658		FilterValue::String(s.to_string())
659	}
660}
661
662impl From<i64> for FilterValue {
663	fn from(i: i64) -> Self {
664		FilterValue::Integer(i)
665	}
666}
667
668impl From<i32> for FilterValue {
669	fn from(i: i32) -> Self {
670		FilterValue::Integer(i as i64)
671	}
672}
673
674macro_rules! filter_value_signed_integer {
675	($($type:ty),+ $(,)?) => {
676		$(
677			impl From<$type> for FilterValue {
678				fn from(value: $type) -> Self {
679					Self::Integer(i64::from(value))
680				}
681			}
682		)+
683	};
684}
685
686macro_rules! filter_value_unsigned_integer {
687	($($type:ty),+ $(,)?) => {
688		$(
689			impl From<$type> for FilterValue {
690				fn from(value: $type) -> Self {
691					Self::Integer(i64::from(value))
692				}
693			}
694		)+
695	};
696}
697
698filter_value_signed_integer!(i8, i16);
699filter_value_unsigned_integer!(u8, u16, u32);
700
701impl From<u64> for FilterValue {
702	fn from(value: u64) -> Self {
703		value
704			.try_into()
705			.map_or_else(|_| Self::String(value.to_string()), Self::Integer)
706	}
707}
708
709impl From<usize> for FilterValue {
710	fn from(value: usize) -> Self {
711		Self::from(value as u64)
712	}
713}
714
715impl From<isize> for FilterValue {
716	fn from(value: isize) -> Self {
717		Self::Integer(value as i64)
718	}
719}
720
721impl From<i128> for FilterValue {
722	fn from(value: i128) -> Self {
723		value
724			.try_into()
725			.map_or_else(|_| Self::String(value.to_string()), Self::Integer)
726	}
727}
728
729impl From<u128> for FilterValue {
730	fn from(value: u128) -> Self {
731		value
732			.try_into()
733			.map_or_else(|_| Self::String(value.to_string()), Self::Integer)
734	}
735}
736
737impl From<f64> for FilterValue {
738	fn from(f: f64) -> Self {
739		FilterValue::Float(f)
740	}
741}
742
743impl From<bool> for FilterValue {
744	fn from(b: bool) -> Self {
745		FilterValue::Boolean(b)
746	}
747}
748
749impl From<chrono::DateTime<chrono::Utc>> for FilterValue {
750	fn from(value: chrono::DateTime<chrono::Utc>) -> Self {
751		Self::Timestamp(value)
752	}
753}
754
755impl From<uuid::Uuid> for FilterValue {
756	fn from(u: uuid::Uuid) -> Self {
757		Self::Uuid(u)
758	}
759}
760
761#[derive(Debug, Clone)]
762/// Represents a orm query.
763pub struct OrmQuery {
764	filters: Vec<Filter>,
765}
766
767impl OrmQuery {
768	/// Creates a new instance.
769	pub fn new() -> Self {
770		Self {
771			filters: Vec::new(),
772		}
773	}
774
775	/// Performs the filter operation.
776	pub fn filter(mut self, filter: Filter) -> Self {
777		self.filters.push(filter);
778		self
779	}
780}
781
782impl Default for OrmQuery {
783	fn default() -> Self {
784		Self::new()
785	}
786}
787
788/// JOIN clause specification for QuerySet
789#[derive(Clone, Debug)]
790struct JoinClause {
791	/// The type of JOIN (INNER, LEFT, RIGHT, CROSS)
792	join_type: super::sqlalchemy_query::JoinType,
793	/// The name of the table to join
794	target_table: String,
795	/// Optional alias for the target table (for self-joins)
796	target_alias: Option<String>,
797	/// The ON condition as a SQL expression string
798	/// Format: "left_table.left_field = right_table.right_field"
799	/// Can include table aliases for self-joins (e.g., "u1.id < u2.id")
800	on_condition: String,
801}
802
803/// Aggregate function types for HAVING clauses
804#[derive(Clone, Debug)]
805enum AggregateFunc {
806	Avg,
807	Count,
808	Sum,
809	Min,
810	Max,
811}
812
813/// Comparison operators for HAVING clauses
814#[derive(Clone, Debug)]
815pub enum ComparisonOp {
816	/// Eq variant.
817	Eq,
818	/// Ne variant.
819	Ne,
820	/// Gt variant.
821	Gt,
822	/// Gte variant.
823	Gte,
824	/// Lt variant.
825	Lt,
826	/// Lte variant.
827	Lte,
828}
829
830/// Value types for aggregate comparisons in HAVING clauses
831#[derive(Clone, Debug)]
832enum AggregateValue {
833	Int(i64),
834	Float(f64),
835}
836
837/// HAVING clause condition specification
838#[derive(Clone, Debug)]
839enum HavingCondition {
840	/// Compare an aggregate function result with a value
841	/// Example: HAVING AVG(price) > 1500.0
842	AggregateCompare {
843		func: AggregateFunc,
844		field: String,
845		operator: ComparisonOp,
846		value: AggregateValue,
847	},
848}
849
850/// Subquery condition specification for WHERE clause
851#[derive(Clone, Debug)]
852enum SubqueryCondition {
853	/// WHERE field IN (subquery)
854	/// Example: WHERE author_id IN (SELECT id FROM authors WHERE name = 'John')
855	In { field: String, subquery: String },
856	/// WHERE field NOT IN (subquery)
857	NotIn { field: String, subquery: String },
858	/// WHERE EXISTS (subquery)
859	/// Example: WHERE EXISTS (SELECT 1 FROM books WHERE author_id = authors.id)
860	Exists {
861		subquery: String,
862		outer_fields: Vec<String>,
863	},
864	/// WHERE NOT EXISTS (subquery)
865	NotExists {
866		subquery: String,
867		outer_fields: Vec<String>,
868	},
869}
870
871fn rewrite_subquery_field_to_placeholder(sql: &mut String, old_field: &str, placeholder: &str) {
872	let old_identifier = format!("\"{}\"", old_field.replace('"', "\"\""));
873	*sql = sql.replace(&old_identifier, placeholder);
874
875	let old_qualified_identifier = quote_identifier(old_field);
876	*sql = sql.replace(&old_qualified_identifier, placeholder);
877}
878
879fn rewrite_subquery_fields(sql: &str, rewrites: &[(String, String)]) -> String {
880	let mut rewritten = sql.to_owned();
881	let placeholders = rewrites
882		.iter()
883		.enumerate()
884		.map(|(index, _)| format!("\u{1}reinhardt_subquery_field_{index}\u{1}"))
885		.collect::<Vec<_>>();
886
887	for ((old_field, _), placeholder) in rewrites.iter().zip(&placeholders) {
888		rewrite_subquery_field_to_placeholder(&mut rewritten, old_field, placeholder);
889	}
890	for ((_, new_field), placeholder) in rewrites.iter().zip(placeholders) {
891		rewritten = rewritten.replace(&placeholder, &quote_identifier(new_field));
892	}
893
894	rewritten
895}
896
897fn collect_subquery_outer_fields(value: &FilterValue, fields: &mut Vec<String>) {
898	match value {
899		FilterValue::FieldRef(field) if field.field.contains('.') => {
900			fields.push(field.field.clone());
901		}
902		FilterValue::OuterRef(field) => fields.push(field.field.clone()),
903		FilterValue::List(values) => {
904			for value in values {
905				collect_subquery_outer_fields(value, fields);
906			}
907		}
908		FilterValue::Range(start, end) => {
909			collect_subquery_outer_fields(start, fields);
910			collect_subquery_outer_fields(end, fields);
911		}
912		_ => {}
913	}
914}
915
916fn collect_subquery_outer_condition(condition: &FilterCondition, fields: &mut Vec<String>) {
917	match condition {
918		FilterCondition::Single(filter) => collect_subquery_outer_fields(&filter.value, fields),
919		FilterCondition::And(conditions) | FilterCondition::Or(conditions) => {
920			for condition in conditions {
921				collect_subquery_outer_condition(condition, fields);
922			}
923		}
924		FilterCondition::Not(condition) => collect_subquery_outer_condition(condition, fields),
925	}
926}
927
928const MAX_FILTER_CONDITION_DEPTH: usize = 64;
929
930#[derive(Clone)]
931/// Represents a query set.
932pub struct QuerySet<T>
933where
934	T: super::Model,
935{
936	_phantom: std::marker::PhantomData<T>,
937	filters: SmallVec<[Filter; 10]>,
938	filter_conditions: SmallVec<[FilterCondition; 4]>,
939	select_related_fields: Vec<String>,
940	prefetch_related_fields: Vec<String>,
941	order_by_fields: Vec<String>,
942	distinct_enabled: bool,
943	selected_fields: Option<Vec<String>>,
944	deferred_fields: Vec<String>,
945	annotations: Vec<super::annotation::Annotation>,
946	manager: Option<std::sync::Arc<super::manager::Manager<T>>>,
947	limit: Option<usize>,
948	offset: Option<usize>,
949	ctes: super::cte::CTECollection,
950	lateral_joins: super::lateral_join::LateralJoins,
951	joins: Vec<JoinClause>,
952	group_by_fields: Vec<String>,
953	having_conditions: Vec<HavingCondition>,
954	subquery_conditions: Vec<SubqueryCondition>,
955	from_alias: Option<String>,
956	/// Subquery SQL for FROM clause (derived table)
957	/// When set, the FROM clause will use this subquery instead of the model's table
958	from_subquery_sql: Option<String>,
959}
960
961impl<T> QuerySet<T>
962where
963	T: super::Model,
964{
965	/// Creates a new instance.
966	pub fn new() -> Self {
967		Self {
968			_phantom: std::marker::PhantomData,
969			filters: SmallVec::new(),
970			filter_conditions: SmallVec::new(),
971			select_related_fields: Vec::new(),
972			prefetch_related_fields: Vec::new(),
973			order_by_fields: Vec::new(),
974			distinct_enabled: false,
975			selected_fields: None,
976			deferred_fields: Vec::new(),
977			annotations: Vec::new(),
978			manager: None,
979			limit: None,
980			offset: None,
981			ctes: super::cte::CTECollection::new(),
982			lateral_joins: super::lateral_join::LateralJoins::new(),
983			joins: Vec::new(),
984			group_by_fields: Vec::new(),
985			having_conditions: Vec::new(),
986			subquery_conditions: Vec::new(),
987			from_alias: None,
988			from_subquery_sql: None,
989		}
990	}
991
992	/// Sets the manager and returns self for chaining.
993	pub fn with_manager(manager: std::sync::Arc<super::manager::Manager<T>>) -> Self {
994		Self {
995			_phantom: std::marker::PhantomData,
996			filters: SmallVec::new(),
997			filter_conditions: SmallVec::new(),
998			select_related_fields: Vec::new(),
999			prefetch_related_fields: Vec::new(),
1000			order_by_fields: Vec::new(),
1001			distinct_enabled: false,
1002			selected_fields: None,
1003			deferred_fields: Vec::new(),
1004			annotations: Vec::new(),
1005			manager: Some(manager),
1006			limit: None,
1007			offset: None,
1008			ctes: super::cte::CTECollection::new(),
1009			lateral_joins: super::lateral_join::LateralJoins::new(),
1010			joins: Vec::new(),
1011			group_by_fields: Vec::new(),
1012			having_conditions: Vec::new(),
1013			subquery_conditions: Vec::new(),
1014			from_alias: None,
1015			from_subquery_sql: None,
1016		}
1017	}
1018
1019	/// Appends a filter expression to this `QuerySet`.
1020	///
1021	/// Accepts any value convertible into [`FilterCondition`] — typically a
1022	/// [`Filter`] from `FieldRef::eq()` / `.gt()` / ... or a composite condition
1023	/// built with [`Filter::and`], [`Filter::or`], and [`Filter::not`].
1024	pub fn filter(mut self, filter: impl Into<FilterCondition>) -> Self {
1025		match filter.into() {
1026			FilterCondition::Single(filter) => self.filters.push(filter),
1027			condition => self.filter_conditions.push(condition),
1028		}
1029		self
1030	}
1031
1032	/// Returns the filters that have been applied to this `QuerySet`.
1033	///
1034	/// Useful for inspection in tests and for custom managers that need to
1035	/// observe or assert on the active filter chain (Issue #3980).
1036	pub fn filters(&self) -> &[Filter] {
1037		&self.filters
1038	}
1039
1040	/// Returns composite filter conditions applied to this `QuerySet`.
1041	pub fn filter_conditions(&self) -> &[FilterCondition] {
1042		&self.filter_conditions
1043	}
1044
1045	/// Maps the column name of every stored filter, including nested conditions.
1046	///
1047	/// This lets request handlers normalize filters produced by custom managers
1048	/// before adding their own request-scoped predicates.
1049	pub fn map_filter_columns<F>(&mut self, mut mapper: F)
1050	where
1051		F: FnMut(&mut Filter),
1052	{
1053		for filter in &mut self.filters {
1054			mapper(filter);
1055		}
1056		for condition in &mut self.filter_conditions {
1057			map_filter_condition_columns(condition, &mut mapper);
1058		}
1059	}
1060
1061	/// Maps every stored ordering field.
1062	///
1063	/// This lets request handlers normalize ordering produced by custom
1064	/// managers before executing the queryset.
1065	pub fn map_order_by_fields<F>(&mut self, mut mapper: F)
1066	where
1067		F: FnMut(&mut String),
1068	{
1069		for field in &mut self.order_by_fields {
1070			mapper(field);
1071		}
1072	}
1073
1074	/// Maps every field used by an `IN` or `NOT IN` subquery predicate.
1075	///
1076	/// This lets request handlers normalize outer predicate columns produced by
1077	/// custom managers before executing the queryset.
1078	pub fn map_subquery_fields<F>(&mut self, mut mapper: F)
1079	where
1080		F: FnMut(&mut String),
1081	{
1082		for condition in &mut self.subquery_conditions {
1083			match condition {
1084				SubqueryCondition::In { field, .. } | SubqueryCondition::NotIn { field, .. } => {
1085					mapper(field)
1086				}
1087				SubqueryCondition::Exists {
1088					subquery,
1089					outer_fields,
1090				}
1091				| SubqueryCondition::NotExists {
1092					subquery,
1093					outer_fields,
1094				} => {
1095					let mut rewrites = Vec::new();
1096					for field in outer_fields {
1097						let old_field = field.clone();
1098						mapper(field);
1099						if old_field != *field {
1100							rewrites.push((old_field, field.clone()));
1101						}
1102					}
1103					if !rewrites.is_empty() {
1104						*subquery = rewrite_subquery_fields(subquery, &rewrites);
1105					}
1106				}
1107			}
1108		}
1109	}
1110
1111	/// Returns fields used by subquery predicates, including correlated fields.
1112	pub fn subquery_fields(&self) -> impl Iterator<Item = &str> {
1113		self.subquery_conditions
1114			.iter()
1115			.flat_map(|condition| {
1116				let fields: &[String] = match condition {
1117					SubqueryCondition::In { field, .. }
1118					| SubqueryCondition::NotIn { field, .. } => std::slice::from_ref(field),
1119					SubqueryCondition::Exists { outer_fields, .. }
1120					| SubqueryCondition::NotExists { outer_fields, .. } => outer_fields,
1121				};
1122				fields.iter()
1123			})
1124			.map(String::as_str)
1125	}
1126
1127	/// Return annotations retained when a manager queryset is decoded as models.
1128	pub fn annotations(&self) -> &[super::annotation::Annotation] {
1129		&self.annotations
1130	}
1131
1132	/// Return the exposed alias for the root model source.
1133	pub fn root_table_alias(&self) -> &str {
1134		self.from_alias.as_deref().unwrap_or(T::table_name())
1135	}
1136
1137	/// Return whether the queryset contains explicit JOIN clauses.
1138	pub fn has_joins(&self) -> bool {
1139		!self.joins.is_empty()
1140	}
1141
1142	fn has_where_predicates(&self) -> bool {
1143		!(self.filters.is_empty()
1144			&& self.filter_conditions.is_empty()
1145			&& self.subquery_conditions.is_empty())
1146	}
1147
1148	/// Return whether the queryset has a WHERE predicate that can exclude rows.
1149	///
1150	/// Composite filters may still be present while compiling to `TRUE` (empty
1151	/// `AND` is vacuously true; empty `NOT IN` is rewritten as `TRUE`). DELETE
1152	/// and UPDATE must reject that case so a tautology cannot wipe or rewrite
1153	/// the whole table.
1154	fn has_restricting_where_predicates(&self) -> bool {
1155		if !self.subquery_conditions.is_empty() {
1156			return true;
1157		}
1158		self.filters.iter().any(|filter| !filter.is_always_true())
1159			|| self
1160				.filter_conditions
1161				.iter()
1162				.any(|condition| !condition.is_always_true())
1163	}
1164
1165	fn outer_reference_fields(&self) -> Vec<String> {
1166		let mut fields = Vec::new();
1167		for filter in &self.filters {
1168			collect_subquery_outer_fields(&filter.value, &mut fields);
1169		}
1170		for condition in &self.filter_conditions {
1171			collect_subquery_outer_condition(condition, &mut fields);
1172		}
1173		fields.sort_unstable();
1174		fields.dedup();
1175		fields
1176	}
1177
1178	/// Create a QuerySet from a subquery (FROM clause subquery / derived table)
1179	///
1180	/// This method creates a new QuerySet that uses a subquery as its data source
1181	/// instead of a regular table. The subquery becomes a derived table in the FROM clause.
1182	///
1183	/// # Type Parameters
1184	///
1185	/// * `M` - The model type for the subquery
1186	/// * `F` - A closure that builds the subquery
1187	///
1188	/// # Parameters
1189	///
1190	/// * `builder` - A closure that receives a fresh `QuerySet<M>` and returns a configured QuerySet
1191	/// * `alias` - The alias for the derived table (required for FROM subqueries)
1192	///
1193	/// # Examples
1194	///
1195	/// ```
1196	/// # use reinhardt_db::orm::{Model, QuerySet};
1197	/// # use reinhardt_db::orm::annotation::{Annotation, AnnotationValue};
1198	/// # use reinhardt_db::orm::aggregation::Aggregate;
1199	/// # use reinhardt_db::orm::{Filter, FilterOperator, FilterValue};
1200	/// # use reinhardt_db::orm::GroupByFields;
1201	/// # use serde::{Serialize, Deserialize};
1202	/// # #[derive(Clone, Serialize, Deserialize)]
1203	/// # struct Book { id: Option<i64>, author_id: Option<i64> }
1204	/// # #[derive(Clone)]
1205	/// # struct BookFields;
1206	/// # impl reinhardt_db::orm::model::FieldSelector for BookFields {
1207	/// #     fn with_alias(self, _alias: &str) -> Self { self }
1208	/// # }
1209	/// # impl Model for Book {
1210	/// #     type PrimaryKey = i64;
1211	/// #     type Fields = BookFields;
1212	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
1213	/// #     fn table_name() -> &'static str { "books" }
1214	/// #     fn new_fields() -> Self::Fields { BookFields }
1215	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
1216	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
1217	/// # }
1218	/// // Query from a derived table showing author book counts
1219	/// let results = QuerySet::<Book>::from_subquery(
1220	///     |subq: QuerySet<Book>| {
1221	///         subq.values(&["author_id"])
1222	///             .annotate(Annotation::new("book_count", AnnotationValue::Aggregate(Aggregate::count_all())))
1223	///     },
1224	///     "book_stats"
1225	/// )
1226	/// .filter(Filter::new("book_count", FilterOperator::Gt, FilterValue::Int(1)))
1227	/// .to_sql();
1228	/// // Generates: SELECT * FROM (SELECT author_id, COUNT(*) AS book_count FROM books GROUP BY author_id) AS book_stats WHERE book_count > 1
1229	/// ```
1230	pub fn from_subquery<M, F>(builder: F, alias: &str) -> Self
1231	where
1232		M: super::Model + 'static,
1233		F: FnOnce(QuerySet<M>) -> QuerySet<M>,
1234	{
1235		// Create a fresh QuerySet for the subquery model
1236		let subquery_qs = QuerySet::<M>::new();
1237		// Apply the builder to configure the subquery
1238		let configured_subquery = builder(subquery_qs);
1239		// Generate SQL for the subquery (wrapped in parentheses)
1240		let subquery_sql = configured_subquery.as_subquery();
1241
1242		// Create a new QuerySet with the subquery as FROM source
1243		Self {
1244			_phantom: std::marker::PhantomData,
1245			filters: SmallVec::new(),
1246			filter_conditions: SmallVec::new(),
1247			select_related_fields: Vec::new(),
1248			prefetch_related_fields: Vec::new(),
1249			order_by_fields: Vec::new(),
1250			distinct_enabled: false,
1251			selected_fields: None,
1252			deferred_fields: Vec::new(),
1253			annotations: Vec::new(),
1254			manager: None,
1255			limit: None,
1256			offset: None,
1257			ctes: super::cte::CTECollection::new(),
1258			lateral_joins: super::lateral_join::LateralJoins::new(),
1259			joins: Vec::new(),
1260			group_by_fields: Vec::new(),
1261			having_conditions: Vec::new(),
1262			subquery_conditions: Vec::new(),
1263			from_alias: Some(alias.to_string()),
1264			from_subquery_sql: Some(subquery_sql),
1265		}
1266	}
1267
1268	/// Add an INNER JOIN to the query
1269	///
1270	/// Performs an INNER JOIN between the current model (T) and another model (R).
1271	/// Only rows with matching values in both tables are included in the result.
1272	///
1273	/// # Type Parameters
1274	///
1275	/// * `R` - The model type to join with (must implement `Model` trait)
1276	///
1277	/// # Parameters
1278	///
1279	/// * `left_field` - The field name from the left table (current model T)
1280	/// * `right_field` - The field name from the right table (model R)
1281	///
1282	/// # Examples
1283	///
1284	/// ```no_run
1285	/// # use reinhardt_db::orm::Model;
1286	/// # use serde::{Serialize, Deserialize};
1287	/// # #[derive(Clone, Serialize, Deserialize)]
1288	/// # struct User { id: Option<i64> }
1289	/// # #[derive(Clone)]
1290	/// # struct UserFields;
1291	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
1292	/// #     fn with_alias(self, _alias: &str) -> Self { self }
1293	/// # }
1294	/// # impl Model for User {
1295	/// #     type PrimaryKey = i64;
1296	/// #     type Fields = UserFields;
1297	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
1298	/// #     fn table_name() -> &'static str { "users" }
1299	/// #     fn new_fields() -> Self::Fields { UserFields }
1300	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
1301	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
1302	/// # }
1303	/// # #[derive(Clone, Serialize, Deserialize)]
1304	/// # struct Post { id: Option<i64>, user_id: Option<i64> }
1305	/// # #[derive(Clone)]
1306	/// # struct PostFields;
1307	/// # impl reinhardt_db::orm::model::FieldSelector for PostFields {
1308	/// #     fn with_alias(self, _alias: &str) -> Self { self }
1309	/// # }
1310	/// # impl Model for Post {
1311	/// #     type PrimaryKey = i64;
1312	/// #     type Fields = PostFields;
1313	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
1314	/// #     fn table_name() -> &'static str { "posts" }
1315	/// #     fn new_fields() -> Self::Fields { PostFields }
1316	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
1317	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
1318	/// # }
1319	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
1320	/// // Join User and Post on user.id = post.user_id
1321	/// let sql = User::objects()
1322	///     .all()
1323	///     .inner_join::<Post>("id", "user_id")
1324	///     .to_sql();
1325	/// # Ok(())
1326	/// # }
1327	/// ```
1328	pub fn inner_join<R: super::Model>(mut self, left_field: &str, right_field: &str) -> Self {
1329		let condition = format!(
1330			"{}.{} = {}.{}",
1331			T::table_name(),
1332			left_field,
1333			R::table_name(),
1334			right_field
1335		);
1336
1337		self.joins.push(JoinClause {
1338			join_type: super::sqlalchemy_query::JoinType::Inner,
1339			target_table: R::table_name().to_string(),
1340			target_alias: None,
1341			on_condition: condition,
1342		});
1343
1344		self
1345	}
1346
1347	/// Add a LEFT OUTER JOIN to the query
1348	///
1349	/// Performs a LEFT OUTER JOIN between the current model (T) and another model (R).
1350	/// All rows from the left table are included, with matching rows from the right table
1351	/// or NULL values if no match is found.
1352	///
1353	/// # Examples
1354	///
1355	/// ```no_run
1356	/// # use reinhardt_db::orm::Model;
1357	/// # use serde::{Serialize, Deserialize};
1358	/// # #[derive(Clone, Serialize, Deserialize)]
1359	/// # struct User { id: Option<i64> }
1360	/// # #[derive(Clone)]
1361	/// # struct UserFields;
1362	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
1363	/// #     fn with_alias(self, _alias: &str) -> Self { self }
1364	/// # }
1365	/// # impl Model for User {
1366	/// #     type PrimaryKey = i64;
1367	/// #     type Fields = UserFields;
1368	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
1369	/// #     fn table_name() -> &'static str { "users" }
1370	/// #     fn new_fields() -> Self::Fields { UserFields }
1371	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
1372	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
1373	/// # }
1374	/// # #[derive(Clone, Serialize, Deserialize)]
1375	/// # struct Post { id: Option<i64>, user_id: Option<i64> }
1376	/// # #[derive(Clone)]
1377	/// # struct PostFields;
1378	/// # impl reinhardt_db::orm::model::FieldSelector for PostFields {
1379	/// #     fn with_alias(self, _alias: &str) -> Self { self }
1380	/// # }
1381	/// # impl Model for Post {
1382	/// #     type PrimaryKey = i64;
1383	/// #     type Fields = PostFields;
1384	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
1385	/// #     fn table_name() -> &'static str { "posts" }
1386	/// #     fn new_fields() -> Self::Fields { PostFields }
1387	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
1388	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
1389	/// # }
1390	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
1391	/// // Left join User and Post
1392	/// let sql = User::objects()
1393	///     .all()
1394	///     .left_join::<Post>("id", "user_id")
1395	///     .to_sql();
1396	/// # Ok(())
1397	/// # }
1398	/// ```
1399	pub fn left_join<R: super::Model>(mut self, left_field: &str, right_field: &str) -> Self {
1400		let condition = format!(
1401			"{}.{} = {}.{}",
1402			T::table_name(),
1403			left_field,
1404			R::table_name(),
1405			right_field
1406		);
1407
1408		self.joins.push(JoinClause {
1409			join_type: super::sqlalchemy_query::JoinType::Left,
1410			target_table: R::table_name().to_string(),
1411			target_alias: None,
1412			on_condition: condition,
1413		});
1414
1415		self
1416	}
1417
1418	/// Add a RIGHT OUTER JOIN to the query
1419	///
1420	/// Performs a RIGHT OUTER JOIN between the current model (T) and another model (R).
1421	/// All rows from the right table are included, with matching rows from the left table
1422	/// or NULL values if no match is found.
1423	///
1424	/// # Examples
1425	///
1426	/// ```no_run
1427	/// # use reinhardt_db::orm::Model;
1428	/// # use serde::{Serialize, Deserialize};
1429	/// # #[derive(Clone, Serialize, Deserialize)]
1430	/// # struct User { id: Option<i64> }
1431	/// # #[derive(Clone)]
1432	/// # struct UserFields;
1433	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
1434	/// #     fn with_alias(self, _alias: &str) -> Self { self }
1435	/// # }
1436	/// # impl Model for User {
1437	/// #     type PrimaryKey = i64;
1438	/// #     type Fields = UserFields;
1439	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
1440	/// #     fn table_name() -> &'static str { "users" }
1441	/// #     fn new_fields() -> Self::Fields { UserFields }
1442	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
1443	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
1444	/// # }
1445	/// # #[derive(Clone, Serialize, Deserialize)]
1446	/// # struct Post { id: Option<i64>, user_id: Option<i64> }
1447	/// # #[derive(Clone)]
1448	/// # struct PostFields;
1449	/// # impl reinhardt_db::orm::model::FieldSelector for PostFields {
1450	/// #     fn with_alias(self, _alias: &str) -> Self { self }
1451	/// # }
1452	/// # impl Model for Post {
1453	/// #     type PrimaryKey = i64;
1454	/// #     type Fields = PostFields;
1455	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
1456	/// #     fn table_name() -> &'static str { "posts" }
1457	/// #     fn new_fields() -> Self::Fields { PostFields }
1458	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
1459	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
1460	/// # }
1461	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
1462	/// // Right join User and Post
1463	/// let sql = User::objects()
1464	///     .all()
1465	///     .right_join::<Post>("id", "user_id")
1466	///     .to_sql();
1467	/// # Ok(())
1468	/// # }
1469	/// ```
1470	pub fn right_join<R: super::Model>(mut self, left_field: &str, right_field: &str) -> Self {
1471		let condition = format!(
1472			"{}.{} = {}.{}",
1473			T::table_name(),
1474			left_field,
1475			R::table_name(),
1476			right_field
1477		);
1478
1479		self.joins.push(JoinClause {
1480			join_type: super::sqlalchemy_query::JoinType::Right,
1481			target_table: R::table_name().to_string(),
1482			target_alias: None,
1483			on_condition: condition,
1484		});
1485
1486		self
1487	}
1488
1489	/// Add a CROSS JOIN to the query
1490	///
1491	/// Performs a CROSS JOIN between the current model (T) and another model (R).
1492	/// Produces the Cartesian product of both tables (all possible combinations).
1493	/// No ON condition is needed for CROSS JOIN.
1494	///
1495	/// # Examples
1496	///
1497	/// ```no_run
1498	/// # use reinhardt_db::orm::Model;
1499	/// # use serde::{Serialize, Deserialize};
1500	/// # #[derive(Clone, Serialize, Deserialize)]
1501	/// # struct User { id: Option<i64> }
1502	/// # #[derive(Clone)]
1503	/// # struct UserFields;
1504	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
1505	/// #     fn with_alias(self, _alias: &str) -> Self { self }
1506	/// # }
1507	/// # impl Model for User {
1508	/// #     type PrimaryKey = i64;
1509	/// #     type Fields = UserFields;
1510	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
1511	/// #     fn table_name() -> &'static str { "users" }
1512	/// #     fn new_fields() -> Self::Fields { UserFields }
1513	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
1514	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
1515	/// # }
1516	/// # #[derive(Clone, Serialize, Deserialize)]
1517	/// # struct Category { id: Option<i64> }
1518	/// # #[derive(Clone)]
1519	/// # struct CategoryFields;
1520	/// # impl reinhardt_db::orm::model::FieldSelector for CategoryFields {
1521	/// #     fn with_alias(self, _alias: &str) -> Self { self }
1522	/// # }
1523	/// # impl Model for Category {
1524	/// #     type PrimaryKey = i64;
1525	/// #     type Fields = CategoryFields;
1526	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
1527	/// #     fn table_name() -> &'static str { "categories" }
1528	/// #     fn new_fields() -> Self::Fields { CategoryFields }
1529	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
1530	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
1531	/// # }
1532	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
1533	/// // Cross join User and Category
1534	/// let sql = User::objects()
1535	///     .all()
1536	///     .cross_join::<Category>()
1537	///     .to_sql();
1538	/// # Ok(())
1539	/// # }
1540	/// ```
1541	pub fn cross_join<R: super::Model>(mut self) -> Self {
1542		self.joins.push(JoinClause {
1543			join_type: super::sqlalchemy_query::JoinType::Inner, // CROSS JOIN uses Inner with empty condition
1544			target_table: R::table_name().to_string(),
1545			target_alias: None,
1546			on_condition: String::new(), // Empty condition for CROSS JOIN
1547		});
1548
1549		self
1550	}
1551
1552	/// Set an alias for the base table (FROM clause)
1553	///
1554	/// This is useful for self-joins where you need to reference the same table multiple times.
1555	///
1556	/// # Parameters
1557	///
1558	/// * `alias` - The alias name for the base table
1559	///
1560	/// # Examples
1561	///
1562	/// ```
1563	/// # use reinhardt_db::orm::Model;
1564	/// # use reinhardt_db::orm::query_fields::Field;
1565	/// # use reinhardt_db::orm::FieldSelector;
1566	/// # use serde::{Serialize, Deserialize};
1567	/// # #[derive(Clone, Serialize, Deserialize)]
1568	/// # struct User { id: Option<i64> }
1569	/// #
1570	/// # #[derive(Clone)]
1571	/// # struct UserFields {
1572	/// #     pub id: Field<User, i64>,
1573	/// # }
1574	/// # impl UserFields {
1575	/// #     pub fn new() -> Self {
1576	/// #         Self { id: Field::new(vec!["id"]) }
1577	/// #     }
1578	/// # }
1579	/// # impl FieldSelector for UserFields {
1580	/// #     fn with_alias(mut self, alias: &str) -> Self {
1581	/// #         self.id = self.id.with_alias(alias);
1582	/// #         self
1583	/// #     }
1584	/// # }
1585	/// # impl Model for User {
1586	/// #     type PrimaryKey = i64;
1587	/// #     type Fields = UserFields;
1588	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
1589	/// #     fn table_name() -> &'static str { "users" }
1590	/// #     fn new_fields() -> Self::Fields { UserFields::new() }
1591	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
1592	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
1593	/// # }
1594	/// # fn example() -> Result<(), Box<dyn std::error::Error>> {
1595	/// // Self-join: find user pairs
1596	/// let sql = User::objects()
1597	///     .all()
1598	///     .from_as("u1")
1599	///     .inner_join_as::<User, _>("u1", "u2", |left, right| left.id.field_lt(right.id))
1600	///     .to_sql();
1601	/// # Ok(())
1602	/// # }
1603	/// ```
1604	pub fn from_as(mut self, alias: &str) -> Self {
1605		self.from_alias = Some(alias.to_string());
1606		self
1607	}
1608
1609	/// Add an INNER JOIN with custom condition
1610	///
1611	/// Performs an INNER JOIN with a custom ON condition expression.
1612	/// Use this when you need complex join conditions beyond simple equality.
1613	///
1614	/// # Type Parameters
1615	///
1616	/// * `R` - The model type to join with (must implement `Model` trait)
1617	///
1618	/// # Parameters
1619	///
1620	/// * `condition` - Custom SQL condition for the JOIN (e.g., "users.id = posts.user_id AND posts.status = 'published'")
1621	///
1622	/// # Examples
1623	///
1624	/// ```no_run
1625	/// # use reinhardt_db::orm::Model;
1626	/// # use serde::{Serialize, Deserialize};
1627	/// # #[derive(Clone, Serialize, Deserialize)]
1628	/// # struct User { id: Option<i64> }
1629	/// # #[derive(Clone)]
1630	/// # struct UserFields;
1631	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
1632	/// #     fn with_alias(self, _alias: &str) -> Self { self }
1633	/// # }
1634	/// # impl Model for User {
1635	/// #     type PrimaryKey = i64;
1636	/// #     type Fields = UserFields;
1637	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
1638	/// #     fn table_name() -> &'static str { "users" }
1639	/// #     fn new_fields() -> Self::Fields { UserFields }
1640	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
1641	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
1642	/// # }
1643	/// # #[derive(Clone, Serialize, Deserialize)]
1644	/// # struct Post { id: Option<i64>, user_id: Option<i64> }
1645	/// # #[derive(Clone)]
1646	/// # struct PostFields;
1647	/// # impl reinhardt_db::orm::model::FieldSelector for PostFields {
1648	/// #     fn with_alias(self, _alias: &str) -> Self { self }
1649	/// # }
1650	/// # impl Model for Post {
1651	/// #     type PrimaryKey = i64;
1652	/// #     type Fields = PostFields;
1653	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
1654	/// #     fn table_name() -> &'static str { "posts" }
1655	/// #     fn new_fields() -> Self::Fields { PostFields }
1656	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
1657	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
1658	/// # }
1659	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
1660	/// // Join with complex condition
1661	/// let sql = User::objects()
1662	///     .all()
1663	///     .inner_join_on::<Post>("users.id = posts.user_id AND posts.title LIKE 'First%'")
1664	///     .to_sql();
1665	/// # Ok(())
1666	/// # }
1667	/// ```
1668	pub fn inner_join_on<R: super::Model>(mut self, condition: &str) -> Self {
1669		self.joins.push(JoinClause {
1670			join_type: super::sqlalchemy_query::JoinType::Inner,
1671			target_table: R::table_name().to_string(),
1672			target_alias: None,
1673			on_condition: condition.to_string(),
1674		});
1675
1676		self
1677	}
1678
1679	/// Add a LEFT OUTER JOIN with custom condition
1680	///
1681	/// Similar to `inner_join_on()` but performs a LEFT OUTER JOIN.
1682	///
1683	/// # Type Parameters
1684	///
1685	/// * `R` - The model type to join with (must implement `Model` trait)
1686	///
1687	/// # Parameters
1688	///
1689	/// * `condition` - Custom SQL condition for the JOIN
1690	///
1691	/// # Examples
1692	///
1693	/// ```no_run
1694	/// # use reinhardt_db::orm::Model;
1695	/// # use serde::{Serialize, Deserialize};
1696	/// # #[derive(Clone, Serialize, Deserialize)]
1697	/// # struct User { id: Option<i64> }
1698	/// # #[derive(Clone)]
1699	/// # struct UserFields;
1700	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
1701	/// #     fn with_alias(self, _alias: &str) -> Self { self }
1702	/// # }
1703	/// # impl Model for User {
1704	/// #     type PrimaryKey = i64;
1705	/// #     type Fields = UserFields;
1706	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
1707	/// #     fn table_name() -> &'static str { "users" }
1708	/// #     fn new_fields() -> Self::Fields { UserFields }
1709	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
1710	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
1711	/// # }
1712	/// # #[derive(Clone, Serialize, Deserialize)]
1713	/// # struct Post { id: Option<i64>, user_id: Option<i64> }
1714	/// # #[derive(Clone)]
1715	/// # struct PostFields;
1716	/// # impl reinhardt_db::orm::model::FieldSelector for PostFields {
1717	/// #     fn with_alias(self, _alias: &str) -> Self { self }
1718	/// # }
1719	/// # impl Model for Post {
1720	/// #     type PrimaryKey = i64;
1721	/// #     type Fields = PostFields;
1722	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
1723	/// #     fn table_name() -> &'static str { "posts" }
1724	/// #     fn new_fields() -> Self::Fields { PostFields }
1725	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
1726	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
1727	/// # }
1728	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
1729	/// let sql = User::objects()
1730	///     .all()
1731	///     .left_join_on::<Post>("users.id = posts.user_id AND posts.published = true")
1732	///     .to_sql();
1733	/// # Ok(())
1734	/// # }
1735	/// ```
1736	pub fn left_join_on<R: super::Model>(mut self, condition: &str) -> Self {
1737		self.joins.push(JoinClause {
1738			join_type: super::sqlalchemy_query::JoinType::Left,
1739			target_table: R::table_name().to_string(),
1740			target_alias: None,
1741			on_condition: condition.to_string(),
1742		});
1743
1744		self
1745	}
1746
1747	/// Add a RIGHT OUTER JOIN with custom condition
1748	///
1749	/// Similar to `inner_join_on()` but performs a RIGHT OUTER JOIN.
1750	///
1751	/// # Type Parameters
1752	///
1753	/// * `R` - The model type to join with (must implement `Model` trait)
1754	///
1755	/// # Parameters
1756	///
1757	/// * `condition` - Custom SQL condition for the JOIN
1758	///
1759	/// # Examples
1760	///
1761	/// ```no_run
1762	/// # use reinhardt_db::orm::Model;
1763	/// # use serde::{Serialize, Deserialize};
1764	/// # #[derive(Clone, Serialize, Deserialize)]
1765	/// # struct User { id: Option<i64> }
1766	/// # #[derive(Clone)]
1767	/// # struct UserFields;
1768	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
1769	/// #     fn with_alias(self, _alias: &str) -> Self { self }
1770	/// # }
1771	/// # impl Model for User {
1772	/// #     type PrimaryKey = i64;
1773	/// #     type Fields = UserFields;
1774	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
1775	/// #     fn table_name() -> &'static str { "users" }
1776	/// #     fn new_fields() -> Self::Fields { UserFields }
1777	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
1778	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
1779	/// # }
1780	/// # #[derive(Clone, Serialize, Deserialize)]
1781	/// # struct Post { id: Option<i64>, user_id: Option<i64> }
1782	/// # #[derive(Clone)]
1783	/// # struct PostFields;
1784	/// # impl reinhardt_db::orm::model::FieldSelector for PostFields {
1785	/// #     fn with_alias(self, _alias: &str) -> Self { self }
1786	/// # }
1787	/// # impl Model for Post {
1788	/// #     type PrimaryKey = i64;
1789	/// #     type Fields = PostFields;
1790	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
1791	/// #     fn table_name() -> &'static str { "posts" }
1792	/// #     fn new_fields() -> Self::Fields { PostFields }
1793	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
1794	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
1795	/// # }
1796	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
1797	/// let sql = User::objects()
1798	///     .all()
1799	///     .right_join_on::<Post>("users.id = posts.user_id AND users.active = true")
1800	///     .to_sql();
1801	/// # Ok(())
1802	/// # }
1803	/// ```
1804	pub fn right_join_on<R: super::Model>(mut self, condition: &str) -> Self {
1805		self.joins.push(JoinClause {
1806			join_type: super::sqlalchemy_query::JoinType::Right,
1807			target_table: R::table_name().to_string(),
1808			target_alias: None,
1809			on_condition: condition.to_string(),
1810		});
1811
1812		self
1813	}
1814
1815	/// Add an INNER JOIN with table alias
1816	///
1817	/// Performs an INNER JOIN with an alias for the target table.
1818	/// Useful for self-joins or when you need to reference the same table multiple times.
1819	///
1820	/// # Type Parameters
1821	///
1822	/// * `R` - The model type to join with (must implement `Model` trait)
1823	/// * `F` - Closure that builds the JOIN ON condition
1824	///
1825	/// # Parameters
1826	///
1827	/// * `alias` - Alias name for the target table
1828	/// * `condition_fn` - Closure that receives a `JoinOnBuilder` and returns it with the condition set
1829	///
1830	/// # Examples
1831	///
1832	/// ```
1833	/// # use reinhardt_db::orm::Model;
1834	/// # use reinhardt_db::orm::query_fields::Field;
1835	/// # use reinhardt_db::orm::FieldSelector;
1836	/// # use serde::{Serialize, Deserialize};
1837	/// # #[derive(Clone, Serialize, Deserialize)]
1838	/// # struct User { id: Option<i64> }
1839	/// #
1840	/// # #[derive(Clone)]
1841	/// # struct UserFields {
1842	/// #     pub id: Field<User, i64>,
1843	/// # }
1844	/// # impl UserFields {
1845	/// #     pub fn new() -> Self {
1846	/// #         Self { id: Field::new(vec!["id"]) }
1847	/// #     }
1848	/// # }
1849	/// # impl FieldSelector for UserFields {
1850	/// #     fn with_alias(mut self, alias: &str) -> Self {
1851	/// #         self.id = self.id.with_alias(alias);
1852	/// #         self
1853	/// #     }
1854	/// # }
1855	/// # impl Model for User {
1856	/// #     type PrimaryKey = i64;
1857	/// #     type Fields = UserFields;
1858	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
1859	/// #     fn table_name() -> &'static str { "users" }
1860	/// #     fn new_fields() -> Self::Fields { UserFields::new() }
1861	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
1862	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
1863	/// # }
1864	/// # fn example() -> Result<(), Box<dyn std::error::Error>> {
1865	/// // Self-join: find user pairs where user1.id < user2.id
1866	/// let sql = User::objects()
1867	///     .all()
1868	///     .inner_join_as::<User, _>("u1", "u2", |u1, u2| u1.id.field_lt(u2.id))
1869	///     .to_sql();
1870	/// # Ok(())
1871	/// # }
1872	/// ```
1873	/// # Breaking Change
1874	///
1875	/// The signature of this method has been changed from string-based JOIN conditions
1876	/// to type-safe field comparisons.
1877	pub fn inner_join_as<R: super::Model, F>(
1878		mut self,
1879		left_alias: &str,
1880		right_alias: &str,
1881		condition_fn: F,
1882	) -> Self
1883	where
1884		F: FnOnce(T::Fields, R::Fields) -> FieldComparison,
1885	{
1886		// Set base table alias
1887		if self.from_alias.is_none() {
1888			self.from_alias = Some(left_alias.to_string());
1889		}
1890
1891		// Create field selectors and set aliases
1892		let left_fields = T::new_fields().with_alias(left_alias);
1893		let right_fields = R::new_fields().with_alias(right_alias);
1894
1895		// Get comparison expression from closure
1896		let comparison = condition_fn(left_fields, right_fields);
1897
1898		// Convert to SQL
1899		let condition = QueryFieldCompiler::compile_field_comparison(&comparison);
1900
1901		// Add to JoinClause
1902		self.joins.push(JoinClause {
1903			join_type: super::sqlalchemy_query::JoinType::Inner,
1904			target_table: R::table_name().to_string(),
1905			target_alias: Some(right_alias.to_string()),
1906			on_condition: condition,
1907		});
1908
1909		self
1910	}
1911
1912	/// Add a LEFT OUTER JOIN with table alias
1913	///
1914	/// Similar to `inner_join_as()` but performs a LEFT OUTER JOIN.
1915	///
1916	/// # Type Parameters
1917	///
1918	/// * `R` - The model type to join with (must implement `Model` trait)
1919	/// * `F` - Closure that builds the JOIN ON condition
1920	///
1921	/// # Parameters
1922	///
1923	/// * `alias` - Alias name for the target table
1924	/// * `condition_fn` - Closure that receives a `JoinOnBuilder` and returns it with the condition set
1925	///
1926	/// # Examples
1927	///
1928	/// ```
1929	/// # use reinhardt_db::orm::Model;
1930	/// # use reinhardt_db::orm::query_fields::Field;
1931	/// # use reinhardt_db::orm::FieldSelector;
1932	/// # use serde::{Serialize, Deserialize};
1933	/// # #[derive(Clone, Serialize, Deserialize)]
1934	/// # struct User { id: Option<i64> }
1935	/// #
1936	/// # #[derive(Clone)]
1937	/// # struct UserFields {
1938	/// #     pub id: Field<User, i64>,
1939	/// #     pub manager_id: Field<User, i64>,
1940	/// # }
1941	/// # impl UserFields {
1942	/// #     pub fn new() -> Self {
1943	/// #         Self {
1944	/// #             id: Field::new(vec!["id"]),
1945	/// #             manager_id: Field::new(vec!["manager_id"]),
1946	/// #         }
1947	/// #     }
1948	/// # }
1949	/// # impl FieldSelector for UserFields {
1950	/// #     fn with_alias(mut self, alias: &str) -> Self {
1951	/// #         self.id = self.id.with_alias(alias);
1952	/// #         self.manager_id = self.manager_id.with_alias(alias);
1953	/// #         self
1954	/// #     }
1955	/// # }
1956	/// # impl Model for User {
1957	/// #     type PrimaryKey = i64;
1958	/// #     type Fields = UserFields;
1959	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
1960	/// #     fn table_name() -> &'static str { "users" }
1961	/// #     fn new_fields() -> Self::Fields { UserFields::new() }
1962	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
1963	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
1964	/// # }
1965	/// # fn example() -> Result<(), Box<dyn std::error::Error>> {
1966	/// // Self-join with LEFT JOIN: find employees and their managers
1967	/// let sql = User::objects()
1968	///     .all()
1969	///     .left_join_as::<User, _>("u1", "u2", |u1, u2| u2.id.field_eq(u1.manager_id))
1970	///     .to_sql();
1971	/// # Ok(())
1972	/// # }
1973	/// ```
1974	/// # Breaking Change
1975	///
1976	/// This method signature has been changed from string-based JOIN conditions
1977	/// to type-safe field comparisons.
1978	pub fn left_join_as<R: super::Model, F>(
1979		mut self,
1980		left_alias: &str,
1981		right_alias: &str,
1982		condition_fn: F,
1983	) -> Self
1984	where
1985		F: FnOnce(T::Fields, R::Fields) -> FieldComparison,
1986	{
1987		// Set base table alias
1988		if self.from_alias.is_none() {
1989			self.from_alias = Some(left_alias.to_string());
1990		}
1991
1992		// Create field selectors with aliases
1993		let left_fields = T::new_fields().with_alias(left_alias);
1994		let right_fields = R::new_fields().with_alias(right_alias);
1995
1996		// Get comparison from closure
1997		let comparison = condition_fn(left_fields, right_fields);
1998
1999		// Convert to SQL
2000		let condition = QueryFieldCompiler::compile_field_comparison(&comparison);
2001
2002		// Add to JoinClause
2003		self.joins.push(JoinClause {
2004			join_type: super::sqlalchemy_query::JoinType::Left,
2005			target_table: R::table_name().to_string(),
2006			target_alias: Some(right_alias.to_string()),
2007			on_condition: condition,
2008		});
2009
2010		self
2011	}
2012
2013	/// Add a RIGHT OUTER JOIN with table alias
2014	///
2015	/// Similar to `inner_join_as()` but performs a RIGHT OUTER JOIN.
2016	///
2017	/// # Type Parameters
2018	///
2019	/// * `R` - The model type to join with (must implement `Model` trait)
2020	/// * `F` - Closure that builds the JOIN ON condition
2021	///
2022	/// # Parameters
2023	///
2024	/// * `alias` - Alias name for the target table
2025	/// * `condition_fn` - Closure that receives a `JoinOnBuilder` and returns it with the condition set
2026	///
2027	/// # Examples
2028	///
2029	/// ```
2030	/// # use reinhardt_db::orm::Model;
2031	/// # use reinhardt_db::orm::query_fields::Field;
2032	/// # use reinhardt_db::orm::FieldSelector;
2033	/// # use serde::{Serialize, Deserialize};
2034	/// # #[derive(Clone, Serialize, Deserialize)]
2035	/// # struct User { id: Option<i64> }
2036	/// #
2037	/// # #[derive(Clone)]
2038	/// # struct UserFields {
2039	/// #     pub id: Field<User, i64>,
2040	/// #     pub department_id: Field<User, i64>,
2041	/// # }
2042	/// # impl UserFields {
2043	/// #     pub fn new() -> Self {
2044	/// #         Self {
2045	/// #             id: Field::new(vec!["id"]),
2046	/// #             department_id: Field::new(vec!["department_id"]),
2047	/// #         }
2048	/// #     }
2049	/// # }
2050	/// # impl FieldSelector for UserFields {
2051	/// #     fn with_alias(mut self, alias: &str) -> Self {
2052	/// #         self.id = self.id.with_alias(alias);
2053	/// #         self.department_id = self.department_id.with_alias(alias);
2054	/// #         self
2055	/// #     }
2056	/// # }
2057	/// # impl Model for User {
2058	/// #     type PrimaryKey = i64;
2059	/// #     type Fields = UserFields;
2060	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
2061	/// #     fn table_name() -> &'static str { "users" }
2062	/// #     fn new_fields() -> Self::Fields { UserFields::new() }
2063	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
2064	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
2065	/// # }
2066	/// # fn example() -> Result<(), Box<dyn std::error::Error>> {
2067	/// // RIGHT JOIN: find all departments even if no users belong to them
2068	/// let sql = User::objects()
2069	///     .all()
2070	///     .right_join_as::<User, _>("u1", "u2", |u1, u2| u2.id.field_eq(u1.department_id))
2071	///     .to_sql();
2072	/// # Ok(())
2073	/// # }
2074	/// ```
2075	/// # Breaking Change
2076	///
2077	/// This method signature has been changed from string-based JOIN conditions
2078	/// to type-safe field comparisons.
2079	pub fn right_join_as<R: super::Model, F>(
2080		mut self,
2081		left_alias: &str,
2082		right_alias: &str,
2083		condition_fn: F,
2084	) -> Self
2085	where
2086		F: FnOnce(T::Fields, R::Fields) -> FieldComparison,
2087	{
2088		// Set base table alias
2089		if self.from_alias.is_none() {
2090			self.from_alias = Some(left_alias.to_string());
2091		}
2092
2093		// Create field selectors with aliases
2094		let left_fields = T::new_fields().with_alias(left_alias);
2095		let right_fields = R::new_fields().with_alias(right_alias);
2096
2097		// Get comparison from closure
2098		let comparison = condition_fn(left_fields, right_fields);
2099
2100		// Convert to SQL
2101		let condition = QueryFieldCompiler::compile_field_comparison(&comparison);
2102
2103		// Add to JoinClause
2104		self.joins.push(JoinClause {
2105			join_type: super::sqlalchemy_query::JoinType::Right,
2106			target_table: R::table_name().to_string(),
2107			target_alias: Some(right_alias.to_string()),
2108			on_condition: condition,
2109		});
2110
2111		self
2112	}
2113
2114	/// Add GROUP BY clause to the query
2115	///
2116	/// Groups rows that have the same values in specified columns into summary rows.
2117	/// Typically used with aggregate functions (COUNT, MAX, MIN, SUM, AVG).
2118	///
2119	/// # Type Parameters
2120	///
2121	/// * `F` - Closure that builds the GROUP BY field list
2122	///
2123	/// # Parameters
2124	///
2125	/// * `builder_fn` - Closure that receives a `GroupByBuilder` and returns it with fields set
2126	///
2127	/// # Examples
2128	///
2129	/// ```
2130	/// # use reinhardt_db::orm::{Model, query_fields::{Field, GroupByFields}, FieldSelector};
2131	/// # use serde::{Serialize, Deserialize};
2132	/// # #[derive(Clone, Serialize, Deserialize)]
2133	/// # struct Book { id: Option<i64> }
2134	/// #
2135	/// # #[derive(Clone)]
2136	/// # struct BookFields {
2137	/// #     pub author_id: Field<Book, i64>,
2138	/// # }
2139	/// # impl BookFields {
2140	/// #     pub fn new() -> Self {
2141	/// #         Self { author_id: Field::new(vec!["author_id"]) }
2142	/// #     }
2143	/// # }
2144	/// # impl FieldSelector for BookFields {
2145	/// #     fn with_alias(mut self, alias: &str) -> Self {
2146	/// #         self.author_id = self.author_id.with_alias(alias);
2147	/// #         self
2148	/// #     }
2149	/// # }
2150	/// # impl Model for Book {
2151	/// #     type PrimaryKey = i64;
2152	/// #     type Fields = BookFields;
2153	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
2154	/// #     fn table_name() -> &'static str { "books" }
2155	/// #     fn new_fields() -> Self::Fields { BookFields::new() }
2156	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
2157	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
2158	/// # }
2159	/// # #[derive(Clone, Serialize, Deserialize)]
2160	/// # struct Sale { id: Option<i64> }
2161	/// #
2162	/// # #[derive(Clone)]
2163	/// # struct SaleFields {
2164	/// #     pub region: Field<Sale, String>,
2165	/// #     pub product_category: Field<Sale, String>,
2166	/// # }
2167	/// # impl SaleFields {
2168	/// #     pub fn new() -> Self {
2169	/// #         Self {
2170	/// #             region: Field::new(vec!["region"]),
2171	/// #             product_category: Field::new(vec!["product_category"]),
2172	/// #         }
2173	/// #     }
2174	/// # }
2175	/// # impl FieldSelector for SaleFields {
2176	/// #     fn with_alias(mut self, alias: &str) -> Self {
2177	/// #         self.region = self.region.with_alias(alias);
2178	/// #         self.product_category = self.product_category.with_alias(alias);
2179	/// #         self
2180	/// #     }
2181	/// # }
2182	/// # impl Model for Sale {
2183	/// #     type PrimaryKey = i64;
2184	/// #     type Fields = SaleFields;
2185	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
2186	/// #     fn table_name() -> &'static str { "sales" }
2187	/// #     fn new_fields() -> Self::Fields { SaleFields::new() }
2188	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
2189	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
2190	/// # }
2191	/// # fn example() -> Result<(), Box<dyn std::error::Error>> {
2192	/// // Group by single field
2193	/// let sql1 = Book::objects()
2194	///     .all()
2195	///     .group_by(|fields| GroupByFields::new().add(&fields.author_id))
2196	///     .to_sql();
2197	///
2198	/// // Group by multiple fields (chain .add())
2199	/// let sql2 = Sale::objects()
2200	///     .all()
2201	///     .group_by(|fields| GroupByFields::new().add(&fields.region).add(&fields.product_category))
2202	///     .to_sql();
2203	/// # Ok(())
2204	/// # }
2205	/// ```
2206	/// # Breaking Change
2207	///
2208	/// This method signature has been changed from string-based field selection
2209	/// to type-safe field selectors.
2210	pub fn group_by<F>(mut self, selector_fn: F) -> Self
2211	where
2212		F: FnOnce(T::Fields) -> GroupByFields,
2213	{
2214		let fields = T::new_fields();
2215		let group_by_fields = selector_fn(fields);
2216		self.group_by_fields = group_by_fields.build();
2217		self
2218	}
2219
2220	/// Add HAVING clause for AVG aggregate
2221	///
2222	/// Filters grouped rows based on the average value of a field.
2223	///
2224	/// # Type Parameters
2225	///
2226	/// * `F` - Closure that selects the field
2227	///
2228	/// # Parameters
2229	///
2230	/// * `field_fn` - Closure that receives a `HavingFieldSelector` and returns it with the field set
2231	/// * `operator` - Comparison operator (Eq, Ne, Gt, Gte, Lt, Lte)
2232	/// * `value` - Value to compare against
2233	///
2234	/// # Examples
2235	///
2236	/// ```
2237	/// # use reinhardt_db::orm::{Model, query_fields::{Field, GroupByFields}, FieldSelector};
2238	/// # use serde::{Serialize, Deserialize};
2239	/// # #[derive(Clone, Serialize, Deserialize)]
2240	/// # struct Author { id: Option<i64> }
2241	/// #
2242	/// # #[derive(Clone)]
2243	/// # struct AuthorFields {
2244	/// #     pub author_id: Field<Author, i64>,
2245	/// #     pub price: Field<Author, f64>,
2246	/// # }
2247	/// # impl AuthorFields {
2248	/// #     pub fn new() -> Self {
2249	/// #         Self {
2250	/// #             author_id: Field::new(vec!["author_id"]),
2251	/// #             price: Field::new(vec!["price"]),
2252	/// #         }
2253	/// #     }
2254	/// # }
2255	/// # impl FieldSelector for AuthorFields {
2256	/// #     fn with_alias(mut self, alias: &str) -> Self {
2257	/// #         self.author_id = self.author_id.with_alias(alias);
2258	/// #         self.price = self.price.with_alias(alias);
2259	/// #         self
2260	/// #     }
2261	/// # }
2262	/// # impl Model for Author {
2263	/// #     type PrimaryKey = i64;
2264	/// #     type Fields = AuthorFields;
2265	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
2266	/// #     fn table_name() -> &'static str { "authors" }
2267	/// #     fn new_fields() -> Self::Fields { AuthorFields::new() }
2268	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
2269	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
2270	/// # }
2271	/// # fn example() -> Result<(), Box<dyn std::error::Error>> {
2272	/// // Find authors with average book price > 1500
2273	/// let sql = Author::objects()
2274	///     .all()
2275	///     .group_by(|fields| GroupByFields::new().add(&fields.author_id))
2276	///     .having_avg(|fields| &fields.price, |avg| avg.gt(1500.0))
2277	///     .to_sql();
2278	/// # Ok(())
2279	/// # }
2280	/// ```
2281	/// # Breaking Change
2282	///
2283	/// This method signature has been changed to use type-safe field selectors
2284	/// and aggregate expressions.
2285	pub fn having_avg<FS, FE, NT>(mut self, field_selector: FS, expr_fn: FE) -> Self
2286	where
2287		FS: FnOnce(&T::Fields) -> &super::query_fields::Field<T, NT>,
2288		NT: super::query_fields::NumericType,
2289		FE: FnOnce(AggregateExpr) -> ComparisonExpr,
2290	{
2291		let fields = T::new_fields();
2292		let field = field_selector(&fields);
2293		let field_path = field.path().join(".");
2294
2295		let avg_expr = AggregateExpr::avg(&field_path);
2296		let comparison = expr_fn(avg_expr);
2297
2298		// Extract components for HavingCondition
2299		let operator = match comparison.op {
2300			super::query_fields::comparison::ComparisonOperator::Eq => ComparisonOp::Eq,
2301			super::query_fields::comparison::ComparisonOperator::Ne => ComparisonOp::Ne,
2302			super::query_fields::comparison::ComparisonOperator::Gt => ComparisonOp::Gt,
2303			super::query_fields::comparison::ComparisonOperator::Gte => ComparisonOp::Gte,
2304			super::query_fields::comparison::ComparisonOperator::Lt => ComparisonOp::Lt,
2305			super::query_fields::comparison::ComparisonOperator::Lte => ComparisonOp::Lte,
2306		};
2307
2308		let value = match comparison.value {
2309			super::query_fields::aggregate::ComparisonValue::Int(i) => {
2310				AggregateValue::Float(i as f64)
2311			}
2312			super::query_fields::aggregate::ComparisonValue::Float(f) => AggregateValue::Float(f),
2313		};
2314
2315		self.having_conditions
2316			.push(HavingCondition::AggregateCompare {
2317				func: AggregateFunc::Avg,
2318				field: comparison.aggregate.field().to_string(),
2319				operator,
2320				value,
2321			});
2322		self
2323	}
2324
2325	/// Add HAVING clause for COUNT aggregate
2326	///
2327	/// Filters grouped rows based on the count of rows in each group.
2328	///
2329	/// # Type Parameters
2330	///
2331	/// * `F` - Closure that selects the field
2332	///
2333	/// # Parameters
2334	///
2335	/// * `field_fn` - Closure that receives a `HavingFieldSelector` and returns it with the field set
2336	/// * `operator` - Comparison operator (Eq, Ne, Gt, Gte, Lt, Lte)
2337	/// * `value` - Value to compare against
2338	///
2339	/// # Examples
2340	///
2341	/// ```
2342	/// # use reinhardt_db::orm::{Model, query_fields::{Field, GroupByFields}, FieldSelector};
2343	/// # use serde::{Serialize, Deserialize};
2344	/// # #[derive(Clone, Serialize, Deserialize)]
2345	/// # struct Author { id: Option<i64> }
2346	/// #
2347	/// # #[derive(Clone)]
2348	/// # struct AuthorFields {
2349	/// #     pub author_id: Field<Author, i64>,
2350	/// # }
2351	/// # impl AuthorFields {
2352	/// #     pub fn new() -> Self {
2353	/// #         Self { author_id: Field::new(vec!["author_id"]) }
2354	/// #     }
2355	/// # }
2356	/// # impl FieldSelector for AuthorFields {
2357	/// #     fn with_alias(mut self, alias: &str) -> Self {
2358	/// #         self.author_id = self.author_id.with_alias(alias);
2359	/// #         self
2360	/// #     }
2361	/// # }
2362	/// # impl Model for Author {
2363	/// #     type PrimaryKey = i64;
2364	/// #     type Fields = AuthorFields;
2365	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
2366	/// #     fn table_name() -> &'static str { "authors" }
2367	/// #     fn new_fields() -> Self::Fields { AuthorFields::new() }
2368	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
2369	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
2370	/// # }
2371	/// # fn example() -> Result<(), Box<dyn std::error::Error>> {
2372	/// // Find authors with more than 5 books
2373	/// let sql = Author::objects()
2374	///     .all()
2375	///     .group_by(|fields| GroupByFields::new().add(&fields.author_id))
2376	///     .having_count(|count| count.gt(5))
2377	///     .to_sql();
2378	/// # Ok(())
2379	/// # }
2380	/// ```
2381	/// # Breaking Change
2382	///
2383	/// This method signature has been changed to use type-safe aggregate expressions.
2384	pub fn having_count<F>(mut self, expr_fn: F) -> Self
2385	where
2386		F: FnOnce(AggregateExpr) -> ComparisonExpr,
2387	{
2388		let count_expr = AggregateExpr::count("*");
2389		let comparison = expr_fn(count_expr);
2390
2391		// Extract components for HavingCondition
2392		let operator = match comparison.op {
2393			super::query_fields::comparison::ComparisonOperator::Eq => ComparisonOp::Eq,
2394			super::query_fields::comparison::ComparisonOperator::Ne => ComparisonOp::Ne,
2395			super::query_fields::comparison::ComparisonOperator::Gt => ComparisonOp::Gt,
2396			super::query_fields::comparison::ComparisonOperator::Gte => ComparisonOp::Gte,
2397			super::query_fields::comparison::ComparisonOperator::Lt => ComparisonOp::Lt,
2398			super::query_fields::comparison::ComparisonOperator::Lte => ComparisonOp::Lte,
2399		};
2400
2401		let value = match comparison.value {
2402			super::query_fields::aggregate::ComparisonValue::Int(i) => AggregateValue::Int(i),
2403			super::query_fields::aggregate::ComparisonValue::Float(f) => AggregateValue::Float(f),
2404		};
2405
2406		self.having_conditions
2407			.push(HavingCondition::AggregateCompare {
2408				func: AggregateFunc::Count,
2409				field: comparison.aggregate.field().to_string(),
2410				operator,
2411				value,
2412			});
2413		self
2414	}
2415
2416	/// Add HAVING clause for SUM aggregate
2417	///
2418	/// Filters grouped rows based on the sum of values in a field.
2419	///
2420	/// # Type Parameters
2421	///
2422	/// * `F` - Closure that selects the field
2423	///
2424	/// # Parameters
2425	///
2426	/// * `field_fn` - Closure that receives a `HavingFieldSelector` and returns it with the field set
2427	/// * `operator` - Comparison operator (Eq, Ne, Gt, Gte, Lt, Lte)
2428	/// * `value` - Value to compare against
2429	///
2430	/// # Examples
2431	///
2432	/// ```
2433	/// # use reinhardt_db::orm::{Model, query_fields::{Field, GroupByFields}, FieldSelector};
2434	/// # use serde::{Serialize, Deserialize};
2435	/// # #[derive(Clone, Serialize, Deserialize)]
2436	/// # struct Product { id: Option<i64> }
2437	/// #
2438	/// # #[derive(Clone)]
2439	/// # struct ProductFields {
2440	/// #     pub category: Field<Product, String>,
2441	/// #     pub sales_amount: Field<Product, f64>,
2442	/// # }
2443	/// # impl ProductFields {
2444	/// #     pub fn new() -> Self {
2445	/// #         Self {
2446	/// #             category: Field::new(vec!["category"]),
2447	/// #             sales_amount: Field::new(vec!["sales_amount"]),
2448	/// #         }
2449	/// #     }
2450	/// # }
2451	/// # impl FieldSelector for ProductFields {
2452	/// #     fn with_alias(mut self, alias: &str) -> Self {
2453	/// #         self.category = self.category.with_alias(alias);
2454	/// #         self.sales_amount = self.sales_amount.with_alias(alias);
2455	/// #         self
2456	/// #     }
2457	/// # }
2458	/// # impl Model for Product {
2459	/// #     type PrimaryKey = i64;
2460	/// #     type Fields = ProductFields;
2461	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
2462	/// #     fn table_name() -> &'static str { "products" }
2463	/// #     fn new_fields() -> Self::Fields { ProductFields::new() }
2464	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
2465	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
2466	/// # }
2467	/// # fn example() -> Result<(), Box<dyn std::error::Error>> {
2468	/// // Find categories with total sales > 10000
2469	/// let sql = Product::objects()
2470	///     .all()
2471	///     .group_by(|fields| GroupByFields::new().add(&fields.category))
2472	///     .having_sum(|fields| &fields.sales_amount, |sum| sum.gt(10000.0))
2473	///     .to_sql();
2474	/// # Ok(())
2475	/// # }
2476	/// ```
2477	/// # Breaking Change
2478	///
2479	/// This method signature has been changed to use type-safe field selectors.
2480	pub fn having_sum<FS, FE, NT>(mut self, field_selector: FS, expr_fn: FE) -> Self
2481	where
2482		FS: FnOnce(&T::Fields) -> &super::query_fields::Field<T, NT>,
2483		NT: super::query_fields::NumericType,
2484		FE: FnOnce(AggregateExpr) -> ComparisonExpr,
2485	{
2486		let fields = T::new_fields();
2487		let field = field_selector(&fields);
2488		let field_path = field.path().join(".");
2489
2490		let sum_expr = AggregateExpr::sum(&field_path);
2491		let comparison = expr_fn(sum_expr);
2492
2493		let operator = match comparison.op {
2494			super::query_fields::comparison::ComparisonOperator::Eq => ComparisonOp::Eq,
2495			super::query_fields::comparison::ComparisonOperator::Ne => ComparisonOp::Ne,
2496			super::query_fields::comparison::ComparisonOperator::Gt => ComparisonOp::Gt,
2497			super::query_fields::comparison::ComparisonOperator::Gte => ComparisonOp::Gte,
2498			super::query_fields::comparison::ComparisonOperator::Lt => ComparisonOp::Lt,
2499			super::query_fields::comparison::ComparisonOperator::Lte => ComparisonOp::Lte,
2500		};
2501
2502		let value = match comparison.value {
2503			super::query_fields::aggregate::ComparisonValue::Int(i) => AggregateValue::Int(i),
2504			super::query_fields::aggregate::ComparisonValue::Float(f) => AggregateValue::Float(f),
2505		};
2506
2507		self.having_conditions
2508			.push(HavingCondition::AggregateCompare {
2509				func: AggregateFunc::Sum,
2510				field: comparison.aggregate.field().to_string(),
2511				operator,
2512				value,
2513			});
2514		self
2515	}
2516
2517	/// Add HAVING clause for MIN aggregate
2518	///
2519	/// Filters grouped rows based on the minimum value in a field.
2520	///
2521	/// # Breaking Change
2522	///
2523	/// This method signature has been changed to use type-safe field selectors.
2524	///
2525	/// # Type Parameters
2526	///
2527	/// * `FS` - Field selector closure that returns a reference to a numeric field
2528	/// * `FE` - Expression closure that builds the comparison expression
2529	///
2530	/// # Parameters
2531	///
2532	/// * `field_selector` - Closure that selects the field from the model
2533	/// * `expr_fn` - Closure that builds the comparison expression using method chaining
2534	///
2535	/// # Examples
2536	///
2537	/// ```
2538	/// # use reinhardt_db::orm::{Model, query_fields::{Field, GroupByFields}, FieldSelector};
2539	/// # use serde::{Serialize, Deserialize};
2540	/// # #[derive(Clone, Serialize, Deserialize)]
2541	/// # struct Author { id: Option<i64> }
2542	/// #
2543	/// # #[derive(Clone)]
2544	/// # struct AuthorFields {
2545	/// #     pub author_id: Field<Author, i64>,
2546	/// #     pub price: Field<Author, f64>,
2547	/// # }
2548	/// # impl AuthorFields {
2549	/// #     pub fn new() -> Self {
2550	/// #         Self {
2551	/// #             author_id: Field::new(vec!["author_id"]),
2552	/// #             price: Field::new(vec!["price"]),
2553	/// #         }
2554	/// #     }
2555	/// # }
2556	/// # impl FieldSelector for AuthorFields {
2557	/// #     fn with_alias(mut self, alias: &str) -> Self {
2558	/// #         self.author_id = self.author_id.with_alias(alias);
2559	/// #         self.price = self.price.with_alias(alias);
2560	/// #         self
2561	/// #     }
2562	/// # }
2563	/// # impl Model for Author {
2564	/// #     type PrimaryKey = i64;
2565	/// #     type Fields = AuthorFields;
2566	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
2567	/// #     fn table_name() -> &'static str { "authors" }
2568	/// #     fn new_fields() -> Self::Fields { AuthorFields::new() }
2569	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
2570	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
2571	/// # }
2572	/// # fn example() -> Result<(), Box<dyn std::error::Error>> {
2573	/// // Find authors where minimum book price > 1000
2574	/// let sql = Author::objects()
2575	///     .all()
2576	///     .group_by(|fields| GroupByFields::new().add(&fields.author_id))
2577	///     .having_min(|fields| &fields.price, |min| min.gt(1000.0))
2578	///     .to_sql();
2579	/// # Ok(())
2580	/// # }
2581	/// ```
2582	pub fn having_min<FS, FE, NT>(mut self, field_selector: FS, expr_fn: FE) -> Self
2583	where
2584		FS: FnOnce(&T::Fields) -> &super::query_fields::Field<T, NT>,
2585		NT: super::query_fields::NumericType,
2586		FE: FnOnce(AggregateExpr) -> ComparisonExpr,
2587	{
2588		let fields = T::new_fields();
2589		let field = field_selector(&fields);
2590		let field_path = field.path().join(".");
2591
2592		let min_expr = AggregateExpr::min(&field_path);
2593		let comparison = expr_fn(min_expr);
2594
2595		let operator = match comparison.op {
2596			super::query_fields::comparison::ComparisonOperator::Eq => ComparisonOp::Eq,
2597			super::query_fields::comparison::ComparisonOperator::Ne => ComparisonOp::Ne,
2598			super::query_fields::comparison::ComparisonOperator::Gt => ComparisonOp::Gt,
2599			super::query_fields::comparison::ComparisonOperator::Gte => ComparisonOp::Gte,
2600			super::query_fields::comparison::ComparisonOperator::Lt => ComparisonOp::Lt,
2601			super::query_fields::comparison::ComparisonOperator::Lte => ComparisonOp::Lte,
2602		};
2603
2604		let value = match comparison.value {
2605			super::query_fields::aggregate::ComparisonValue::Int(i) => AggregateValue::Int(i),
2606			super::query_fields::aggregate::ComparisonValue::Float(f) => AggregateValue::Float(f),
2607		};
2608
2609		self.having_conditions
2610			.push(HavingCondition::AggregateCompare {
2611				func: AggregateFunc::Min,
2612				field: comparison.aggregate.field().to_string(),
2613				operator,
2614				value,
2615			});
2616		self
2617	}
2618
2619	/// Add HAVING clause for MAX aggregate
2620	///
2621	/// Filters grouped rows based on the maximum value in a field.
2622	///
2623	/// # Breaking Change
2624	///
2625	/// This method signature has been changed to use type-safe field selectors.
2626	///
2627	/// # Type Parameters
2628	///
2629	/// * `FS` - Field selector closure that returns a reference to a numeric field
2630	/// * `FE` - Expression closure that builds the comparison expression
2631	///
2632	/// # Parameters
2633	///
2634	/// * `field_selector` - Closure that selects the field from the model
2635	/// * `expr_fn` - Closure that builds the comparison expression using method chaining
2636	///
2637	/// # Examples
2638	///
2639	/// ```
2640	/// # use reinhardt_db::orm::{Model, query_fields::{Field, GroupByFields}, FieldSelector};
2641	/// # use serde::{Serialize, Deserialize};
2642	/// # #[derive(Clone, Serialize, Deserialize)]
2643	/// # struct Author { id: Option<i64> }
2644	/// #
2645	/// # #[derive(Clone)]
2646	/// # struct AuthorFields {
2647	/// #     pub author_id: Field<Author, i64>,
2648	/// #     pub price: Field<Author, f64>,
2649	/// # }
2650	/// # impl AuthorFields {
2651	/// #     pub fn new() -> Self {
2652	/// #         Self {
2653	/// #             author_id: Field::new(vec!["author_id"]),
2654	/// #             price: Field::new(vec!["price"]),
2655	/// #         }
2656	/// #     }
2657	/// # }
2658	/// # impl FieldSelector for AuthorFields {
2659	/// #     fn with_alias(mut self, alias: &str) -> Self {
2660	/// #         self.author_id = self.author_id.with_alias(alias);
2661	/// #         self.price = self.price.with_alias(alias);
2662	/// #         self
2663	/// #     }
2664	/// # }
2665	/// # impl Model for Author {
2666	/// #     type PrimaryKey = i64;
2667	/// #     type Fields = AuthorFields;
2668	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
2669	/// #     fn table_name() -> &'static str { "authors" }
2670	/// #     fn new_fields() -> Self::Fields { AuthorFields::new() }
2671	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
2672	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
2673	/// # }
2674	/// # fn example() -> Result<(), Box<dyn std::error::Error>> {
2675	/// // Find authors where maximum book price < 5000
2676	/// let sql = Author::objects()
2677	///     .all()
2678	///     .group_by(|fields| GroupByFields::new().add(&fields.author_id))
2679	///     .having_max(|fields| &fields.price, |max| max.lt(5000.0))
2680	///     .to_sql();
2681	/// # Ok(())
2682	/// # }
2683	/// ```
2684	pub fn having_max<FS, FE, NT>(mut self, field_selector: FS, expr_fn: FE) -> Self
2685	where
2686		FS: FnOnce(&T::Fields) -> &super::query_fields::Field<T, NT>,
2687		NT: super::query_fields::NumericType,
2688		FE: FnOnce(AggregateExpr) -> ComparisonExpr,
2689	{
2690		let fields = T::new_fields();
2691		let field = field_selector(&fields);
2692		let field_path = field.path().join(".");
2693
2694		let max_expr = AggregateExpr::max(&field_path);
2695		let comparison = expr_fn(max_expr);
2696
2697		let operator = match comparison.op {
2698			super::query_fields::comparison::ComparisonOperator::Eq => ComparisonOp::Eq,
2699			super::query_fields::comparison::ComparisonOperator::Ne => ComparisonOp::Ne,
2700			super::query_fields::comparison::ComparisonOperator::Gt => ComparisonOp::Gt,
2701			super::query_fields::comparison::ComparisonOperator::Gte => ComparisonOp::Gte,
2702			super::query_fields::comparison::ComparisonOperator::Lt => ComparisonOp::Lt,
2703			super::query_fields::comparison::ComparisonOperator::Lte => ComparisonOp::Lte,
2704		};
2705
2706		let value = match comparison.value {
2707			super::query_fields::aggregate::ComparisonValue::Int(i) => AggregateValue::Int(i),
2708			super::query_fields::aggregate::ComparisonValue::Float(f) => AggregateValue::Float(f),
2709		};
2710
2711		self.having_conditions
2712			.push(HavingCondition::AggregateCompare {
2713				func: AggregateFunc::Max,
2714				field: comparison.aggregate.field().to_string(),
2715				operator,
2716				value,
2717			});
2718		self
2719	}
2720
2721	/// Add WHERE IN (subquery) condition
2722	///
2723	/// Filters rows where the specified field's value is in the result set of a subquery.
2724	///
2725	/// # Type Parameters
2726	///
2727	/// * `R` - The model type used in the subquery (must implement `Model` trait)
2728	/// * `F` - Function that builds the subquery QuerySet
2729	///
2730	/// # Examples
2731	///
2732	/// ```no_run
2733	/// # use reinhardt_db::orm::Model;
2734	/// # use reinhardt_db::orm::{QuerySet, Filter, FilterOperator, FilterValue};
2735	/// # use serde::{Serialize, Deserialize};
2736	/// # #[derive(Clone, Serialize, Deserialize)]
2737	/// # struct Author { id: Option<i64> }
2738	/// # #[derive(Clone)]
2739	/// # struct AuthorFields;
2740	/// # impl reinhardt_db::orm::model::FieldSelector for AuthorFields {
2741	/// #     fn with_alias(self, _alias: &str) -> Self { self }
2742	/// # }
2743	/// # impl Model for Author {
2744	/// #     type PrimaryKey = i64;
2745	/// #     type Fields = AuthorFields;
2746	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
2747	/// #     fn table_name() -> &'static str { "authors" }
2748	/// #     fn new_fields() -> Self::Fields { AuthorFields }
2749	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
2750	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
2751	/// # }
2752	/// # #[derive(Clone, Serialize, Deserialize)]
2753	/// # struct Book { id: Option<i64> }
2754	/// # #[derive(Clone)]
2755	/// # struct BookFields;
2756	/// # impl reinhardt_db::orm::model::FieldSelector for BookFields {
2757	/// #     fn with_alias(self, _alias: &str) -> Self { self }
2758	/// # }
2759	/// # impl Model for Book {
2760	/// #     type PrimaryKey = i64;
2761	/// #     type Fields = BookFields;
2762	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
2763	/// #     fn table_name() -> &'static str { "books" }
2764	/// #     fn new_fields() -> Self::Fields { BookFields }
2765	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
2766	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
2767	/// # }
2768	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
2769	/// // Find authors who have books priced over 1500
2770	/// let authors = Author::objects()
2771	///     .filter_in_subquery("id", |subq: QuerySet<Book>| {
2772	///         subq.filter(Filter::new("price", FilterOperator::Gt, FilterValue::Int(1500)))
2773	///             .values(&["author_id"])
2774	///     })
2775	///     .all()
2776	///     .await?;
2777	/// # Ok(())
2778	/// # }
2779	/// ```
2780	pub fn filter_in_subquery<R: super::Model, F>(mut self, field: &str, subquery_fn: F) -> Self
2781	where
2782		F: FnOnce(QuerySet<R>) -> QuerySet<R>,
2783	{
2784		let subquery_qs = subquery_fn(QuerySet::<R>::new());
2785		let subquery_sql = subquery_qs.as_subquery();
2786
2787		self.subquery_conditions.push(SubqueryCondition::In {
2788			field: field.to_string(),
2789			subquery: subquery_sql,
2790		});
2791
2792		self
2793	}
2794
2795	/// Add WHERE NOT IN (subquery) condition
2796	///
2797	/// Filters rows where the specified field's value is NOT in the result set of a subquery.
2798	///
2799	/// # Examples
2800	///
2801	/// ```no_run
2802	/// # use reinhardt_db::orm::Model;
2803	/// # use reinhardt_db::orm::{QuerySet, Filter, FilterOperator, FilterValue};
2804	/// # use serde::{Serialize, Deserialize};
2805	/// # #[derive(Clone, Serialize, Deserialize)]
2806	/// # struct Author { id: Option<i64> }
2807	/// # #[derive(Clone)]
2808	/// # struct AuthorFields;
2809	/// # impl reinhardt_db::orm::model::FieldSelector for AuthorFields {
2810	/// #     fn with_alias(self, _alias: &str) -> Self { self }
2811	/// # }
2812	/// # impl Model for Author {
2813	/// #     type PrimaryKey = i64;
2814	/// #     type Fields = AuthorFields;
2815	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
2816	/// #     fn table_name() -> &'static str { "authors" }
2817	/// #     fn new_fields() -> Self::Fields { AuthorFields }
2818	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
2819	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
2820	/// # }
2821	/// # #[derive(Clone, Serialize, Deserialize)]
2822	/// # struct Book { id: Option<i64> }
2823	/// # #[derive(Clone)]
2824	/// # struct BookFields;
2825	/// # impl reinhardt_db::orm::model::FieldSelector for BookFields {
2826	/// #     fn with_alias(self, _alias: &str) -> Self { self }
2827	/// # }
2828	/// # impl Model for Book {
2829	/// #     type PrimaryKey = i64;
2830	/// #     type Fields = BookFields;
2831	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
2832	/// #     fn table_name() -> &'static str { "books" }
2833	/// #     fn new_fields() -> Self::Fields { BookFields }
2834	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
2835	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
2836	/// # }
2837	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
2838	/// // Find authors who have NO books priced over 1500
2839	/// let authors = Author::objects()
2840	///     .filter_not_in_subquery("id", |subq: QuerySet<Book>| {
2841	///         subq.filter(Filter::new("price", FilterOperator::Gt, FilterValue::Int(1500)))
2842	///             .values(&["author_id"])
2843	///     })
2844	///     .all()
2845	///     .await?;
2846	/// # Ok(())
2847	/// # }
2848	/// ```
2849	pub fn filter_not_in_subquery<R: super::Model, F>(mut self, field: &str, subquery_fn: F) -> Self
2850	where
2851		F: FnOnce(QuerySet<R>) -> QuerySet<R>,
2852	{
2853		let subquery_qs = subquery_fn(QuerySet::<R>::new());
2854		let subquery_sql = subquery_qs.as_subquery();
2855
2856		self.subquery_conditions.push(SubqueryCondition::NotIn {
2857			field: field.to_string(),
2858			subquery: subquery_sql,
2859		});
2860
2861		self
2862	}
2863
2864	/// Add WHERE EXISTS (subquery) condition
2865	///
2866	/// Filters rows where the subquery returns at least one row.
2867	/// Typically used with correlated subqueries.
2868	///
2869	/// # Examples
2870	///
2871	/// ```no_run
2872	/// # use reinhardt_db::orm::Model;
2873	/// # use reinhardt_db::orm::{QuerySet, Filter, FilterOperator, FilterValue};
2874	/// # use serde::{Serialize, Deserialize};
2875	/// # #[derive(Clone, Serialize, Deserialize)]
2876	/// # struct Author { id: Option<i64> }
2877	/// # #[derive(Clone)]
2878	/// # struct AuthorFields;
2879	/// # impl reinhardt_db::orm::model::FieldSelector for AuthorFields {
2880	/// #     fn with_alias(self, _alias: &str) -> Self { self }
2881	/// # }
2882	/// # impl Model for Author {
2883	/// #     type PrimaryKey = i64;
2884	/// #     type Fields = AuthorFields;
2885	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
2886	/// #     fn table_name() -> &'static str { "authors" }
2887	/// #     fn new_fields() -> Self::Fields { AuthorFields }
2888	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
2889	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
2890	/// # }
2891	/// # #[derive(Clone, Serialize, Deserialize)]
2892	/// # struct Book { id: Option<i64> }
2893	/// # #[derive(Clone)]
2894	/// # struct BookFields;
2895	/// # impl reinhardt_db::orm::model::FieldSelector for BookFields {
2896	/// #     fn with_alias(self, _alias: &str) -> Self { self }
2897	/// # }
2898	/// # impl Model for Book {
2899	/// #     type PrimaryKey = i64;
2900	/// #     type Fields = BookFields;
2901	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
2902	/// #     fn table_name() -> &'static str { "books" }
2903	/// #     fn new_fields() -> Self::Fields { BookFields }
2904	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
2905	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
2906	/// # }
2907	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
2908	/// use reinhardt_db::orm::F;
2909	/// // Find authors who have at least one book
2910	/// let authors = Author::objects()
2911	///     .filter_exists(|subq: QuerySet<Book>| {
2912	///         subq.filter(Filter::new("author_id", FilterOperator::Eq, FilterValue::FieldRef(F::new("authors.id"))))
2913	///     })
2914	///     .all()
2915	///     .await?;
2916	/// # Ok(())
2917	/// # }
2918	/// ```
2919	pub fn filter_exists<R: super::Model, F>(mut self, subquery_fn: F) -> Self
2920	where
2921		F: FnOnce(QuerySet<R>) -> QuerySet<R>,
2922	{
2923		let subquery_qs = subquery_fn(QuerySet::<R>::new());
2924		let outer_fields = subquery_qs.outer_reference_fields();
2925		let subquery_sql = subquery_qs.as_subquery();
2926
2927		self.subquery_conditions.push(SubqueryCondition::Exists {
2928			subquery: subquery_sql,
2929			outer_fields,
2930		});
2931
2932		self
2933	}
2934
2935	/// Add WHERE NOT EXISTS (subquery) condition
2936	///
2937	/// Filters rows where the subquery returns no rows.
2938	/// Typically used with correlated subqueries.
2939	///
2940	/// # Examples
2941	///
2942	/// ```no_run
2943	/// # use reinhardt_db::orm::Model;
2944	/// # use reinhardt_db::orm::{QuerySet, Filter, FilterOperator, FilterValue};
2945	/// # use serde::{Serialize, Deserialize};
2946	/// # #[derive(Clone, Serialize, Deserialize)]
2947	/// # struct Author { id: Option<i64> }
2948	/// # #[derive(Clone)]
2949	/// # struct AuthorFields;
2950	/// # impl reinhardt_db::orm::model::FieldSelector for AuthorFields {
2951	/// #     fn with_alias(self, _alias: &str) -> Self { self }
2952	/// # }
2953	/// # impl Model for Author {
2954	/// #     type PrimaryKey = i64;
2955	/// #     type Fields = AuthorFields;
2956	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
2957	/// #     fn table_name() -> &'static str { "authors" }
2958	/// #     fn new_fields() -> Self::Fields { AuthorFields }
2959	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
2960	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
2961	/// # }
2962	/// # #[derive(Clone, Serialize, Deserialize)]
2963	/// # struct Book { id: Option<i64> }
2964	/// # #[derive(Clone)]
2965	/// # struct BookFields;
2966	/// # impl reinhardt_db::orm::model::FieldSelector for BookFields {
2967	/// #     fn with_alias(self, _alias: &str) -> Self { self }
2968	/// # }
2969	/// # impl Model for Book {
2970	/// #     type PrimaryKey = i64;
2971	/// #     type Fields = BookFields;
2972	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
2973	/// #     fn table_name() -> &'static str { "books" }
2974	/// #     fn new_fields() -> Self::Fields { BookFields }
2975	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
2976	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
2977	/// # }
2978	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
2979	/// use reinhardt_db::orm::F;
2980	/// // Find authors who have NO books
2981	/// let authors = Author::objects()
2982	///     .filter_not_exists(|subq: QuerySet<Book>| {
2983	///         subq.filter(Filter::new("author_id", FilterOperator::Eq, FilterValue::FieldRef(F::new("authors.id"))))
2984	///     })
2985	///     .all()
2986	///     .await?;
2987	/// # Ok(())
2988	/// # }
2989	/// ```
2990	pub fn filter_not_exists<R: super::Model, F>(mut self, subquery_fn: F) -> Self
2991	where
2992		F: FnOnce(QuerySet<R>) -> QuerySet<R>,
2993	{
2994		let subquery_qs = subquery_fn(QuerySet::<R>::new());
2995		let outer_fields = subquery_qs.outer_reference_fields();
2996		let subquery_sql = subquery_qs.as_subquery();
2997
2998		self.subquery_conditions.push(SubqueryCondition::NotExists {
2999			subquery: subquery_sql,
3000			outer_fields,
3001		});
3002
3003		self
3004	}
3005
3006	/// Add a Common Table Expression (WITH clause) to the query
3007	///
3008	/// CTEs allow you to define named subqueries that can be referenced
3009	/// in the main query. This is useful for complex queries that need
3010	/// to reference the same subquery multiple times or for recursive queries.
3011	///
3012	/// # Examples
3013	///
3014	/// ```no_run
3015	/// # use reinhardt_db::orm::Model;
3016	/// # use reinhardt_db::orm::cte::CTE;
3017	/// # use serde::{Serialize, Deserialize};
3018	/// # #[derive(Clone, Serialize, Deserialize)]
3019	/// # struct Employee { id: Option<i64> }
3020	/// # #[derive(Clone)]
3021	/// # struct EmployeeFields;
3022	/// # impl reinhardt_db::orm::model::FieldSelector for EmployeeFields {
3023	/// #     fn with_alias(self, _alias: &str) -> Self { self }
3024	/// # }
3025	/// # impl Model for Employee {
3026	/// #     type PrimaryKey = i64;
3027	/// #     type Fields = EmployeeFields;
3028	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
3029	/// #     fn table_name() -> &'static str { "employees" }
3030	/// #     fn new_fields() -> Self::Fields { EmployeeFields }
3031	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
3032	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
3033	/// # }
3034	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
3035	/// // Simple CTE
3036	/// let high_earners = CTE::new("high_earners", "SELECT * FROM employees WHERE salary > 100000");
3037	/// let results = Employee::objects()
3038	///     .with_cte(high_earners)
3039	///     .all()
3040	///     .await?;
3041	///
3042	/// // Recursive CTE for hierarchical data
3043	/// let hierarchy = CTE::new(
3044	///     "org_hierarchy",
3045	///     "SELECT id, name, manager_id, 1 as level FROM employees WHERE manager_id IS NULL \
3046	///      UNION ALL \
3047	///      SELECT e.id, e.name, e.manager_id, h.level + 1 \
3048	///      FROM employees e JOIN org_hierarchy h ON e.manager_id = h.id"
3049	/// ).recursive();
3050	///
3051	/// let org = Employee::objects()
3052	///     .with_cte(hierarchy)
3053	///     .all()
3054	///     .await?;
3055	/// # Ok(())
3056	/// # }
3057	/// ```
3058	pub fn with_cte(mut self, cte: super::cte::CTE) -> Self {
3059		self.ctes.add(cte);
3060		self
3061	}
3062
3063	/// Add a LATERAL JOIN to the query
3064	///
3065	/// LATERAL JOINs allow correlated subqueries in the FROM clause,
3066	/// where the subquery can reference columns from preceding tables.
3067	/// This is useful for "top-N per group" queries and similar patterns.
3068	///
3069	/// **Note**: LATERAL JOIN is supported in PostgreSQL 9.3+, MySQL 8.0.14+,
3070	/// but NOT in SQLite.
3071	///
3072	/// # Examples
3073	///
3074	/// ```no_run
3075	/// # use reinhardt_db::orm::Model;
3076	/// # use serde::{Serialize, Deserialize};
3077	/// # #[derive(Clone, Serialize, Deserialize)]
3078	/// # struct Customer { id: Option<i64> }
3079	/// # #[derive(Clone)]
3080	/// # struct CustomerFields;
3081	/// # impl reinhardt_db::orm::model::FieldSelector for CustomerFields {
3082	/// #     fn with_alias(self, _alias: &str) -> Self { self }
3083	/// # }
3084	/// # impl Model for Customer {
3085	/// #     type PrimaryKey = i64;
3086	/// #     type Fields = CustomerFields;
3087	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
3088	/// #     fn table_name() -> &'static str { "customers" }
3089	/// #     fn new_fields() -> Self::Fields { CustomerFields }
3090	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
3091	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
3092	/// # }
3093	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
3094	/// use reinhardt_db::orm::lateral_join::{LateralJoin, LateralJoinPatterns};
3095	///
3096	/// // Get top 3 orders per customer
3097	/// let top_orders = LateralJoinPatterns::top_n_per_group(
3098	///     "recent_orders",
3099	///     "orders",
3100	///     "customer_id",
3101	///     "customers",
3102	///     "created_at DESC",
3103	///     3,
3104	/// );
3105	///
3106	/// let results = Customer::objects()
3107	///     .all()
3108	///     .with_lateral_join(top_orders)
3109	///     .all()
3110	///     .await?;
3111	///
3112	/// // Get latest order per customer
3113	/// let latest = LateralJoinPatterns::latest_per_parent(
3114	///     "latest_order",
3115	///     "orders",
3116	///     "customer_id",
3117	///     "customers",
3118	///     "created_at",
3119	/// );
3120	///
3121	/// let customers_with_orders = Customer::objects()
3122	///     .all()
3123	///     .with_lateral_join(latest)
3124	///     .all()
3125	///     .await?;
3126	/// # Ok(())
3127	/// # }
3128	/// ```
3129	pub fn with_lateral_join(mut self, join: super::lateral_join::LateralJoin) -> Self {
3130		self.lateral_joins.add(join);
3131		self
3132	}
3133
3134	/// Build WHERE condition using reinhardt-query from accumulated filters
3135	fn build_where_condition(&self) -> reinhardt_core::exception::Result<Option<Condition>> {
3136		if !self.has_where_predicates() {
3137			return Ok(None);
3138		}
3139
3140		let mut cond = Condition::all();
3141		let mut added = false;
3142
3143		for filter in &self.filters {
3144			let col = Self::filter_lhs_expr(filter);
3145
3146			let expr = match (&filter.operator, &filter.value) {
3147				// Field-to-field comparisons (must come before generic patterns)
3148				(FilterOperator::Eq, FilterValue::FieldRef(f)) => {
3149					col.eq(Expr::col(Alias::new(&f.field)))
3150				}
3151				(FilterOperator::Ne, FilterValue::FieldRef(f)) => {
3152					col.ne(Expr::col(Alias::new(&f.field)))
3153				}
3154				(FilterOperator::Gt, FilterValue::FieldRef(f)) => {
3155					col.gt(Expr::col(Alias::new(&f.field)))
3156				}
3157				(FilterOperator::Gte, FilterValue::FieldRef(f)) => {
3158					col.gte(Expr::col(Alias::new(&f.field)))
3159				}
3160				(FilterOperator::Lt, FilterValue::FieldRef(f)) => {
3161					col.lt(Expr::col(Alias::new(&f.field)))
3162				}
3163				(FilterOperator::Lte, FilterValue::FieldRef(f)) => {
3164					col.lte(Expr::col(Alias::new(&f.field)))
3165				}
3166				// OuterRef comparisons for correlated subqueries
3167				(FilterOperator::Eq, FilterValue::OuterRef(outer)) => {
3168					// For correlated subqueries, reference outer query field
3169					// e.g., WHERE books.author_id = authors.id (where authors is from outer query)
3170					col.eq(Expr::col(parse_column_reference(&outer.field)))
3171				}
3172				(FilterOperator::Ne, FilterValue::OuterRef(outer)) => {
3173					col.ne(Expr::col(parse_column_reference(&outer.field)))
3174				}
3175				(FilterOperator::Gt, FilterValue::OuterRef(outer)) => {
3176					col.gt(Expr::col(parse_column_reference(&outer.field)))
3177				}
3178				(FilterOperator::Gte, FilterValue::OuterRef(outer)) => {
3179					col.gte(Expr::col(parse_column_reference(&outer.field)))
3180				}
3181				(FilterOperator::Lt, FilterValue::OuterRef(outer)) => {
3182					col.lt(Expr::col(parse_column_reference(&outer.field)))
3183				}
3184				(FilterOperator::Lte, FilterValue::OuterRef(outer)) => {
3185					col.lte(Expr::col(parse_column_reference(&outer.field)))
3186				}
3187				// Expression comparisons (F("a") * F("b") etc.)
3188				(FilterOperator::Eq, FilterValue::Expression(expr)) => {
3189					col.eq(Self::expression_to_query_expr(expr))
3190				}
3191				(FilterOperator::Ne, FilterValue::Expression(expr)) => {
3192					col.ne(Self::expression_to_query_expr(expr))
3193				}
3194				(FilterOperator::Gt, FilterValue::Expression(expr)) => {
3195					col.gt(Self::expression_to_query_expr(expr))
3196				}
3197				(FilterOperator::Gte, FilterValue::Expression(expr)) => {
3198					col.gte(Self::expression_to_query_expr(expr))
3199				}
3200				(FilterOperator::Lt, FilterValue::Expression(expr)) => {
3201					col.lt(Self::expression_to_query_expr(expr))
3202				}
3203				(FilterOperator::Lte, FilterValue::Expression(expr)) => {
3204					col.lte(Self::expression_to_query_expr(expr))
3205				}
3206				// NULL checks
3207				(FilterOperator::Eq, FilterValue::Null) => col.is_null(),
3208				(FilterOperator::Ne, FilterValue::Null) => col.is_not_null(),
3209				(FilterOperator::IExact, FilterValue::String(s)) => {
3210					Self::like_expr(filter, s, LikePattern::Exact, true)
3211				}
3212				(FilterOperator::IExact, v) => col.eq(Self::filter_value_to_sea_value(v)),
3213				// Generic value comparisons (catch-all for other FilterValue types)
3214				(FilterOperator::Eq, v) => col.eq(Self::filter_value_to_sea_value(v)),
3215				(FilterOperator::Ne, v) => col.ne(Self::filter_value_to_sea_value(v)),
3216				(FilterOperator::Gt, v) => col.gt(Self::filter_value_to_sea_value(v)),
3217				(FilterOperator::Gte, v) => col.gte(Self::filter_value_to_sea_value(v)),
3218				(FilterOperator::Lt, v) => col.lt(Self::filter_value_to_sea_value(v)),
3219				(FilterOperator::Lte, v) => col.lte(Self::filter_value_to_sea_value(v)),
3220				(FilterOperator::In, FilterValue::String(s)) => {
3221					let values = parse_membership_string(s);
3222					col.is_in(values)
3223				}
3224				(FilterOperator::In, FilterValue::Array(arr)) => {
3225					col.is_in(arr.iter().map(|s| s.as_str()).collect::<Vec<_>>())
3226				}
3227				(FilterOperator::In, FilterValue::List(values)) => col.is_in(
3228					values
3229						.iter()
3230						.map(Self::filter_value_to_sea_value)
3231						.collect::<Vec<_>>(),
3232				),
3233				(FilterOperator::NotIn, FilterValue::String(s)) => {
3234					let values = parse_membership_string(s);
3235					col.is_not_in(values)
3236				}
3237				(FilterOperator::NotIn, FilterValue::Array(arr)) => {
3238					col.is_not_in(arr.iter().map(|s| s.as_str()).collect::<Vec<_>>())
3239				}
3240				(FilterOperator::NotIn, FilterValue::List(values)) => col.is_not_in(
3241					values
3242						.iter()
3243						.map(Self::filter_value_to_sea_value)
3244						.collect::<Vec<_>>(),
3245				),
3246				(FilterOperator::Contains, FilterValue::String(s)) => {
3247					Self::like_expr(filter, s, LikePattern::Contains, false)
3248				}
3249				(FilterOperator::IContains, FilterValue::String(s)) => {
3250					Self::like_expr(filter, s, LikePattern::Contains, true)
3251				}
3252				(FilterOperator::Contains, FilterValue::Array(arr)) => {
3253					let value = arr.first().map(String::as_str).unwrap_or("");
3254					Self::like_expr(filter, value, LikePattern::Contains, false)
3255				}
3256				(FilterOperator::StartsWith, FilterValue::String(s)) => {
3257					Self::like_expr(filter, s, LikePattern::StartsWith, false)
3258				}
3259				(FilterOperator::IStartsWith, FilterValue::String(s)) => {
3260					Self::like_expr(filter, s, LikePattern::StartsWith, true)
3261				}
3262				(FilterOperator::StartsWith, FilterValue::Array(arr)) => {
3263					let value = arr.first().map(String::as_str).unwrap_or("");
3264					Self::like_expr(filter, value, LikePattern::StartsWith, false)
3265				}
3266				(FilterOperator::EndsWith, FilterValue::String(s)) => {
3267					Self::like_expr(filter, s, LikePattern::EndsWith, false)
3268				}
3269				(FilterOperator::IEndsWith, FilterValue::String(s)) => {
3270					Self::like_expr(filter, s, LikePattern::EndsWith, true)
3271				}
3272				(FilterOperator::EndsWith, FilterValue::Array(arr)) => {
3273					let value = arr.first().map(String::as_str).unwrap_or("");
3274					Self::like_expr(filter, value, LikePattern::EndsWith, false)
3275				}
3276				(FilterOperator::Regex, FilterValue::String(pattern)) => Expr::cust_with_values(
3277					format!("{} ~ ?", Self::filter_lhs_sql(filter)),
3278					[pattern.clone()],
3279				)
3280				.into_simple_expr(),
3281				(FilterOperator::IRegex, FilterValue::String(pattern)) => Expr::cust_with_values(
3282					format!("{} ~* ?", Self::filter_lhs_sql(filter)),
3283					[pattern.clone()],
3284				)
3285				.into_simple_expr(),
3286				(FilterOperator::Range, FilterValue::Range(start, end)) => Expr::cust_with_values(
3287					format!("{} BETWEEN ? AND ?", Self::filter_lhs_sql(filter)),
3288					[
3289						Self::filter_value_to_sea_value(start),
3290						Self::filter_value_to_sea_value(end),
3291					],
3292				)
3293				.into_simple_expr(),
3294				// Handle Integer, Float, Boolean for text operators
3295				(FilterOperator::Contains, FilterValue::Integer(i) | FilterValue::Int(i)) => {
3296					col.like(format!("%{}%", i))
3297				}
3298				(FilterOperator::IContains, FilterValue::Integer(i) | FilterValue::Int(i)) => {
3299					col.binary(BinOper::ILike, SimpleExpr::from(format!("%{}%", i)))
3300				}
3301				(FilterOperator::Contains, FilterValue::Float(f)) => col.like(format!("%{}%", f)),
3302				(FilterOperator::IContains, FilterValue::Float(f)) => {
3303					col.binary(BinOper::ILike, SimpleExpr::from(format!("%{}%", f)))
3304				}
3305				(FilterOperator::Contains, FilterValue::Boolean(b) | FilterValue::Bool(b)) => {
3306					col.like(format!("%{}%", b))
3307				}
3308				(FilterOperator::IContains, FilterValue::Boolean(b) | FilterValue::Bool(b)) => {
3309					col.binary(BinOper::ILike, SimpleExpr::from(format!("%{}%", b)))
3310				}
3311				(FilterOperator::Contains, FilterValue::Null) => col.like("%"),
3312				(FilterOperator::IContains, FilterValue::Null) => {
3313					col.binary(BinOper::ILike, SimpleExpr::from("%"))
3314				}
3315				(FilterOperator::StartsWith, FilterValue::Integer(i) | FilterValue::Int(i)) => {
3316					col.like(format!("{}%", i))
3317				}
3318				(FilterOperator::IStartsWith, FilterValue::Integer(i) | FilterValue::Int(i)) => {
3319					col.binary(BinOper::ILike, SimpleExpr::from(format!("{}%", i)))
3320				}
3321				(FilterOperator::StartsWith, FilterValue::Float(f)) => col.like(format!("{}%", f)),
3322				(FilterOperator::IStartsWith, FilterValue::Float(f)) => {
3323					col.binary(BinOper::ILike, SimpleExpr::from(format!("{}%", f)))
3324				}
3325				(FilterOperator::StartsWith, FilterValue::Boolean(b) | FilterValue::Bool(b)) => {
3326					col.like(format!("{}%", b))
3327				}
3328				(FilterOperator::IStartsWith, FilterValue::Boolean(b) | FilterValue::Bool(b)) => {
3329					col.binary(BinOper::ILike, SimpleExpr::from(format!("{}%", b)))
3330				}
3331				(FilterOperator::StartsWith, FilterValue::Null) => col.like("%"),
3332				(FilterOperator::IStartsWith, FilterValue::Null) => {
3333					col.binary(BinOper::ILike, SimpleExpr::from("%"))
3334				}
3335				(FilterOperator::EndsWith, FilterValue::Integer(i) | FilterValue::Int(i)) => {
3336					col.like(format!("%{}", i))
3337				}
3338				(FilterOperator::IEndsWith, FilterValue::Integer(i) | FilterValue::Int(i)) => {
3339					col.binary(BinOper::ILike, SimpleExpr::from(format!("%{}", i)))
3340				}
3341				(FilterOperator::EndsWith, FilterValue::Float(f)) => col.like(format!("%{}", f)),
3342				(FilterOperator::IEndsWith, FilterValue::Float(f)) => {
3343					col.binary(BinOper::ILike, SimpleExpr::from(format!("%{}", f)))
3344				}
3345				(FilterOperator::EndsWith, FilterValue::Boolean(b) | FilterValue::Bool(b)) => {
3346					col.like(format!("%{}", b))
3347				}
3348				(FilterOperator::IEndsWith, FilterValue::Boolean(b) | FilterValue::Bool(b)) => {
3349					col.binary(BinOper::ILike, SimpleExpr::from(format!("%{}", b)))
3350				}
3351				(FilterOperator::EndsWith, FilterValue::Null) => col.like("%"),
3352				(FilterOperator::IEndsWith, FilterValue::Null) => {
3353					col.binary(BinOper::ILike, SimpleExpr::from("%"))
3354				}
3355				// Handle In/NotIn for non-String types
3356				(FilterOperator::In, FilterValue::Integer(i) | FilterValue::Int(i)) => {
3357					col.is_in(vec![*i])
3358				}
3359				(FilterOperator::In, FilterValue::Float(f)) => col.is_in(vec![*f]),
3360				(FilterOperator::In, FilterValue::Boolean(b) | FilterValue::Bool(b)) => {
3361					col.is_in(vec![*b])
3362				}
3363				(FilterOperator::In, FilterValue::Null) => {
3364					col.is_in(vec![reinhardt_query::value::Value::Int(None)])
3365				}
3366				(FilterOperator::NotIn, FilterValue::Integer(i) | FilterValue::Int(i)) => {
3367					col.is_not_in(vec![*i])
3368				}
3369				(FilterOperator::NotIn, FilterValue::Float(f)) => col.is_not_in(vec![*f]),
3370				(FilterOperator::NotIn, FilterValue::Boolean(b) | FilterValue::Bool(b)) => {
3371					col.is_not_in(vec![*b])
3372				}
3373				(FilterOperator::NotIn, FilterValue::Null) => {
3374					col.is_not_in(vec![reinhardt_query::value::Value::Int(None)])
3375				}
3376				// IsNull/IsNotNull operators
3377				(FilterOperator::IsNull, _) => col.is_null(),
3378				(FilterOperator::IsNotNull, _) => col.is_not_null(),
3379				// PostgreSQL Array operators (using custom SQL)
3380				(FilterOperator::ArrayContains, FilterValue::Array(arr)) => {
3381					// field @> ARRAY[?, ?] - parameterized
3382					let placeholders = arr.iter().map(|_| "?").collect::<Vec<_>>().join(", ");
3383					Expr::cust_with_values(
3384						format!(
3385							"{} @> ARRAY[{}]",
3386							Self::filter_lhs_sql(filter),
3387							placeholders
3388						),
3389						arr.iter().cloned(),
3390					)
3391					.into_simple_expr()
3392				}
3393				(FilterOperator::ArrayContainedBy, FilterValue::Array(arr)) => {
3394					// field <@ ARRAY[?, ?] - parameterized
3395					let placeholders = arr.iter().map(|_| "?").collect::<Vec<_>>().join(", ");
3396					Expr::cust_with_values(
3397						format!(
3398							"{} <@ ARRAY[{}]",
3399							Self::filter_lhs_sql(filter),
3400							placeholders
3401						),
3402						arr.iter().cloned(),
3403					)
3404					.into_simple_expr()
3405				}
3406				(FilterOperator::ArrayOverlap, FilterValue::Array(arr)) => {
3407					// field && ARRAY[?, ?] - parameterized
3408					let placeholders = arr.iter().map(|_| "?").collect::<Vec<_>>().join(", ");
3409					Expr::cust_with_values(
3410						format!(
3411							"{} && ARRAY[{}]",
3412							Self::filter_lhs_sql(filter),
3413							placeholders
3414						),
3415						arr.iter().cloned(),
3416					)
3417					.into_simple_expr()
3418				}
3419				// PostgreSQL Full-text search
3420				(FilterOperator::FullTextMatch, FilterValue::String(query)) => {
3421					// field @@ plainto_tsquery('english', ?) - parameterized
3422					Expr::cust_with_values(
3423						format!(
3424							"{} @@ plainto_tsquery('english', ?)",
3425							Self::filter_lhs_sql(filter)
3426						),
3427						[query.clone()],
3428					)
3429					.into_simple_expr()
3430				}
3431				// PostgreSQL JSONB operators
3432				(FilterOperator::JsonbContains, FilterValue::String(json)) => {
3433					// field @> ?::jsonb - parameterized
3434					Expr::cust_with_values(
3435						format!("{} @> ?::jsonb", Self::filter_lhs_sql(filter)),
3436						[json.clone()],
3437					)
3438					.into_simple_expr()
3439				}
3440				(FilterOperator::JsonbContainedBy, FilterValue::String(json)) => {
3441					// field <@ ?::jsonb - parameterized
3442					Expr::cust_with_values(
3443						format!("{} <@ ?::jsonb", Self::filter_lhs_sql(filter)),
3444						[json.clone()],
3445					)
3446					.into_simple_expr()
3447				}
3448				(FilterOperator::JsonbKeyExists, FilterValue::String(key)) => {
3449					// field ? 'key' - using PgBinOper for safe parameterization
3450					Expr::cust(Self::filter_lhs_sql(filter))
3451						.into_simple_expr()
3452						.binary(
3453							BinOper::PgOperator(PgBinOper::JsonContainsKey),
3454							SimpleExpr::from(key.clone()),
3455						)
3456				}
3457				(FilterOperator::JsonbAnyKeyExists, FilterValue::Array(keys)) => {
3458					// field ?| array[?, ?] - using PgBinOper for safe parameterization
3459					let placeholders = keys.iter().map(|_| "?").collect::<Vec<_>>().join(", ");
3460					let array_expr = Expr::cust_with_values(
3461						format!("array[{}]", placeholders),
3462						keys.iter().cloned(),
3463					)
3464					.into_simple_expr();
3465					Expr::cust(Self::filter_lhs_sql(filter))
3466						.into_simple_expr()
3467						.binary(
3468							BinOper::PgOperator(PgBinOper::JsonContainsAnyKey),
3469							array_expr,
3470						)
3471				}
3472				(FilterOperator::JsonbAllKeysExist, FilterValue::Array(keys)) => {
3473					// field ?& array[?, ?] - using PgBinOper for safe parameterization
3474					let placeholders = keys.iter().map(|_| "?").collect::<Vec<_>>().join(", ");
3475					let array_expr = Expr::cust_with_values(
3476						format!("array[{}]", placeholders),
3477						keys.iter().cloned(),
3478					)
3479					.into_simple_expr();
3480					Expr::cust(Self::filter_lhs_sql(filter))
3481						.into_simple_expr()
3482						.binary(
3483							BinOper::PgOperator(PgBinOper::JsonContainsAllKeys),
3484							array_expr,
3485						)
3486				}
3487				(FilterOperator::JsonbPathExists, FilterValue::String(path)) => {
3488					// field @? ? - parameterized
3489					Expr::cust_with_values(
3490						format!("{} @? ?", Self::filter_lhs_sql(filter)),
3491						[path.clone()],
3492					)
3493					.into_simple_expr()
3494				}
3495				// PostgreSQL Range operators
3496				(FilterOperator::RangeContains, v) => {
3497					// field @> ? - parameterized
3498					Expr::cust_with_values(
3499						format!("{} @> ?", Self::filter_lhs_sql(filter)),
3500						[Self::filter_value_to_sea_value(v)],
3501					)
3502					.into_simple_expr()
3503				}
3504				(FilterOperator::RangeContainedBy, FilterValue::String(range)) => {
3505					// field <@ ? - parameterized
3506					Expr::cust_with_values(
3507						format!("{} <@ ?", Self::filter_lhs_sql(filter)),
3508						[range.clone()],
3509					)
3510					.into_simple_expr()
3511				}
3512				(FilterOperator::RangeOverlaps, FilterValue::String(range)) => {
3513					// field && ? - parameterized
3514					Expr::cust_with_values(
3515						format!("{} && ?", Self::filter_lhs_sql(filter)),
3516						[range.clone()],
3517					)
3518					.into_simple_expr()
3519				}
3520				// Fallback for unsupported combinations
3521				_ => {
3522					// Default to equality for unhandled cases
3523					col.eq(Self::filter_value_to_sea_value(&filter.value))
3524				}
3525			};
3526
3527			cond = cond.add(expr);
3528			added = true;
3529		}
3530
3531		for filter_condition in &self.filter_conditions {
3532			if let Some(expr) = Self::build_filter_condition(filter_condition, 0)? {
3533				cond = cond.add(expr);
3534				added = true;
3535			}
3536		}
3537
3538		// Add subquery conditions
3539		for subq_cond in &self.subquery_conditions {
3540			let expr = match subq_cond {
3541				SubqueryCondition::In { field, subquery } => {
3542					// field IN (subquery)
3543					Expr::cust(format!("{} IN {}", quote_identifier(field), subquery))
3544						.into_simple_expr()
3545				}
3546				SubqueryCondition::NotIn { field, subquery } => {
3547					// field NOT IN (subquery)
3548					Expr::cust(format!("{} NOT IN {}", quote_identifier(field), subquery))
3549						.into_simple_expr()
3550				}
3551				SubqueryCondition::Exists { subquery, .. } => {
3552					// EXISTS (subquery)
3553					Expr::cust(format!("EXISTS {}", subquery)).into_simple_expr()
3554				}
3555				SubqueryCondition::NotExists { subquery, .. } => {
3556					// NOT EXISTS (subquery)
3557					Expr::cust(format!("NOT EXISTS {}", subquery)).into_simple_expr()
3558				}
3559			};
3560
3561			cond = cond.add(expr);
3562			added = true;
3563		}
3564
3565		Ok(added.then_some(cond))
3566	}
3567
3568	fn build_filter_condition(
3569		filter_condition: &FilterCondition,
3570		depth: usize,
3571	) -> reinhardt_core::exception::Result<Option<Condition>> {
3572		if depth >= MAX_FILTER_CONDITION_DEPTH {
3573			return Err(reinhardt_core::exception::Error::Validation(format!(
3574				"Filter condition exceeded maximum depth of {} levels",
3575				MAX_FILTER_CONDITION_DEPTH
3576			)));
3577		}
3578
3579		match filter_condition {
3580			FilterCondition::Single(filter) => {
3581				let mut queryset = Self::new();
3582				queryset.filters.push(filter.clone());
3583				queryset.build_where_condition()
3584			}
3585			FilterCondition::And(conditions) => {
3586				let mut condition = Condition::all();
3587				let mut added = false;
3588				for item in conditions {
3589					if let Some(sub_condition) = Self::build_filter_condition(item, depth + 1)? {
3590						condition = condition.add(sub_condition);
3591						added = true;
3592					}
3593				}
3594				if !added {
3595					condition = condition.add(Expr::cust("TRUE").into_simple_expr());
3596				}
3597				Ok(Some(condition))
3598			}
3599			FilterCondition::Or(conditions) => {
3600				if conditions.is_empty() {
3601					return Ok(Some(Self::false_condition()));
3602				}
3603				let mut condition = Condition::any();
3604				let mut added = false;
3605				for item in conditions {
3606					if let Some(sub_condition) = Self::build_filter_condition(item, depth + 1)? {
3607						condition = condition.add(sub_condition);
3608						added = true;
3609					}
3610				}
3611				Ok(added.then_some(condition))
3612			}
3613			FilterCondition::Not(condition) => {
3614				Ok(Self::build_filter_condition(condition, depth + 1)?
3615					.map(|condition| condition.not()))
3616			}
3617		}
3618	}
3619
3620	fn false_condition() -> Condition {
3621		Condition::all().add(Expr::cust("FALSE").into_simple_expr())
3622	}
3623
3624	fn build_where_condition_or_false(&self) -> Option<Condition> {
3625		match self.build_where_condition() {
3626			Ok(condition) => condition,
3627			Err(_) => Some(Self::false_condition()),
3628		}
3629	}
3630
3631	/// Convert FilterValue to reinhardt_query::value::Value
3632	/// Convert Expression to reinhardt-query Expr for use in WHERE clauses
3633	///
3634	/// Uses Expr::cust() for arithmetic operations as reinhardt-query doesn't provide
3635	/// multiply/divide/etc. methods. SQL injection risk is low since F() only
3636	/// accepts field names.
3637	fn expression_to_query_expr(expr: &super::annotation::Expression) -> Expr {
3638		use crate::orm::annotation::Expression;
3639
3640		match expr {
3641			Expression::Add(left, right) => {
3642				let left_sql = Self::annotation_value_to_sql(left);
3643				let right_sql = Self::annotation_value_to_sql(right);
3644				Expr::cust(format!("({} + {})", left_sql, right_sql))
3645			}
3646			Expression::Subtract(left, right) => {
3647				let left_sql = Self::annotation_value_to_sql(left);
3648				let right_sql = Self::annotation_value_to_sql(right);
3649				Expr::cust(format!("({} - {})", left_sql, right_sql))
3650			}
3651			Expression::Multiply(left, right) => {
3652				let left_sql = Self::annotation_value_to_sql(left);
3653				let right_sql = Self::annotation_value_to_sql(right);
3654				Expr::cust(format!("({} * {})", left_sql, right_sql))
3655			}
3656			Expression::Divide(left, right) => {
3657				let left_sql = Self::annotation_value_to_sql(left);
3658				let right_sql = Self::annotation_value_to_sql(right);
3659				Expr::cust(format!("({} / {})", left_sql, right_sql))
3660			}
3661			Expression::Case { whens, default } => {
3662				let mut case_sql = "CASE".to_string();
3663				for when in whens.iter() {
3664					// Use When::to_sql() which generates "WHEN condition THEN value"
3665					case_sql.push_str(&format!(" {}", when.to_sql()));
3666				}
3667				if let Some(default_val) = default {
3668					case_sql.push_str(&format!(
3669						" ELSE {}",
3670						Self::annotation_value_to_sql(default_val)
3671					));
3672				}
3673				case_sql.push_str(" END");
3674				Expr::cust(case_sql)
3675			}
3676			Expression::Coalesce(values) => {
3677				let value_sqls = values
3678					.iter()
3679					.map(|v| Self::annotation_value_to_sql(v))
3680					.collect::<Vec<_>>()
3681					.join(", ");
3682				Expr::cust(format!("COALESCE({})", value_sqls))
3683			}
3684		}
3685	}
3686
3687	/// Convert AnnotationValue to SQL string for custom expressions
3688	///
3689	/// Delegates to the `AnnotationValue::to_sql()` method which provides
3690	/// complete SQL generation for all annotation value types.
3691	fn annotation_value_to_sql(value: &super::annotation::AnnotationValue) -> String {
3692		value.to_sql()
3693	}
3694
3695	fn filter_lhs_expr(filter: &Filter) -> Expr {
3696		filter_lhs_expr(filter)
3697	}
3698
3699	fn filter_lhs_sql(filter: &Filter) -> String {
3700		filter_lhs_sql(filter)
3701	}
3702
3703	fn like_expr(
3704		filter: &Filter,
3705		value: &str,
3706		pattern: LikePattern,
3707		case_insensitive: bool,
3708	) -> SimpleExpr {
3709		let operator = if case_insensitive { "ILIKE" } else { "LIKE" };
3710		Expr::cust_with_values(
3711			format!(
3712				"{} {} ? ESCAPE '\\'",
3713				Self::filter_lhs_sql(filter),
3714				operator
3715			),
3716			[pattern.apply(value)],
3717		)
3718		.into_simple_expr()
3719	}
3720
3721	pub(crate) fn filter_value_to_sea_value(v: &FilterValue) -> reinhardt_query::value::Value {
3722		match v {
3723			FilterValue::String(s) => s.clone().into(),
3724			FilterValue::Timestamp(value) => (*value).into(),
3725			FilterValue::Date(value) => (*value).into(),
3726			FilterValue::Time(value) => (*value).into(),
3727			FilterValue::NaiveDateTime(value) => (*value).into(),
3728			FilterValue::Decimal(value) => (*value).into(),
3729			FilterValue::Uuid(value) => (*value).into(),
3730			FilterValue::Integer(i) | FilterValue::Int(i) => (*i).into(),
3731			FilterValue::Float(f) => (*f).into(),
3732			FilterValue::Boolean(b) | FilterValue::Bool(b) => (*b).into(),
3733			FilterValue::Null => reinhardt_query::value::Value::Int(None),
3734			FilterValue::Array(arr) => arr.join(",").into(),
3735			FilterValue::List(values) => values
3736				.iter()
3737				.map(Self::value_to_string)
3738				.collect::<Vec<_>>()
3739				.join(",")
3740				.into(),
3741			FilterValue::Range(start, end) => format!(
3742				"{},{}",
3743				Self::value_to_string(start),
3744				Self::value_to_string(end)
3745			)
3746			.into(),
3747			// FieldRef, Expression, and OuterRef are typically handled separately
3748			// in build_where_condition(), but provide proper conversion as fallback
3749			FilterValue::FieldRef(f) => f.field.clone().into(),
3750			FilterValue::Expression(expr) => expr.to_sql().into(),
3751			FilterValue::OuterRef(outer_ref) => outer_ref.field.clone().into(),
3752		}
3753	}
3754
3755	/// Convert FilterValue to String representation
3756	// Allow dead_code: internal conversion helper for filter value stringification in queries
3757	#[allow(dead_code)]
3758	fn value_to_string(v: &FilterValue) -> String {
3759		match v {
3760			FilterValue::String(s) => s.clone(),
3761			FilterValue::Timestamp(value) => value.to_rfc3339(),
3762			FilterValue::Date(value) => value.to_string(),
3763			FilterValue::Time(value) => value.to_string(),
3764			FilterValue::NaiveDateTime(value) => value.to_string(),
3765			FilterValue::Decimal(value) => value.to_string(),
3766			FilterValue::Uuid(value) => value.to_string(),
3767			FilterValue::Integer(i) | FilterValue::Int(i) => i.to_string(),
3768			FilterValue::Float(f) => f.to_string(),
3769			FilterValue::Boolean(b) | FilterValue::Bool(b) => b.to_string(),
3770			FilterValue::Null => String::new(),
3771			FilterValue::Array(arr) => arr.join(","),
3772			FilterValue::List(values) => values
3773				.iter()
3774				.map(Self::value_to_string)
3775				.collect::<Vec<_>>()
3776				.join(","),
3777			FilterValue::Range(start, end) => {
3778				format!(
3779					"{},{}",
3780					Self::value_to_string(start),
3781					Self::value_to_string(end)
3782				)
3783			}
3784			FilterValue::FieldRef(f) => f.field.clone(),
3785			FilterValue::Expression(expr) => expr.to_sql(),
3786			FilterValue::OuterRef(outer_ref) => outer_ref.field.clone(),
3787		}
3788	}
3789
3790	/// Convert FilterValue to array of reinhardt_query::value::Value
3791	// Allow dead_code: internal conversion for IN clause array parameter binding
3792	#[allow(dead_code)]
3793	fn value_to_array(v: &FilterValue) -> Vec<reinhardt_query::value::Value> {
3794		match v {
3795			FilterValue::String(s) => parse_membership_string(s),
3796			FilterValue::Timestamp(value) => vec![(*value).into()],
3797			FilterValue::Date(value) => vec![(*value).into()],
3798			FilterValue::Time(value) => vec![(*value).into()],
3799			FilterValue::NaiveDateTime(value) => vec![(*value).into()],
3800			FilterValue::Decimal(value) => vec![(*value).into()],
3801			FilterValue::Uuid(value) => vec![(*value).into()],
3802			FilterValue::Integer(i) | FilterValue::Int(i) => vec![(*i).into()],
3803			FilterValue::Float(f) => vec![(*f).into()],
3804			FilterValue::Boolean(b) | FilterValue::Bool(b) => vec![(*b).into()],
3805			FilterValue::Null => vec![reinhardt_query::value::Value::Int(None)],
3806			FilterValue::Array(arr) => arr.iter().map(|s| s.clone().into()).collect(),
3807			FilterValue::List(values) => {
3808				values.iter().map(Self::filter_value_to_sea_value).collect()
3809			}
3810			FilterValue::Range(start, end) => vec![
3811				Self::filter_value_to_sea_value(start),
3812				Self::filter_value_to_sea_value(end),
3813			],
3814			FilterValue::FieldRef(f) => vec![f.field.clone().into()],
3815			FilterValue::Expression(expr) => vec![expr.to_sql().into()],
3816			FilterValue::OuterRef(outer) => vec![outer.field.clone().into()],
3817		}
3818	}
3819
3820	/// Build WHERE clause from accumulated filters
3821	///
3822	/// # Deprecation Note
3823	///
3824	/// This method is maintained for backward compatibility with existing code that
3825	/// expects a string-based WHERE clause. New code should use `build_where_condition()`
3826	/// which returns a `Condition` object that can be directly added to reinhardt-query statements.
3827	///
3828	/// This method generates a complete SELECT statement internally and extracts only
3829	/// the WHERE portion, which is less efficient than using `build_where_condition()`.
3830	// Allow dead_code: backward-compatible string-based WHERE clause builder for legacy code paths
3831	#[allow(dead_code)]
3832	fn build_where_clause(&self) -> (String, Vec<String>) {
3833		if !self.has_where_predicates() {
3834			return (String::new(), Vec::new());
3835		}
3836
3837		// Build reinhardt-query condition
3838		let mut stmt = Query::select();
3839		stmt.from(Alias::new("dummy"));
3840
3841		if let Some(cond) = self.build_where_condition_or_false() {
3842			stmt.cond_where(cond);
3843		}
3844
3845		// Convert to SQL string with inline values
3846		use reinhardt_query::prelude::PostgresQueryBuilder;
3847		let sql = stmt.to_string(PostgresQueryBuilder);
3848
3849		// Extract WHERE clause portion by finding the WHERE keyword
3850		let where_clause = if let Some(idx) = sql.find(" WHERE ") {
3851			sql[idx..].to_string()
3852		} else {
3853			String::new()
3854		};
3855
3856		(where_clause, Vec::new())
3857	}
3858
3859	/// Eagerly load related objects using JOIN queries
3860	///
3861	/// This method performs SQL JOINs to fetch related objects in a single query,
3862	/// reducing the number of database round-trips and preventing N+1 query problems.
3863	///
3864	/// # Performance
3865	///
3866	/// Best for one-to-one and many-to-one relationships where JOIN won't create
3867	/// significant data duplication. For one-to-many and many-to-many relationships,
3868	/// consider using `prefetch_related()` instead.
3869	///
3870	/// # Examples
3871	///
3872	/// ```no_run
3873	/// # use reinhardt_db::orm::Model;
3874	/// # use serde::{Serialize, Deserialize};
3875	/// # #[derive(Clone, Serialize, Deserialize)]
3876	/// # struct Post { id: Option<i64>, author: Author, category: Category }
3877	/// # #[derive(Clone, Serialize, Deserialize)]
3878	/// # struct Author { name: String }
3879	/// # #[derive(Clone, Serialize, Deserialize)]
3880	/// # struct Category { name: String }
3881	/// # #[derive(Clone)]
3882	/// # struct PostFields;
3883	/// # impl reinhardt_db::orm::model::FieldSelector for PostFields {
3884	/// #     fn with_alias(self, _alias: &str) -> Self { self }
3885	/// # }
3886	/// # impl Model for Post {
3887	/// #     type PrimaryKey = i64;
3888	/// #     type Fields = PostFields;
3889	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
3890	/// #     fn table_name() -> &'static str { "posts" }
3891	/// #     fn new_fields() -> Self::Fields { PostFields }
3892	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
3893	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
3894	/// # }
3895	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
3896	/// // Single query with JOINs instead of N+1 queries
3897	/// let posts = Post::objects()
3898	///     .select_related(&["author", "category"])
3899	///     .all()
3900	///     .await?;
3901	///
3902	/// // Each post has author and category pre-loaded
3903	/// for post in posts {
3904	///     println!("Author: {}", post.author.name); // No additional query
3905	/// }
3906	/// # Ok(())
3907	/// # }
3908	/// ```
3909	pub fn select_related(mut self, fields: &[&str]) -> Self {
3910		self.select_related_fields = fields.iter().map(|s| s.to_string()).collect();
3911		self
3912	}
3913
3914	/// Generate SELECT query with JOIN clauses for select_related fields
3915	///
3916	/// Returns reinhardt-query SelectStatement with LEFT JOIN for each related field to enable eager loading.
3917	///
3918	/// # Examples
3919	///
3920	/// ```no_run
3921	/// # use reinhardt_db::orm::Model;
3922	/// # use reinhardt_db::orm::{Filter, FilterOperator, FilterValue};
3923	/// # use serde::{Serialize, Deserialize};
3924	/// # #[derive(Clone, Serialize, Deserialize)]
3925	/// # struct Post { id: Option<i64> }
3926	/// # #[derive(Clone)]
3927	/// # struct PostFields;
3928	/// # impl reinhardt_db::orm::model::FieldSelector for PostFields {
3929	/// #     fn with_alias(self, _alias: &str) -> Self { self }
3930	/// # }
3931	/// # impl Model for Post {
3932	/// #     type PrimaryKey = i64;
3933	/// #     type Fields = PostFields;
3934	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
3935	/// #     fn table_name() -> &'static str { "posts" }
3936	/// #     fn new_fields() -> Self::Fields { PostFields }
3937	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
3938	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
3939	/// # }
3940	/// let queryset = Post::objects()
3941	///     .select_related(&["author", "category"])
3942	///     .filter(Filter::new("published", FilterOperator::Eq, FilterValue::Boolean(true)));
3943	///
3944	/// let stmt = queryset.select_related_query();
3945	/// // Generates:
3946	/// // SELECT posts.*, author.*, category.* FROM posts
3947	/// //   LEFT JOIN users AS author ON posts.author_id = author.id
3948	/// //   LEFT JOIN categories AS category ON posts.category_id = category.id
3949	/// //   WHERE posts.published = $1
3950	/// ```
3951	pub fn select_related_query(&self) -> SelectStatement {
3952		let table_name = T::table_name();
3953		let mut stmt = Query::select();
3954
3955		// Apply FROM clause with optional alias
3956		if let Some(ref alias) = self.from_alias {
3957			stmt.from_as(Alias::new(table_name), Alias::new(alias));
3958		} else {
3959			stmt.from(Alias::new(table_name));
3960		}
3961
3962		// Apply DISTINCT if enabled
3963		if self.distinct_enabled {
3964			stmt.distinct();
3965		}
3966
3967		// Add main table columns
3968		stmt.column(ColumnRef::table_asterisk(Alias::new(table_name)));
3969
3970		// Add LEFT JOIN for each related field
3971		for related_field in &self.select_related_fields {
3972			// Convention: related_field is the field name in the model
3973			// We assume FK field is "{related_field}_id" and join to "{related_field}s" table
3974			let fk_field = Alias::new(format!("{}_id", related_field));
3975			let related_table = Alias::new(format!("{}s", related_field));
3976			let related_alias = Alias::new(related_field);
3977
3978			// LEFT JOIN related_table AS related_field ON table.fk_field = related_field.id
3979			stmt.left_join(
3980				related_table,
3981				Expr::col((Alias::new(table_name), fk_field))
3982					.equals((related_alias.clone(), Alias::new("id"))),
3983			);
3984
3985			// Add related table columns to SELECT
3986			stmt.column(ColumnRef::table_asterisk(related_alias));
3987		}
3988
3989		// Apply manual JOINs
3990		for join in &self.joins {
3991			if join.on_condition.is_empty() {
3992				// CROSS JOIN (no ON condition)
3993				if let Some(ref alias) = join.target_alias {
3994					stmt.cross_join((Alias::new(&join.target_table), Alias::new(alias)));
3995				} else {
3996					stmt.cross_join(Alias::new(&join.target_table));
3997				}
3998			} else {
3999				// Convert reinhardt JoinType to reinhardt-query JoinType
4000				let sea_join_type = match join.join_type {
4001					super::sqlalchemy_query::JoinType::Inner => SeaJoinType::InnerJoin,
4002					super::sqlalchemy_query::JoinType::Left => SeaJoinType::LeftJoin,
4003					super::sqlalchemy_query::JoinType::Right => SeaJoinType::RightJoin,
4004					super::sqlalchemy_query::JoinType::Full => SeaJoinType::FullOuterJoin,
4005				};
4006
4007				// Build the join with optional alias
4008				if let Some(ref alias) = join.target_alias {
4009					stmt.join(
4010						sea_join_type,
4011						(Alias::new(&join.target_table), Alias::new(alias)),
4012						Expr::cust(join.on_condition.clone()),
4013					);
4014				} else {
4015					stmt.join(
4016						sea_join_type,
4017						Alias::new(&join.target_table),
4018						Expr::cust(join.on_condition.clone()),
4019					);
4020				}
4021			}
4022		}
4023
4024		// Apply WHERE conditions
4025		if let Some(cond) = self.build_where_condition_or_false() {
4026			stmt.cond_where(cond);
4027		}
4028
4029		// Apply GROUP BY
4030		for group_field in &self.group_by_fields {
4031			let col_ref = parse_column_reference(group_field);
4032			stmt.group_by_col(col_ref);
4033		}
4034
4035		// Apply HAVING
4036		for having_cond in &self.having_conditions {
4037			match having_cond {
4038				HavingCondition::AggregateCompare {
4039					func,
4040					field,
4041					operator,
4042					value,
4043				} => {
4044					// Build aggregate function expression
4045					let agg_expr = match func {
4046						AggregateFunc::Avg => {
4047							Func::avg(Expr::col(Alias::new(field)).into_simple_expr())
4048						}
4049						AggregateFunc::Count => {
4050							if field == "*" {
4051								Func::count(Expr::asterisk().into_simple_expr())
4052							} else {
4053								Func::count(Expr::col(Alias::new(field)).into_simple_expr())
4054							}
4055						}
4056						AggregateFunc::Sum => {
4057							Func::sum(Expr::col(Alias::new(field)).into_simple_expr())
4058						}
4059						AggregateFunc::Min => {
4060							Func::min(Expr::col(Alias::new(field)).into_simple_expr())
4061						}
4062						AggregateFunc::Max => {
4063							Func::max(Expr::col(Alias::new(field)).into_simple_expr())
4064						}
4065					};
4066
4067					// Build comparison expression
4068					let having_expr = match operator {
4069						ComparisonOp::Eq => match value {
4070							AggregateValue::Int(v) => agg_expr.eq(*v),
4071							AggregateValue::Float(v) => agg_expr.eq(*v),
4072						},
4073						ComparisonOp::Ne => match value {
4074							AggregateValue::Int(v) => agg_expr.ne(*v),
4075							AggregateValue::Float(v) => agg_expr.ne(*v),
4076						},
4077						ComparisonOp::Gt => match value {
4078							AggregateValue::Int(v) => agg_expr.gt(*v),
4079							AggregateValue::Float(v) => agg_expr.gt(*v),
4080						},
4081						ComparisonOp::Gte => match value {
4082							AggregateValue::Int(v) => agg_expr.gte(*v),
4083							AggregateValue::Float(v) => agg_expr.gte(*v),
4084						},
4085						ComparisonOp::Lt => match value {
4086							AggregateValue::Int(v) => agg_expr.lt(*v),
4087							AggregateValue::Float(v) => agg_expr.lt(*v),
4088						},
4089						ComparisonOp::Lte => match value {
4090							AggregateValue::Int(v) => agg_expr.lte(*v),
4091							AggregateValue::Float(v) => agg_expr.lte(*v),
4092						},
4093					};
4094
4095					stmt.and_having(having_expr);
4096				}
4097			}
4098		}
4099
4100		// Apply ORDER BY
4101		for order_field in &self.order_by_fields {
4102			let (field, is_desc) = if let Some(stripped) = order_field.strip_prefix('-') {
4103				(stripped, true)
4104			} else {
4105				(order_field.as_str(), false)
4106			};
4107
4108			let col_ref = parse_column_reference(field);
4109			let expr = Expr::col(col_ref);
4110			if is_desc {
4111				stmt.order_by_expr(expr, Order::Desc);
4112			} else {
4113				stmt.order_by_expr(expr, Order::Asc);
4114			}
4115		}
4116
4117		// Apply LIMIT/OFFSET
4118		if let Some(limit) = self.limit {
4119			stmt.limit(limit as u64);
4120		}
4121		if let Some(offset) = self.offset {
4122			stmt.offset(offset as u64);
4123		}
4124
4125		stmt.to_owned()
4126	}
4127
4128	/// Eagerly load related objects using separate queries
4129	///
4130	/// This method performs separate SQL queries for related objects and joins them
4131	/// in memory, which is more efficient than JOINs for one-to-many and many-to-many
4132	/// relationships that would create significant data duplication.
4133	///
4134	/// # Performance
4135	///
4136	/// Best for one-to-many and many-to-many relationships where JOINs would create
4137	/// data duplication (e.g., a post with 100 comments would duplicate post data 100 times).
4138	/// Uses 1 + N queries where N is the number of prefetch_related fields.
4139	///
4140	/// # Examples
4141	///
4142	/// ```no_run
4143	/// # use reinhardt_db::orm::Model;
4144	/// # use serde::{Serialize, Deserialize};
4145	/// # #[derive(Clone, Serialize, Deserialize)]
4146	/// # struct Post { id: Option<i64>, comments: Vec<Comment>, tags: Vec<Tag> }
4147	/// # #[derive(Clone, Serialize, Deserialize)]
4148	/// # struct Comment { text: String }
4149	/// # #[derive(Clone, Serialize, Deserialize)]
4150	/// # struct Tag { name: String }
4151	/// # #[derive(Clone)]
4152	/// # struct PostFields;
4153	/// # impl reinhardt_db::orm::model::FieldSelector for PostFields {
4154	/// #     fn with_alias(self, _alias: &str) -> Self { self }
4155	/// # }
4156	/// # impl Model for Post {
4157	/// #     type PrimaryKey = i64;
4158	/// #     type Fields = PostFields;
4159	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
4160	/// #     fn table_name() -> &'static str { "posts" }
4161	/// #     fn new_fields() -> Self::Fields { PostFields }
4162	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
4163	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
4164	/// # }
4165	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
4166	/// // 2 queries total instead of N+1 queries
4167	/// let posts = Post::objects()
4168	///     .prefetch_related(&["comments", "tags"])
4169	///     .all()
4170	///     .await?;
4171	///
4172	/// // Each post has comments and tags pre-loaded
4173	/// for post in posts {
4174	///     for comment in &post.comments {
4175	///         println!("Comment: {}", comment.text); // No additional query
4176	///     }
4177	/// }
4178	/// # Ok(())
4179	/// # }
4180	/// ```
4181	pub fn prefetch_related(mut self, fields: &[&str]) -> Self {
4182		self.prefetch_related_fields = fields.iter().map(|s| s.to_string()).collect();
4183		self
4184	}
4185
4186	/// Generate SELECT queries for prefetch_related fields
4187	///
4188	/// Returns a vector of (field_name, SelectStatement) tuples, one for each prefetch field.
4189	/// Each query fetches related objects using IN clause with collected primary keys.
4190	///
4191	/// # Examples
4192	///
4193	/// ```no_run
4194	/// # use reinhardt_db::orm::Model;
4195	/// # use serde::{Serialize, Deserialize};
4196	/// # #[derive(Clone, Serialize, Deserialize)]
4197	/// # struct Post { id: Option<i64> }
4198	/// # #[derive(Clone)]
4199	/// # struct PostFields;
4200	/// # impl reinhardt_db::orm::model::FieldSelector for PostFields {
4201	/// #     fn with_alias(self, _alias: &str) -> Self { self }
4202	/// # }
4203	/// # impl Model for Post {
4204	/// #     type PrimaryKey = i64;
4205	/// #     type Fields = PostFields;
4206	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
4207	/// #     fn table_name() -> &'static str { "posts" }
4208	/// #     fn new_fields() -> Self::Fields { PostFields }
4209	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
4210	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
4211	/// # }
4212	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
4213	/// let queryset = Post::objects()
4214	///     .prefetch_related(&["comments", "tags"]);
4215	///
4216	/// let main_results = queryset.all().await?; // Main query
4217	/// let pk_values = vec![1, 2, 3]; // Collected from main results
4218	///
4219	/// let prefetch_queries = queryset.prefetch_related_queries(&pk_values);
4220	/// // Returns SelectStatements for:
4221	/// // 1. comments: SELECT * FROM comments WHERE post_id IN ($1, $2, $3)
4222	/// // 2. tags: SELECT tags.* FROM tags
4223	/// //          INNER JOIN post_tags ON tags.id = post_tags.tag_id
4224	/// //          WHERE post_tags.post_id IN ($1, $2, $3)
4225	/// # Ok(())
4226	/// # }
4227	/// ```
4228	pub fn prefetch_related_queries(&self, pk_values: &[i64]) -> Vec<(String, SelectStatement)> {
4229		if pk_values.is_empty() {
4230			return Vec::new();
4231		}
4232
4233		let mut queries = Vec::new();
4234
4235		for related_field in &self.prefetch_related_fields {
4236			// Determine if this is a many-to-many relation or one-to-many
4237			// by querying the model's relationship metadata
4238			let is_m2m = self.is_many_to_many_relation(related_field);
4239
4240			let stmt = if is_m2m {
4241				self.prefetch_many_to_many_query(related_field, pk_values)
4242			} else {
4243				self.prefetch_one_to_many_query(related_field, pk_values)
4244			};
4245
4246			queries.push((related_field.clone(), stmt));
4247		}
4248
4249		queries
4250	}
4251
4252	/// Check if a related field is a many-to-many relation
4253	///
4254	/// Determines relationship type by querying the model's metadata.
4255	/// Returns true if the relationship is defined as ManyToMany in the model metadata.
4256	fn is_many_to_many_relation(&self, related_field: &str) -> bool {
4257		// Get relationship metadata from the model
4258		let relations = T::relationship_metadata();
4259
4260		// Find the relationship with the matching name
4261		relations
4262			.iter()
4263			.find(|rel| rel.name == related_field)
4264			.map(|rel| rel.relationship_type == super::relationship::RelationshipType::ManyToMany)
4265			.unwrap_or(false)
4266	}
4267
4268	/// Generate query for one-to-many prefetch
4269	///
4270	/// Generates: SELECT * FROM related_table WHERE fk_field IN (pk_values)
4271	fn prefetch_one_to_many_query(
4272		&self,
4273		related_field: &str,
4274		pk_values: &[i64],
4275	) -> SelectStatement {
4276		let table_name = T::table_name();
4277		let related_table = Alias::new(format!("{}s", related_field));
4278		let fk_field = Alias::new(format!("{}_id", table_name.trim_end_matches('s')));
4279
4280		let mut stmt = Query::select();
4281		stmt.from(related_table).column(ColumnRef::Asterisk);
4282
4283		// Add IN clause with pk_values
4284		let values: Vec<reinhardt_query::value::Value> =
4285			pk_values.iter().map(|&id| id.into()).collect();
4286		stmt.and_where(Expr::col(fk_field).is_in(values));
4287
4288		stmt.to_owned()
4289	}
4290
4291	/// Generate query for many-to-many prefetch
4292	///
4293	/// Generates: SELECT related.*, junction.main_id FROM related
4294	///            INNER JOIN junction ON related.id = junction.related_id
4295	///            WHERE junction.main_id IN (pk_values)
4296	fn prefetch_many_to_many_query(
4297		&self,
4298		related_field: &str,
4299		pk_values: &[i64],
4300	) -> SelectStatement {
4301		let table_name = T::table_name();
4302		// Apply the canonical M2M naming rule used by
4303		// `ManyToManyAccessor::default_through_table` and the autodetector
4304		// (`crates/reinhardt-db/src/migrations/autodetector.rs`):
4305		// `{source_table.to_lowercase()}_{to_snake_case(field_name)}`.
4306		// Without this, prefetch joins target a junction table whose
4307		// casing/snake-case diverges from what `makemigrations` produced
4308		// for the same M2M field (#4659).
4309		let junction_table = Alias::new(format!(
4310			"{}_{}",
4311			table_name.to_lowercase(),
4312			to_snake_case(related_field)
4313		));
4314
4315		// Look up relationship metadata to derive FK names correctly
4316		let rel_info = T::relationship_metadata().into_iter().find(|r| {
4317			r.name == related_field
4318				&& r.relationship_type == super::relationship::RelationshipType::ManyToMany
4319		});
4320
4321		// Derive related table name from metadata
4322		let related_table = if let Some(ref info) = rel_info {
4323			Alias::new(to_snake_case(&info.related_model).to_lowercase())
4324		} else {
4325			// Fallback to pluralization heuristic
4326			Alias::new(format!("{}s", related_field))
4327		};
4328
4329		// Derive junction FK names from metadata or use default_link_fields logic
4330		let table_name_lower = table_name.to_lowercase();
4331		let (junction_main_fk, junction_related_fk) = if let Some(ref info) = rel_info {
4332			let source_fk = if let Some(ref sf) = info.source_field {
4333				sf.clone()
4334			} else {
4335				// Mirror ManyToManyAccessor::default_link_fields logic
4336				let related_lower = to_snake_case(&info.related_model).to_lowercase();
4337				if table_name_lower == related_lower {
4338					format!("from_{}_id", table_name_lower)
4339				} else {
4340					format!("{}_id", table_name_lower)
4341				}
4342			};
4343
4344			let target_fk = if let Some(ref tf) = info.target_field {
4345				tf.clone()
4346			} else {
4347				let related_lower = to_snake_case(&info.related_model).to_lowercase();
4348				if table_name_lower == related_lower {
4349					format!("to_{}_id", table_name_lower)
4350				} else {
4351					format!("{}_id", to_snake_case(related_field))
4352				}
4353			};
4354
4355			(Alias::new(source_fk), Alias::new(target_fk))
4356		} else {
4357			// Fallback to heuristics
4358			let source_fk = format!("{}_id", table_name_lower);
4359			let target_fk = format!("{}_id", to_snake_case(related_field));
4360			(Alias::new(source_fk), Alias::new(target_fk))
4361		};
4362
4363		let mut stmt = Query::select();
4364		stmt.from(related_table.clone())
4365			.column(ColumnRef::table_asterisk(related_table.clone()))
4366			.column((junction_table.clone(), junction_main_fk.clone()))
4367			.inner_join(
4368				junction_table.clone(),
4369				Expr::col((related_table.clone(), Alias::new("id")))
4370					.equals((junction_table.clone(), junction_related_fk)),
4371			);
4372
4373		// Add IN clause with pk_values
4374		let values: Vec<reinhardt_query::value::Value> =
4375			pk_values.iter().map(|&id| id.into()).collect();
4376		stmt.and_where(Expr::col((junction_table, junction_main_fk)).is_in(values));
4377
4378		stmt.to_owned()
4379	}
4380
4381	fn build_select_statement(&self) -> reinhardt_core::exception::Result<SelectStatement> {
4382		let has_structural_clauses = !self.select_related_fields.is_empty()
4383			|| !self.joins.is_empty()
4384			|| !self.group_by_fields.is_empty()
4385			|| !self.having_conditions.is_empty();
4386		let mut stmt = if has_structural_clauses {
4387			self.select_related_query()
4388		} else {
4389			let mut stmt = Query::select();
4390			if let Some(ref alias) = self.from_alias {
4391				stmt.from_as(Alias::new(T::table_name()), Alias::new(alias));
4392			} else {
4393				stmt.from(Alias::new(T::table_name()));
4394			}
4395
4396			if self.distinct_enabled {
4397				stmt.distinct();
4398			}
4399
4400			if let Some(ref fields) = self.selected_fields {
4401				for field in fields {
4402					if field.contains('(') && field.contains(')') {
4403						stmt.expr(Expr::cust(field.clone()));
4404					} else {
4405						stmt.column(parse_column_reference(field));
4406					}
4407				}
4408			} else if !self.deferred_fields.is_empty() {
4409				for field in T::field_metadata() {
4410					if !self.deferred_fields.contains(&field.name) {
4411						stmt.column(parse_column_reference(&field.name));
4412					}
4413				}
4414			} else {
4415				stmt.column(ColumnRef::Asterisk);
4416			}
4417
4418			if let Some(cond) = self.build_where_condition()? {
4419				stmt.cond_where(cond);
4420			}
4421
4422			for order_field in &self.order_by_fields {
4423				let (field, order) = if let Some(field) = order_field.strip_prefix('-') {
4424					(field, Order::Desc)
4425				} else {
4426					(order_field.as_str(), Order::Asc)
4427				};
4428				stmt.order_by_expr(Expr::col(parse_column_reference(field)), order);
4429			}
4430
4431			if let Some(limit) = self.limit {
4432				stmt.limit(limit as u64);
4433			}
4434			if let Some(offset) = self.offset {
4435				stmt.offset(offset as u64);
4436			}
4437
4438			stmt.to_owned()
4439		};
4440
4441		if let Some(subquery_sql) = &self.from_subquery_sql {
4442			let inner_sql = subquery_sql
4443				.strip_prefix('(')
4444				.and_then(|sql| sql.strip_suffix(')'))
4445				.unwrap_or(subquery_sql);
4446			stmt.clear_from().from_subquery(
4447				SelectStatement::raw(inner_sql),
4448				Alias::new(self.from_alias.as_deref().unwrap_or(T::table_name())),
4449			);
4450		}
4451
4452		for annotation in &self.annotations {
4453			stmt.expr_as(
4454				Expr::cust(annotation.value.to_sql_expr()),
4455				Alias::new(&annotation.alias),
4456			);
4457		}
4458
4459		for cte in self.ctes.iter() {
4460			let query = SelectStatement::raw(cte.query.clone());
4461			if cte.recursive {
4462				stmt.with_recursive_cte(Alias::new(&cte.name), query);
4463			} else {
4464				stmt.with_cte(Alias::new(&cte.name), query);
4465			}
4466		}
4467
4468		for join in self.lateral_joins.iter() {
4469			let join_type = match join.join_type {
4470				super::lateral_join::LateralJoinType::Inner => SeaJoinType::InnerJoin,
4471				super::lateral_join::LateralJoinType::Left => SeaJoinType::LeftJoin,
4472				super::lateral_join::LateralJoinType::Right => SeaJoinType::RightJoin,
4473				super::lateral_join::LateralJoinType::Full => SeaJoinType::FullOuterJoin,
4474			};
4475			let condition = join.on_condition.as_deref().unwrap_or("true");
4476			stmt.join(
4477				join_type,
4478				reinhardt_query::types::TableRef::lateral_subquery(
4479					SelectStatement::raw(join.subquery.clone()),
4480					Alias::new(&join.alias),
4481				),
4482				Expr::cust(condition),
4483			);
4484		}
4485
4486		Ok(stmt)
4487	}
4488
4489	pub(crate) fn build_full_model_select_statement(
4490		&self,
4491	) -> reinhardt_core::exception::Result<SelectStatement> {
4492		if self.selected_fields.is_some()
4493			|| !self.deferred_fields.is_empty()
4494			|| !self.select_related_fields.is_empty()
4495		{
4496			return Err(reinhardt_core::exception::Error::Database(
4497				"Session::list requires a model-shaped QuerySet".to_owned(),
4498			));
4499		}
4500
4501		self.build_select_statement()
4502	}
4503
4504	/// Remove manager result-shape modifiers before decoding rows as model values.
4505	///
4506	/// Scope predicates, ordering, limits, and offsets remain intact. Projection
4507	/// and eager-loading options are discarded because this session path decodes
4508	/// only the root model from each row. Annotations are retained when present
4509	/// because manager ordering may reference their aliases.
4510	pub fn for_model_session(mut self) -> Self {
4511		self.selected_fields = None;
4512		self.deferred_fields.clear();
4513		self.select_related_fields.clear();
4514		self.prefetch_related_fields.clear();
4515		self
4516	}
4517
4518	/// Execute the queryset and return all matching records
4519	///
4520	/// Fetches all records from the database that match the accumulated filters.
4521	/// If `select_related` fields are specified, performs JOIN queries for eager loading.
4522	///
4523	/// # Examples
4524	///
4525	/// ```no_run
4526	/// # use reinhardt_db::orm::Model;
4527	/// # use reinhardt_db::orm::{Filter, FilterOperator, FilterValue};
4528	/// # use serde::{Serialize, Deserialize};
4529	/// # #[derive(Clone, Serialize, Deserialize)]
4530	/// # struct User { id: Option<i64> }
4531	/// # #[derive(Clone)]
4532	/// # struct UserFields;
4533	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
4534	/// #     fn with_alias(self, _alias: &str) -> Self { self }
4535	/// # }
4536	/// # impl Model for User {
4537	/// #     type PrimaryKey = i64;
4538	/// #     type Fields = UserFields;
4539	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
4540	/// #     fn table_name() -> &'static str { "users" }
4541	/// #     fn new_fields() -> Self::Fields { UserFields }
4542	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
4543	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
4544	/// # }
4545	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
4546	/// // Fetch all users (Manager.all() returns QuerySet, then call .all().await)
4547	/// let users = User::objects().all().all().await?;
4548	///
4549	/// // Fetch filtered users with eager loading
4550	/// let active_users = User::objects()
4551	///     .filter(Filter::new(
4552	///         "is_active",
4553	///         FilterOperator::Eq,
4554	///         FilterValue::Boolean(true),
4555	///     ))
4556	///     .select_related(&["profile"])
4557	///     .all()
4558	///     .await?;
4559	/// # Ok(())
4560	/// # }
4561	/// ```
4562	///
4563	/// # Errors
4564	///
4565	/// Returns an error if:
4566	/// - Database connection fails
4567	/// - SQL execution fails
4568	/// - Deserialization of results fails
4569	pub async fn all(&self) -> reinhardt_core::exception::Result<Vec<T>>
4570	where
4571		T: serde::de::DeserializeOwned,
4572	{
4573		let conn = super::manager::get_connection().await?;
4574
4575		let stmt = if self.select_related_fields.is_empty() {
4576			self.build_select_statement()?
4577		} else {
4578			// SELECT with JOINs for select_related
4579			self.select_related_query()
4580		};
4581
4582		// Convert statement to SQL with inline values (no placeholders)
4583		let sql = stmt.to_string(PostgresQueryBuilder);
4584
4585		// Execute query and deserialize results
4586		let started_at = Instant::now();
4587		let query_result = conn.query(&sql, vec![]).await;
4588		let duration = started_at.elapsed();
4589
4590		let rows = match query_result {
4591			Ok(rows) => {
4592				super::instrumentation::instrumentation()
4593					.orm_query_end_with_params(&sql, &[], duration)
4594					.await;
4595				rows
4596			}
4597			Err(error) => {
4598				super::instrumentation::instrumentation()
4599					.query_error(&sql, &format!("{error:?}"), duration)
4600					.await;
4601				return Err(error.into());
4602			}
4603		};
4604		rows.into_iter()
4605			.map(|row| {
4606				serde_json::from_value(serde_json::to_value(&row.data).map_err(|e| {
4607					reinhardt_core::exception::Error::Database(format!(
4608						"Serialization error: {}",
4609						e
4610					))
4611				})?)
4612				.map_err(|e| {
4613					reinhardt_core::exception::Error::Database(format!(
4614						"Deserialization error: {}",
4615						e
4616					))
4617				})
4618			})
4619			.collect()
4620	}
4621
4622	/// Execute the queryset and return the first matching record
4623	///
4624	/// Returns `None` if no records match the query.
4625	///
4626	/// # Examples
4627	///
4628	/// ```no_run
4629	/// # use reinhardt_db::orm::Model;
4630	/// # use reinhardt_db::orm::{Filter, FilterOperator, FilterValue};
4631	/// # use serde::{Serialize, Deserialize};
4632	/// # #[derive(Clone, Serialize, Deserialize)]
4633	/// # struct User { id: Option<i64>, username: String }
4634	/// # #[derive(Clone)]
4635	/// # struct UserFields;
4636	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
4637	/// #     fn with_alias(self, _alias: &str) -> Self { self }
4638	/// # }
4639	/// # impl Model for User {
4640	/// #     type PrimaryKey = i64;
4641	/// #     type Fields = UserFields;
4642	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
4643	/// #     fn table_name() -> &'static str { "users" }
4644	/// #     fn new_fields() -> Self::Fields { UserFields }
4645	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
4646	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
4647	/// # }
4648	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
4649	/// // Fetch first active user
4650	/// let user = User::objects()
4651	///     .filter(Filter::new(
4652	///         "is_active",
4653	///         FilterOperator::Eq,
4654	///         FilterValue::Boolean(true),
4655	///     ))
4656	///     .first()
4657	///     .await?;
4658	///
4659	/// match user {
4660	///     Some(u) => println!("Found user: {}", u.username),
4661	///     None => println!("No active users found"),
4662	/// }
4663	/// # Ok(())
4664	/// # }
4665	/// ```
4666	pub async fn first(&self) -> reinhardt_core::exception::Result<Option<T>>
4667	where
4668		T: serde::de::DeserializeOwned,
4669	{
4670		let mut results = self.all().await?;
4671		Ok(results.drain(..).next())
4672	}
4673
4674	/// Execute the queryset and return a single matching record
4675	///
4676	/// Returns an error if zero or multiple records are found.
4677	///
4678	/// # Examples
4679	///
4680	/// ```no_run
4681	/// # use reinhardt_db::orm::Model;
4682	/// # use reinhardt_db::orm::{Filter, FilterOperator, FilterValue};
4683	/// # use serde::{Serialize, Deserialize};
4684	/// # #[derive(Clone, Serialize, Deserialize)]
4685	/// # struct User { id: Option<i64>, email: String }
4686	/// # #[derive(Clone)]
4687	/// # struct UserFields;
4688	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
4689	/// #     fn with_alias(self, _alias: &str) -> Self { self }
4690	/// # }
4691	/// # impl Model for User {
4692	/// #     type PrimaryKey = i64;
4693	/// #     type Fields = UserFields;
4694	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
4695	/// #     fn table_name() -> &'static str { "users" }
4696	/// #     fn new_fields() -> Self::Fields { UserFields }
4697	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
4698	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
4699	/// # }
4700	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
4701	/// // Fetch user with specific email (must be unique)
4702	/// let user = User::objects()
4703	///     .filter(Filter::new(
4704	///         "email",
4705	///         FilterOperator::Eq,
4706	///         FilterValue::String("alice@example.com".to_string()),
4707	///     ))
4708	///     .get()
4709	///     .await?;
4710	/// # Ok(())
4711	/// # }
4712	/// ```
4713	///
4714	/// # Errors
4715	///
4716	/// Returns an error if:
4717	/// - No records match the query
4718	/// - Multiple records match the query
4719	/// - Database connection fails
4720	pub async fn get(&self) -> reinhardt_core::exception::Result<T>
4721	where
4722		T: serde::de::DeserializeOwned,
4723	{
4724		let results = self.all().await?;
4725		match results.len() {
4726			0 => Err(reinhardt_core::exception::Error::Database(
4727				"No record found matching the query".to_string(),
4728			)),
4729			1 => Ok(results.into_iter().next().unwrap()),
4730			n => Err(reinhardt_core::exception::Error::Database(format!(
4731				"Multiple records found ({}), expected exactly one",
4732				n
4733			))),
4734		}
4735	}
4736
4737	/// Execute the queryset with an explicit database connection and return all records
4738	///
4739	/// # Examples
4740	///
4741	/// ```no_run
4742	/// # use reinhardt_db::orm::Model;
4743	/// # use serde::{Serialize, Deserialize};
4744	/// # #[derive(Clone, Serialize, Deserialize)]
4745	/// # struct User { id: Option<i64> }
4746	/// # #[derive(Clone)]
4747	/// # struct UserFields;
4748	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
4749	/// #     fn with_alias(self, _alias: &str) -> Self { self }
4750	/// # }
4751	/// # impl Model for User {
4752	/// #     type PrimaryKey = i64;
4753	/// #     type Fields = UserFields;
4754	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
4755	/// #     fn table_name() -> &'static str { "users" }
4756	/// #     fn new_fields() -> Self::Fields { UserFields }
4757	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
4758	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
4759	/// # }
4760	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
4761	/// # let db = reinhardt_db::orm::manager::get_connection().await?;
4762	/// let users = User::objects()
4763	///     .all()
4764	///     .all_with_db(&db)
4765	///     .await?;
4766	/// # Ok(())
4767	/// # }
4768	/// ```
4769	pub async fn all_with_db(
4770		&self,
4771		conn: &super::connection::DatabaseConnection,
4772	) -> reinhardt_core::exception::Result<Vec<T>>
4773	where
4774		T: serde::de::DeserializeOwned,
4775	{
4776		let stmt = if self.select_related_fields.is_empty() {
4777			self.build_select_statement()?
4778		} else {
4779			self.select_related_query()
4780		};
4781
4782		let (sql, params) = build_select_statement(&stmt, conn.backend())?;
4783
4784		let started_at = Instant::now();
4785		let query_result = conn.query(&sql, params.clone()).await;
4786		let duration = started_at.elapsed();
4787
4788		let rows = match query_result {
4789			Ok(rows) => {
4790				let instrumentation_params = params
4791					.iter()
4792					.map(|param| format!("{param:?}"))
4793					.collect::<Vec<_>>();
4794				super::instrumentation::instrumentation()
4795					.orm_query_end_with_params(&sql, &instrumentation_params, duration)
4796					.await;
4797				rows
4798			}
4799			Err(error) => {
4800				super::instrumentation::instrumentation()
4801					.query_error(&sql, &format!("{error:?}"), duration)
4802					.await;
4803				return Err(error.into());
4804			}
4805		};
4806		rows.into_iter()
4807			.map(|row| {
4808				serde_json::from_value(serde_json::to_value(&row.data).map_err(|e| {
4809					reinhardt_core::exception::Error::Database(format!(
4810						"Serialization error: {}",
4811						e
4812					))
4813				})?)
4814				.map_err(|e| {
4815					reinhardt_core::exception::Error::Database(format!(
4816						"Deserialization error: {}",
4817						e
4818					))
4819				})
4820			})
4821			.collect()
4822	}
4823
4824	/// Execute the queryset with an explicit database connection and return a single record
4825	///
4826	/// # Examples
4827	///
4828	/// ```no_run
4829	/// # use reinhardt_db::orm::Model;
4830	/// # use serde::{Serialize, Deserialize};
4831	/// # #[derive(Clone, Serialize, Deserialize)]
4832	/// # struct User { id: Option<i64> }
4833	/// # #[derive(Clone)]
4834	/// # struct UserFields;
4835	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
4836	/// #     fn with_alias(self, _alias: &str) -> Self { self }
4837	/// # }
4838	/// # impl Model for User {
4839	/// #     type PrimaryKey = i64;
4840	/// #     type Fields = UserFields;
4841	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
4842	/// #     fn table_name() -> &'static str { "users" }
4843	/// #     fn new_fields() -> Self::Fields { UserFields }
4844	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
4845	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
4846	/// # }
4847	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
4848	/// # let user_id = 1;
4849	/// let db = reinhardt_db::orm::manager::get_connection().await?;
4850	/// let user = User::objects()
4851	///     .filter(reinhardt_db::orm::Filter::new("id", reinhardt_db::orm::FilterOperator::Eq, reinhardt_db::orm::FilterValue::Integer(user_id)))
4852	///     .get_with_db(&db)
4853	///     .await?;
4854	/// # Ok(())
4855	/// # }
4856	/// ```
4857	pub async fn get_with_db(
4858		&self,
4859		conn: &super::connection::DatabaseConnection,
4860	) -> reinhardt_core::exception::Result<T>
4861	where
4862		T: serde::de::DeserializeOwned,
4863	{
4864		let results = self.all_with_db(conn).await?;
4865		match results.len() {
4866			0 => Err(reinhardt_core::exception::Error::NotFound(
4867				"No record found matching the query".to_string(),
4868			)),
4869			1 => Ok(results.into_iter().next().unwrap()),
4870			n => Err(reinhardt_core::exception::Error::Database(format!(
4871				"Multiple records found ({}), expected exactly one",
4872				n
4873			))),
4874		}
4875	}
4876
4877	/// Execute the queryset with an explicit database connection and return the first record
4878	///
4879	/// # Examples
4880	///
4881	/// ```no_run
4882	/// # use reinhardt_db::orm::Model;
4883	/// # use serde::{Serialize, Deserialize};
4884	/// # #[derive(Clone, Serialize, Deserialize)]
4885	/// # struct User { id: Option<i64> }
4886	/// # #[derive(Clone)]
4887	/// # struct UserFields;
4888	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
4889	/// #     fn with_alias(self, _alias: &str) -> Self { self }
4890	/// # }
4891	/// # impl Model for User {
4892	/// #     type PrimaryKey = i64;
4893	/// #     type Fields = UserFields;
4894	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
4895	/// #     fn table_name() -> &'static str { "users" }
4896	/// #     fn new_fields() -> Self::Fields { UserFields }
4897	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
4898	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
4899	/// # }
4900	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
4901	/// let db = reinhardt_db::orm::manager::get_connection().await?;
4902	/// let user = User::objects()
4903	///     .filter(reinhardt_db::orm::Filter::new("status", reinhardt_db::orm::FilterOperator::Eq, reinhardt_db::orm::FilterValue::String("active".to_string())))
4904	///     .first_with_db(&db)
4905	///     .await?;
4906	/// # Ok(())
4907	/// # }
4908	/// ```
4909	pub async fn first_with_db(
4910		&self,
4911		conn: &super::connection::DatabaseConnection,
4912	) -> reinhardt_core::exception::Result<Option<T>>
4913	where
4914		T: serde::de::DeserializeOwned,
4915	{
4916		let mut results = self.all_with_db(conn).await?;
4917		Ok(results.drain(..).next())
4918	}
4919
4920	/// Execute the queryset and return the count of matching records
4921	///
4922	/// More efficient than calling `all().await?.len()` as it only executes COUNT query.
4923	///
4924	/// # Examples
4925	///
4926	/// ```no_run
4927	/// # use reinhardt_db::orm::Model;
4928	/// # use reinhardt_db::orm::{Filter, FilterOperator, FilterValue};
4929	/// # use serde::{Serialize, Deserialize};
4930	/// # #[derive(Clone, Serialize, Deserialize)]
4931	/// # struct User { id: Option<i64> }
4932	/// # #[derive(Clone)]
4933	/// # struct UserFields;
4934	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
4935	/// #     fn with_alias(self, _alias: &str) -> Self { self }
4936	/// # }
4937	/// # impl Model for User {
4938	/// #     type PrimaryKey = i64;
4939	/// #     type Fields = UserFields;
4940	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
4941	/// #     fn table_name() -> &'static str { "users" }
4942	/// #     fn new_fields() -> Self::Fields { UserFields }
4943	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
4944	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
4945	/// # }
4946	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
4947	/// // Count active users
4948	/// let count = User::objects()
4949	///     .filter(Filter::new(
4950	///         "is_active",
4951	///         FilterOperator::Eq,
4952	///         FilterValue::Boolean(true),
4953	///     ))
4954	///     .count()
4955	///     .await?;
4956	///
4957	/// println!("Active users: {}", count);
4958	/// # Ok(())
4959	/// # }
4960	/// ```
4961	pub async fn count(&self) -> reinhardt_core::exception::Result<usize> {
4962		use reinhardt_query::prelude::{Func, PostgresQueryBuilder, QueryBuilder};
4963
4964		let conn = super::manager::get_connection().await?;
4965
4966		// Build COUNT query using reinhardt-query
4967		let mut stmt = Query::select();
4968		stmt.from(Alias::new(T::table_name()))
4969			.expr(Func::count(Expr::asterisk().into_simple_expr()));
4970
4971		// Add WHERE conditions
4972		if let Some(cond) = self.build_where_condition()? {
4973			stmt.cond_where(cond);
4974		}
4975
4976		// Convert to SQL and extract parameter values
4977		let (sql, values) = PostgresQueryBuilder.build_select(&stmt);
4978
4979		// Convert reinhardt_query::value::Values to QueryValue
4980		let params = super::execution::convert_values(values);
4981
4982		// Execute query with parameters
4983		let rows = conn.query(&sql, params).await?;
4984		if let Some(row) = rows.first() {
4985			// Extract count from first row
4986			if let Some(count_value) = row.data.get("count")
4987				&& let Some(count) = count_value.as_i64()
4988			{
4989				return Ok(count as usize);
4990			}
4991		}
4992
4993		Ok(0)
4994	}
4995
4996	/// Check if any records match the queryset
4997	///
4998	/// More efficient than calling `count().await? > 0` as it can short-circuit.
4999	///
5000	/// # Examples
5001	///
5002	/// ```no_run
5003	/// # use reinhardt_db::orm::Model;
5004	/// # use reinhardt_db::orm::{Filter, FilterOperator, FilterValue};
5005	/// # use serde::{Serialize, Deserialize};
5006	/// # #[derive(Clone, Serialize, Deserialize)]
5007	/// # struct User { id: Option<i64> }
5008	/// # #[derive(Clone)]
5009	/// # struct UserFields;
5010	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
5011	/// #     fn with_alias(self, _alias: &str) -> Self { self }
5012	/// # }
5013	/// # impl Model for User {
5014	/// #     type PrimaryKey = i64;
5015	/// #     type Fields = UserFields;
5016	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
5017	/// #     fn table_name() -> &'static str { "users" }
5018	/// #     fn new_fields() -> Self::Fields { UserFields }
5019	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
5020	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
5021	/// # }
5022	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
5023	/// // Check if any admin users exist
5024	/// let has_admin = User::objects()
5025	///     .filter(Filter::new(
5026	///         "role",
5027	///         FilterOperator::Eq,
5028	///         FilterValue::String("admin".to_string()),
5029	///     ))
5030	///     .exists()
5031	///     .await?;
5032	///
5033	/// if has_admin {
5034	///     println!("Admin users exist");
5035	/// }
5036	/// # Ok(())
5037	/// # }
5038	/// ```
5039	pub async fn exists(&self) -> reinhardt_core::exception::Result<bool> {
5040		let count = self.count().await?;
5041		Ok(count > 0)
5042	}
5043
5044	/// Create a new object in the database
5045	///
5046	/// # Examples
5047	///
5048	/// ```no_run
5049	/// # use reinhardt_db::orm::Model;
5050	/// # use serde::{Serialize, Deserialize};
5051	/// # #[derive(Clone, Serialize, Deserialize)]
5052	/// # struct User { id: Option<i64>, username: String, email: String }
5053	/// # #[derive(Clone)]
5054	/// # struct UserFields;
5055	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
5056	/// #     fn with_alias(self, _alias: &str) -> Self { self }
5057	/// # }
5058	/// # impl Model for User {
5059	/// #     type PrimaryKey = i64;
5060	/// #     type Fields = UserFields;
5061	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
5062	/// #     fn table_name() -> &'static str { "users" }
5063	/// #     fn new_fields() -> Self::Fields { UserFields }
5064	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
5065	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
5066	/// # }
5067	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
5068	/// let user = User {
5069	///     id: None,
5070	///     username: "alice".to_string(),
5071	///     email: "alice@example.com".to_string(),
5072	/// };
5073	/// let created = User::objects().create(&user).await?;
5074	/// # Ok(())
5075	/// # }
5076	/// ```
5077	pub async fn create(&self, object: T) -> reinhardt_core::exception::Result<T>
5078	where
5079		T: super::Model + Clone,
5080	{
5081		// Delegate to Manager::create() which handles all the SQL generation,
5082		// database connection, primary key retrieval, and error handling
5083		match &self.manager {
5084			Some(manager) => manager.create(&object).await,
5085			None => {
5086				// Fallback: create a new manager instance if none exists
5087				let manager = super::manager::Manager::<T>::new();
5088				manager.create(&object).await
5089			}
5090		}
5091	}
5092
5093	/// Generate UPDATE statement using reinhardt-query
5094	pub fn update_query(
5095		&self,
5096		updates: &HashMap<String, UpdateValue>,
5097	) -> reinhardt_query::prelude::UpdateStatement {
5098		let mut stmt = Query::update();
5099		stmt.table(Alias::new(T::table_name()));
5100
5101		// Add SET clauses
5102		for (field, value) in updates {
5103			stmt.value_expr(Alias::new(field), Self::update_value_to_query_expr(value));
5104		}
5105
5106		// Add WHERE conditions
5107		if let Some(cond) = self.build_where_condition_or_false() {
5108			stmt.cond_where(cond);
5109		}
5110
5111		stmt.to_owned()
5112	}
5113
5114	/// Generate an UPDATE statement for field assignments on rows matched by this `QuerySet`.
5115	///
5116	/// Unlike [`QuerySet::update_query`], this public partial-update builder validates
5117	/// that at least one restricting predicate is present so callers cannot
5118	/// accidentally update every row in the model table. Empty `AND` and empty
5119	/// `NOT IN` collections compile to `TRUE` and are rejected.
5120	pub fn update_fields_query<I, A>(
5121		&self,
5122		values: I,
5123	) -> reinhardt_core::exception::Result<UpdateStatement>
5124	where
5125		I: IntoIterator<Item = A>,
5126		A: Into<FieldAssignment>,
5127	{
5128		let assignments = Self::collect_field_assignments(values);
5129		self.update_fields_query_from_assignments(&assignments)
5130	}
5131
5132	/// Generate PostgreSQL UPDATE SQL for field assignments on this `QuerySet`.
5133	///
5134	/// This mirrors [`QuerySet::update_sql`] for tests and custom SQL inspection.
5135	/// Use [`QuerySet::update_fields`] to execute the update against the configured
5136	/// database backend.
5137	pub fn update_fields_sql<I, A>(
5138		&self,
5139		values: I,
5140	) -> reinhardt_core::exception::Result<(String, Vec<String>)>
5141	where
5142		I: IntoIterator<Item = A>,
5143		A: Into<FieldAssignment>,
5144	{
5145		let stmt = self.update_fields_query(values)?;
5146		let (sql, values) = PostgresQueryBuilder.build_update(&stmt);
5147		let params = values
5148			.iter()
5149			.map(|value| Self::sea_value_to_string(value))
5150			.collect();
5151		Ok((sql, params))
5152	}
5153
5154	/// Update fields for rows matched by this `QuerySet` and return the affected row count.
5155	///
5156	/// The generated `UPDATE` preserves every filter, composite condition, and
5157	/// subquery predicate already attached to the `QuerySet`.
5158	pub async fn update_fields<I, A>(self, values: I) -> reinhardt_core::exception::Result<u64>
5159	where
5160		I: IntoIterator<Item = A>,
5161		A: Into<FieldAssignment>,
5162	{
5163		let conn = super::manager::get_connection().await?;
5164		self.update_fields_with_conn(&conn, values).await
5165	}
5166
5167	/// Update fields using an explicit database connection.
5168	pub async fn update_fields_with_conn<I, A>(
5169		&self,
5170		conn: &super::connection::DatabaseConnection,
5171		values: I,
5172	) -> reinhardt_core::exception::Result<u64>
5173	where
5174		I: IntoIterator<Item = A>,
5175		A: Into<FieldAssignment>,
5176	{
5177		let stmt = self.update_fields_query(values)?;
5178		let (sql, values) = Self::build_update_for_backend(&stmt, conn.backend());
5179		let params = super::execution::convert_values(values);
5180
5181		conn.execute(&sql, params)
5182			.await
5183			.map_err(|error| reinhardt_core::exception::Error::Database(error.to_string()))
5184	}
5185
5186	fn collect_field_assignments<I, A>(values: I) -> Vec<FieldAssignment>
5187	where
5188		I: IntoIterator<Item = A>,
5189		A: Into<FieldAssignment>,
5190	{
5191		values.into_iter().map(Into::into).collect()
5192	}
5193
5194	fn update_fields_query_from_assignments(
5195		&self,
5196		assignments: &[FieldAssignment],
5197	) -> reinhardt_core::exception::Result<UpdateStatement> {
5198		Self::validate_update_fields(assignments)?;
5199
5200		if !self.has_restricting_where_predicates() {
5201			let message = if self.has_where_predicates() {
5202				"QuerySet::update_fields requires at least one non-empty filter predicate"
5203			} else {
5204				"QuerySet::update_fields requires at least one filter predicate"
5205			};
5206			return Err(reinhardt_core::exception::Error::Validation(
5207				message.to_string(),
5208			));
5209		}
5210
5211		let condition = self.build_where_condition()?.ok_or_else(|| {
5212			reinhardt_core::exception::Error::Validation(
5213				"QuerySet::update_fields requires at least one non-empty filter predicate"
5214					.to_string(),
5215			)
5216		})?;
5217
5218		let mut stmt = Query::update();
5219		stmt.table(Alias::new(T::table_name()));
5220
5221		for assignment in assignments {
5222			stmt.value_expr(
5223				Alias::new(assignment.field()),
5224				Self::update_value_to_query_expr(assignment.value()),
5225			);
5226		}
5227
5228		stmt.cond_where(condition);
5229
5230		Ok(stmt.to_owned())
5231	}
5232
5233	fn validate_update_fields(
5234		assignments: &[FieldAssignment],
5235	) -> reinhardt_core::exception::Result<()> {
5236		if assignments.is_empty() {
5237			return Err(reinhardt_core::exception::Error::Validation(
5238				"QuerySet::update_fields requires at least one field assignment".to_string(),
5239			));
5240		}
5241
5242		if assignments
5243			.iter()
5244			.any(|assignment| assignment.field().trim().is_empty())
5245		{
5246			return Err(reinhardt_core::exception::Error::Validation(
5247				"QuerySet::update_fields field names must not be empty".to_string(),
5248			));
5249		}
5250
5251		Ok(())
5252	}
5253
5254	fn build_update_for_backend(
5255		stmt: &UpdateStatement,
5256		backend: super::connection::DatabaseBackend,
5257	) -> (String, reinhardt_query::prelude::Values) {
5258		match backend {
5259			super::connection::DatabaseBackend::Postgres => PostgresQueryBuilder.build_update(stmt),
5260			super::connection::DatabaseBackend::MySql => MySqlQueryBuilder.build_update(stmt),
5261			super::connection::DatabaseBackend::Sqlite => SqliteQueryBuilder.build_update(stmt),
5262		}
5263	}
5264
5265	fn update_value_to_query_expr(value: &UpdateValue) -> Expr {
5266		match value {
5267			UpdateValue::String(s) => Expr::val(s.clone()),
5268			UpdateValue::Integer(i) => Expr::val(*i),
5269			UpdateValue::Float(f) => Expr::val(*f),
5270			UpdateValue::Boolean(b) => Expr::val(*b),
5271			UpdateValue::Null => Expr::cust("NULL"),
5272			UpdateValue::Timestamp(dt) => Expr::val(
5273				reinhardt_query::value::Value::ChronoDateTimeUtc(Some(Box::new(*dt))),
5274			),
5275			UpdateValue::Uuid(uuid) => {
5276				Expr::val(reinhardt_query::value::Value::Uuid(Some(Box::new(*uuid))))
5277			}
5278			UpdateValue::FieldRef(f) => Expr::col(Alias::new(&f.field)),
5279			UpdateValue::Expression(expr) => Self::expression_to_query_expr(expr),
5280		}
5281	}
5282
5283	/// Generate UPDATE SQL with WHERE clause and parameter binding
5284	///
5285	/// Returns SQL with placeholders ($1, $2, etc.) and the values to bind.
5286	///
5287	/// # Examples
5288	///
5289	/// ```no_run
5290	/// # use reinhardt_db::orm::Model;
5291	/// # use reinhardt_db::orm::{Filter, FilterOperator, FilterValue};
5292	/// # use reinhardt_db::orm::query::UpdateValue;
5293	/// # use serde::{Serialize, Deserialize};
5294	/// # #[derive(Clone, Serialize, Deserialize)]
5295	/// # struct User { id: Option<i64> }
5296	/// # #[derive(Clone)]
5297	/// # struct UserFields;
5298	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
5299	/// #     fn with_alias(self, _alias: &str) -> Self { self }
5300	/// # }
5301	/// # impl Model for User {
5302	/// #     type PrimaryKey = i64;
5303	/// #     type Fields = UserFields;
5304	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
5305	/// #     fn table_name() -> &'static str { "users" }
5306	/// #     fn new_fields() -> Self::Fields { UserFields }
5307	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
5308	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
5309	/// # }
5310	/// use std::collections::HashMap;
5311	/// let queryset = User::objects()
5312	///     .filter(Filter::new("id", FilterOperator::Eq, FilterValue::Integer(1)));
5313	///
5314	/// let mut updates = HashMap::new();
5315	/// updates.insert("name".to_string(), UpdateValue::String("Alice".to_string()));
5316	/// updates.insert("email".to_string(), UpdateValue::String("alice@example.com".to_string()));
5317	/// let (sql, params) = queryset.update_sql(&updates);
5318	/// // sql: "UPDATE users SET name = $1, email = $2 WHERE id = $3"
5319	/// // params: ["Alice", "alice@example.com", "1"]
5320	/// ```
5321	pub fn update_sql(&self, updates: &HashMap<String, UpdateValue>) -> (String, Vec<String>) {
5322		let stmt = self.update_query(updates);
5323		use reinhardt_query::prelude::{PostgresQueryBuilder, QueryBuilder};
5324		let (sql, values) = PostgresQueryBuilder.build_update(&stmt);
5325		let params: Vec<String> = values
5326			.iter()
5327			.map(|v| Self::sea_value_to_string(v))
5328			.collect();
5329		(sql, params)
5330	}
5331
5332	/// Convert reinhardt-query Value to String without SQL quoting
5333	fn sea_value_to_string(value: &reinhardt_query::value::Value) -> String {
5334		use reinhardt_query::value::Value;
5335		match value {
5336			Value::Bool(Some(b)) => b.to_string(),
5337			Value::TinyInt(Some(i)) => i.to_string(),
5338			Value::SmallInt(Some(i)) => i.to_string(),
5339			Value::Int(Some(i)) => i.to_string(),
5340			Value::BigInt(Some(i)) => i.to_string(),
5341			Value::TinyUnsigned(Some(i)) => i.to_string(),
5342			Value::SmallUnsigned(Some(i)) => i.to_string(),
5343			Value::Unsigned(Some(i)) => i.to_string(),
5344			Value::BigUnsigned(Some(i)) => i.to_string(),
5345			Value::Float(Some(f)) => f.to_string(),
5346			Value::Double(Some(f)) => f.to_string(),
5347			Value::String(Some(s)) => s.to_string(),
5348			Value::Bytes(Some(b)) => String::from_utf8_lossy(b).to_string(),
5349			Value::ChronoDateTimeUtc(Some(dt)) => dt.to_rfc3339(),
5350			Value::Uuid(Some(uuid)) => uuid.to_string(),
5351			_ => String::new(),
5352		}
5353	}
5354
5355	/// Generate DELETE SQL with WHERE clause and parameter binding
5356	///
5357	/// Returns SQL with placeholders ($1, $2, etc.) and the values to bind.
5358	///
5359	/// # Safety
5360	///
5361	/// This method will panic if no filters are set, or if every filter is a tautology
5362	/// (for example an empty `AND` or an empty `NOT IN` collection), to prevent
5363	/// accidental deletion of all rows. Always use `.filter()` with a restricting
5364	/// predicate before calling this method.
5365	///
5366	/// # Examples
5367	///
5368	/// ```no_run
5369	/// # use reinhardt_db::orm::Model;
5370	/// # use reinhardt_db::orm::{Filter, FilterOperator, FilterValue};
5371	/// # use serde::{Serialize, Deserialize};
5372	/// # #[derive(Clone, Serialize, Deserialize)]
5373	/// # struct User { id: Option<i64> }
5374	/// # #[derive(Clone)]
5375	/// # struct UserFields;
5376	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
5377	/// #     fn with_alias(self, _alias: &str) -> Self { self }
5378	/// # }
5379	/// # impl Model for User {
5380	/// #     type PrimaryKey = i64;
5381	/// #     type Fields = UserFields;
5382	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
5383	/// #     fn table_name() -> &'static str { "users" }
5384	/// #     fn new_fields() -> Self::Fields { UserFields }
5385	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
5386	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
5387	/// # }
5388	/// let queryset = User::objects()
5389	///     .filter(Filter::new("id", FilterOperator::Eq, FilterValue::Integer(1)));
5390	///
5391	/// let (sql, params) = queryset.delete_sql();
5392	/// // sql: "DELETE FROM users WHERE id = $1"
5393	/// // params: ["1"]
5394	/// ```
5395	/// Generate DELETE statement using reinhardt-query
5396	pub fn delete_query(&self) -> reinhardt_query::prelude::DeleteStatement {
5397		if !self.has_restricting_where_predicates() {
5398			panic!(
5399				"DELETE without WHERE clause is not allowed. Use .filter() to specify which rows to delete."
5400			);
5401		}
5402
5403		let Some(cond) = self.build_where_condition_or_false() else {
5404			panic!(
5405				"DELETE without WHERE clause is not allowed. Use .filter() to specify which rows to delete."
5406			);
5407		};
5408
5409		let mut stmt = Query::delete();
5410		stmt.from_table(Alias::new(T::table_name()));
5411		stmt.cond_where(cond);
5412
5413		stmt.to_owned()
5414	}
5415
5416	/// Deletes sql.
5417	pub fn delete_sql(&self) -> (String, Vec<String>) {
5418		let stmt = self.delete_query();
5419		use reinhardt_query::prelude::{PostgresQueryBuilder, QueryBuilder};
5420		let (sql, values) = PostgresQueryBuilder.build_delete(&stmt);
5421		let params: Vec<String> = values
5422			.iter()
5423			.map(|v| Self::sea_value_to_string(v))
5424			.collect();
5425		(sql, params)
5426	}
5427
5428	/// Retrieve a single object by composite primary key
5429	///
5430	/// This method queries the database using all fields that compose the composite primary key.
5431	/// It validates that all required primary key fields are provided and returns the matching record.
5432	///
5433	/// # Examples
5434	///
5435	/// ```no_run
5436	/// # use reinhardt_db::orm::Model;
5437	/// # use reinhardt_db::orm::composite_pk::{CompositePrimaryKey, PkValue};
5438	/// # use serde::{Serialize, Deserialize};
5439	/// # use std::collections::HashMap;
5440	/// # #[derive(Clone, Serialize, Deserialize)]
5441	/// # struct PostTag { post_id: i64, tag_id: i64 }
5442	/// # #[derive(Clone)]
5443	/// # struct PostTagFields;
5444	/// # impl reinhardt_db::orm::model::FieldSelector for PostTagFields {
5445	/// #     fn with_alias(self, _alias: &str) -> Self { self }
5446	/// # }
5447	/// # impl Model for PostTag {
5448	/// #     type PrimaryKey = i64;
5449	/// #     type Fields = PostTagFields;
5450	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
5451	/// #     fn table_name() -> &'static str { "post_tags" }
5452	/// #     fn new_fields() -> Self::Fields { PostTagFields }
5453	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { None }
5454	/// #     fn set_primary_key(&mut self, _value: Self::PrimaryKey) {}
5455	/// #     fn composite_primary_key() -> Option<CompositePrimaryKey> {
5456	/// #         CompositePrimaryKey::new(vec!["post_id".to_string(), "tag_id".to_string()]).ok()
5457	/// #     }
5458	/// # }
5459	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
5460	/// let mut pk_values = HashMap::new();
5461	/// pk_values.insert("post_id".to_string(), PkValue::Int(1));
5462	/// pk_values.insert("tag_id".to_string(), PkValue::Int(5));
5463	///
5464	/// let post_tag = PostTag::objects().get_composite(&pk_values).await?;
5465	/// # Ok(())
5466	/// # }
5467	/// ```
5468	///
5469	/// # Errors
5470	///
5471	/// Returns an error if:
5472	/// - The model doesn't have a composite primary key
5473	/// - Required primary key fields are missing from the provided values
5474	/// - No matching record is found in the database
5475	/// - Multiple records match (should not happen with a valid composite PK)
5476	pub async fn get_composite(
5477		&self,
5478		pk_values: &HashMap<String, super::composite_pk::PkValue>,
5479	) -> reinhardt_core::exception::Result<T>
5480	where
5481		T: super::Model + Clone,
5482	{
5483		use reinhardt_query::prelude::{
5484			Alias, BinOper, ColumnRef, Expr, PostgresQueryBuilder, Value,
5485		};
5486
5487		// Get composite primary key definition from the model
5488		let composite_pk = T::composite_primary_key().ok_or_else(|| {
5489			reinhardt_core::exception::Error::Database(
5490				"Model does not have a composite primary key".to_string(),
5491			)
5492		})?;
5493
5494		// Validate that all required PK fields are provided
5495		composite_pk.validate(pk_values).map_err(|e| {
5496			reinhardt_core::exception::Error::Database(format!(
5497				"Composite PK validation failed: {}",
5498				e
5499			))
5500		})?;
5501
5502		// Build SELECT query using reinhardt-query
5503		let table_name = T::table_name();
5504		let mut query = Query::select();
5505
5506		// Use Alias::new for table name
5507		let table_alias = Alias::new(table_name);
5508		query.from(table_alias).column(ColumnRef::Asterisk);
5509
5510		// Add WHERE conditions for each composite PK field
5511		for field_name in composite_pk.fields() {
5512			let pk_value: &super::composite_pk::PkValue = pk_values.get(field_name).unwrap();
5513			let col_alias = Alias::new(field_name);
5514
5515			match pk_value {
5516				&super::composite_pk::PkValue::Int(v) => {
5517					let condition = Expr::col(col_alias)
5518						.binary(BinOper::Equal, Expr::value(Value::BigInt(Some(v))));
5519					query.and_where(condition);
5520				}
5521				&super::composite_pk::PkValue::Uint(v) => {
5522					let condition = Expr::col(col_alias)
5523						.binary(BinOper::Equal, Expr::value(Value::BigInt(Some(v as i64))));
5524					query.and_where(condition);
5525				}
5526				super::composite_pk::PkValue::String(v) => {
5527					let condition = Expr::col(col_alias).binary(
5528						BinOper::Equal,
5529						Expr::value(Value::String(Some(Box::new(v.clone())))),
5530					);
5531					query.and_where(condition);
5532				}
5533				&super::composite_pk::PkValue::Bool(v) => {
5534					let condition = Expr::col(col_alias)
5535						.binary(BinOper::Equal, Expr::value(Value::Bool(Some(v))));
5536					query.and_where(condition);
5537				}
5538			}
5539		}
5540
5541		// Build SQL with inline values (no placeholders)
5542		let sql = query.to_string(PostgresQueryBuilder);
5543
5544		// Execute query using database connection
5545		let conn = super::manager::get_connection().await?;
5546
5547		// Execute the SELECT query
5548		let rows = conn.query(&sql, vec![]).await?;
5549
5550		// Composite PK queries should return exactly one row
5551		if rows.is_empty() {
5552			return Err(reinhardt_core::exception::Error::Database(
5553				"No record found matching the composite primary key".to_string(),
5554			));
5555		}
5556
5557		if rows.len() > 1 {
5558			return Err(reinhardt_core::exception::Error::Database(format!(
5559				"Multiple records found ({}) for composite primary key, expected exactly one",
5560				rows.len()
5561			)));
5562		}
5563
5564		// Deserialize the single row into the model
5565		let row = &rows[0];
5566		let value = serde_json::to_value(&row.data).map_err(|e| {
5567			reinhardt_core::exception::Error::Database(format!("Serialization error: {}", e))
5568		})?;
5569
5570		serde_json::from_value(value).map_err(|e| {
5571			reinhardt_core::exception::Error::Database(format!("Deserialization error: {}", e))
5572		})
5573	}
5574
5575	/// Add an annotation to the QuerySet
5576	///
5577	/// Annotations allow you to add calculated fields to query results using expressions,
5578	/// aggregations, or subqueries. The annotation will be added to the SELECT clause.
5579	///
5580	/// # Examples
5581	///
5582	/// ```no_run
5583	/// # use reinhardt_db::orm::Model;
5584	/// # use serde::{Serialize, Deserialize};
5585	/// # #[derive(Clone, Serialize, Deserialize)]
5586	/// # struct User { id: Option<i64> }
5587	/// # #[derive(Clone)]
5588	/// # struct UserFields;
5589	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
5590	/// #     fn with_alias(self, _alias: &str) -> Self { self }
5591	/// # }
5592	/// # impl Model for User {
5593	/// #     type PrimaryKey = i64;
5594	/// #     type Fields = UserFields;
5595	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
5596	/// #     fn table_name() -> &'static str { "users" }
5597	/// #     fn new_fields() -> Self::Fields { UserFields }
5598	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
5599	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
5600	/// # }
5601	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
5602	/// use reinhardt_db::orm::annotation::{Annotation, AnnotationValue};
5603	/// use reinhardt_db::orm::aggregation::Aggregate;
5604	///
5605	/// // Add aggregate annotation
5606	/// let users = User::objects()
5607	///     .annotate(Annotation::new("total_orders",
5608	///         AnnotationValue::Aggregate(Aggregate::count(Some("orders")))))
5609	///     .all()
5610	///     .await?;
5611	/// # Ok(())
5612	/// # }
5613	/// ```
5614	pub fn annotate(mut self, annotation: super::annotation::Annotation) -> Self {
5615		self.annotations.push(annotation);
5616		self
5617	}
5618
5619	/// Add a subquery annotation to the QuerySet (SELECT clause subquery)
5620	///
5621	/// This method adds a scalar subquery to the SELECT clause, allowing you to
5622	/// include computed values from related tables without explicit JOINs.
5623	///
5624	/// # Type Parameters
5625	///
5626	/// * `M` - The model type for the subquery
5627	/// * `F` - A closure that builds the subquery
5628	///
5629	/// # Parameters
5630	///
5631	/// * `name` - The alias for the subquery result column
5632	/// * `builder` - A closure that receives a fresh `QuerySet<M>` and returns a configured QuerySet
5633	///
5634	/// # Examples
5635	///
5636	/// ```no_run
5637	/// # use reinhardt_db::orm::Model;
5638	/// # use reinhardt_db::orm::{Filter, FilterOperator, FilterValue};
5639	/// # use reinhardt_db::orm::OuterRef;
5640	/// # use serde::{Serialize, Deserialize};
5641	/// # #[derive(Clone, Serialize, Deserialize)]
5642	/// # struct Author { id: Option<i64> }
5643	/// # #[derive(Clone)]
5644	/// # struct AuthorFields;
5645	/// # impl reinhardt_db::orm::model::FieldSelector for AuthorFields {
5646	/// #     fn with_alias(self, _alias: &str) -> Self { self }
5647	/// # }
5648	/// # impl Model for Author {
5649	/// #     type PrimaryKey = i64;
5650	/// #     type Fields = AuthorFields;
5651	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
5652	/// #     fn table_name() -> &'static str { "authors" }
5653	/// #     fn new_fields() -> Self::Fields { AuthorFields }
5654	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
5655	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
5656	/// # }
5657	/// # #[derive(Clone, Serialize, Deserialize)]
5658	/// # struct Book { id: Option<i64> }
5659	/// # #[derive(Clone)]
5660	/// # struct BookFields;
5661	/// # impl reinhardt_db::orm::model::FieldSelector for BookFields {
5662	/// #     fn with_alias(self, _alias: &str) -> Self { self }
5663	/// # }
5664	/// # impl Model for Book {
5665	/// #     type PrimaryKey = i64;
5666	/// #     type Fields = BookFields;
5667	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
5668	/// #     fn table_name() -> &'static str { "books" }
5669	/// #     fn new_fields() -> Self::Fields { BookFields }
5670	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
5671	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
5672	/// # }
5673	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
5674	/// // Add book count for each author
5675	/// let authors = Author::objects()
5676	///     .annotate_subquery::<Book, _>("book_count", |subq| {
5677	///         subq.filter(Filter::new(
5678	///             "author_id",
5679	///             FilterOperator::Eq,
5680	///             FilterValue::OuterRef(OuterRef::new("authors.id"))
5681	///         ))
5682	///         .values(&["COUNT(*)"])
5683	///     })
5684	///     .all()
5685	///     .await?;
5686	/// // Generates: SELECT *, (SELECT COUNT(*) FROM books WHERE author_id = authors.id) AS book_count FROM authors
5687	/// # Ok(())
5688	/// # }
5689	/// ```
5690	pub fn annotate_subquery<M, F>(mut self, name: &str, builder: F) -> Self
5691	where
5692		M: super::Model + 'static,
5693		F: FnOnce(QuerySet<M>) -> QuerySet<M>,
5694	{
5695		// Create a fresh QuerySet for the subquery model
5696		let subquery_qs = QuerySet::<M>::new();
5697		// Apply the builder to configure the subquery
5698		let configured_subquery = builder(subquery_qs);
5699		// Generate SQL for the subquery (wrapped in parentheses)
5700		let subquery_sql = configured_subquery.as_subquery();
5701
5702		// Add as annotation using AnnotationValue::Subquery
5703		let annotation = super::annotation::Annotation {
5704			alias: name.to_string(),
5705			value: super::annotation::AnnotationValue::Subquery(subquery_sql),
5706		};
5707		self.annotations.push(annotation);
5708		self
5709	}
5710
5711	/// Perform an aggregation on the QuerySet
5712	///
5713	/// Aggregations allow you to calculate summary statistics (COUNT, SUM, AVG, MAX, MIN)
5714	/// for the queryset. The aggregation result will be added to the SELECT clause.
5715	///
5716	/// # Examples
5717	///
5718	/// ```no_run
5719	/// # use reinhardt_db::orm::Model;
5720	/// # use serde::{Serialize, Deserialize};
5721	/// # #[derive(Serialize, Deserialize, Clone)]
5722	/// # struct User { id: Option<i64> }
5723	/// # #[derive(Clone)]
5724	/// # struct UserFields;
5725	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
5726	/// #     fn with_alias(self, _alias: &str) -> Self { self }
5727	/// # }
5728	/// # impl Model for User {
5729	/// #     type PrimaryKey = i64;
5730	/// #     type Fields = UserFields;
5731	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
5732	/// #     fn table_name() -> &'static str { "users" }
5733	/// #     fn new_fields() -> Self::Fields { UserFields }
5734	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
5735	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
5736	/// # }
5737	/// # #[derive(Serialize, Deserialize, Clone)]
5738	/// # struct Order { id: Option<i64> }
5739	/// # #[derive(Clone)]
5740	/// # struct OrderFields;
5741	/// # impl reinhardt_db::orm::model::FieldSelector for OrderFields {
5742	/// #     fn with_alias(self, _alias: &str) -> Self { self }
5743	/// # }
5744	/// # impl Model for Order {
5745	/// #     type PrimaryKey = i64;
5746	/// #     type Fields = OrderFields;
5747	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
5748	/// #     fn table_name() -> &'static str { "orders" }
5749	/// #     fn new_fields() -> Self::Fields { OrderFields }
5750	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
5751	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
5752	/// # }
5753	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
5754	/// use reinhardt_db::orm::aggregation::Aggregate;
5755	///
5756	/// // Count all users
5757	/// let result = User::objects()
5758	///     .all()
5759	///     .aggregate(Aggregate::count_all().with_alias("total_users"))
5760	///     .all()
5761	///     .await?;
5762	///
5763	/// // Sum order amounts
5764	/// let result = Order::objects()
5765	///     .all()
5766	///     .aggregate(Aggregate::sum("amount").with_alias("total_amount"))
5767	///     .all()
5768	///     .await?;
5769	/// # Ok(())
5770	/// # }
5771	/// ```
5772	pub fn aggregate(mut self, aggregate: super::aggregation::Aggregate) -> Self {
5773		// Convert Aggregate to Annotation and add to annotations list
5774		let alias = aggregate
5775			.alias
5776			.clone()
5777			.unwrap_or_else(|| aggregate.func.to_string().to_lowercase());
5778		let annotation = super::annotation::Annotation {
5779			alias,
5780			value: super::annotation::AnnotationValue::Aggregate(aggregate),
5781		};
5782		self.annotations.push(annotation);
5783		self
5784	}
5785
5786	/// Converts to sql.
5787	pub fn to_sql(&self) -> String {
5788		let mut stmt = if self.select_related_fields.is_empty() {
5789			// Simple SELECT without JOINs
5790			let mut stmt = Query::select();
5791
5792			// Apply FROM clause with optional alias
5793			if let Some(ref alias) = self.from_alias {
5794				stmt.from_as(Alias::new(T::table_name()), Alias::new(alias));
5795			} else {
5796				stmt.from(Alias::new(T::table_name()));
5797			}
5798
5799			// Apply DISTINCT if enabled
5800			if self.distinct_enabled {
5801				stmt.distinct();
5802			}
5803
5804			// Column selection considering selected_fields and deferred_fields
5805			if let Some(ref fields) = self.selected_fields {
5806				for field in fields {
5807					// Detect raw SQL expressions (like COUNT(*), AVG(price), etc.)
5808					if field.contains('(') && field.contains(')') {
5809						// Use expr() for raw SQL expressions - clone to satisfy lifetime
5810						stmt.expr(Expr::cust(field.clone()));
5811					} else {
5812						// Regular column reference
5813						let col_ref = parse_column_reference(field);
5814						stmt.column(col_ref);
5815					}
5816				}
5817			} else if !self.deferred_fields.is_empty() {
5818				let all_fields = T::field_metadata();
5819				for field in all_fields {
5820					if !self.deferred_fields.contains(&field.name) {
5821						let col_ref = parse_column_reference(&field.name);
5822						stmt.column(col_ref);
5823					}
5824				}
5825			} else {
5826				stmt.column(ColumnRef::Asterisk);
5827			}
5828
5829			// Apply JOINs
5830			for join in &self.joins {
5831				if join.on_condition.is_empty() {
5832					// CROSS JOIN (no ON condition)
5833					if let Some(ref alias) = join.target_alias {
5834						// CROSS JOIN with alias - reinhardt-query doesn't support this directly
5835						// Use regular join syntax instead
5836						stmt.cross_join((Alias::new(&join.target_table), Alias::new(alias)));
5837					} else {
5838						stmt.cross_join(Alias::new(&join.target_table));
5839					}
5840				} else {
5841					// Convert reinhardt JoinType to reinhardt-query JoinType
5842					let sea_join_type = match join.join_type {
5843						super::sqlalchemy_query::JoinType::Inner => SeaJoinType::InnerJoin,
5844						super::sqlalchemy_query::JoinType::Left => SeaJoinType::LeftJoin,
5845						super::sqlalchemy_query::JoinType::Right => SeaJoinType::RightJoin,
5846						super::sqlalchemy_query::JoinType::Full => SeaJoinType::FullOuterJoin,
5847					};
5848
5849					// Build the join with optional alias
5850					if let Some(ref alias) = join.target_alias {
5851						// JOIN with alias: (table, alias)
5852						stmt.join(
5853							sea_join_type,
5854							(Alias::new(&join.target_table), Alias::new(alias)),
5855							Expr::cust(join.on_condition.clone()),
5856						);
5857					} else {
5858						// JOIN without alias
5859						stmt.join(
5860							sea_join_type,
5861							Alias::new(&join.target_table),
5862							Expr::cust(join.on_condition.clone()),
5863						);
5864					}
5865				}
5866			}
5867
5868			// Apply WHERE conditions
5869			if let Some(cond) = self.build_where_condition_or_false() {
5870				stmt.cond_where(cond);
5871			}
5872
5873			// Apply GROUP BY
5874			for group_field in &self.group_by_fields {
5875				stmt.group_by_col(Alias::new(group_field));
5876			}
5877
5878			// Apply HAVING
5879			for having_cond in &self.having_conditions {
5880				match having_cond {
5881					HavingCondition::AggregateCompare {
5882						func,
5883						field,
5884						operator,
5885						value,
5886					} => {
5887						// Build aggregate function expression
5888						let agg_expr = match func {
5889							AggregateFunc::Avg => {
5890								Func::avg(Expr::col(Alias::new(field)).into_simple_expr())
5891							}
5892							AggregateFunc::Count => {
5893								if field == "*" {
5894									Func::count(Expr::asterisk().into_simple_expr())
5895								} else {
5896									Func::count(Expr::col(Alias::new(field)).into_simple_expr())
5897								}
5898							}
5899							AggregateFunc::Sum => {
5900								Func::sum(Expr::col(Alias::new(field)).into_simple_expr())
5901							}
5902							AggregateFunc::Min => {
5903								Func::min(Expr::col(Alias::new(field)).into_simple_expr())
5904							}
5905							AggregateFunc::Max => {
5906								Func::max(Expr::col(Alias::new(field)).into_simple_expr())
5907							}
5908						};
5909
5910						// Build comparison expression
5911						let having_expr = match operator {
5912							ComparisonOp::Eq => match value {
5913								AggregateValue::Int(v) => agg_expr.eq(*v),
5914								AggregateValue::Float(v) => agg_expr.eq(*v),
5915							},
5916							ComparisonOp::Ne => match value {
5917								AggregateValue::Int(v) => agg_expr.ne(*v),
5918								AggregateValue::Float(v) => agg_expr.ne(*v),
5919							},
5920							ComparisonOp::Gt => match value {
5921								AggregateValue::Int(v) => agg_expr.gt(*v),
5922								AggregateValue::Float(v) => agg_expr.gt(*v),
5923							},
5924							ComparisonOp::Gte => match value {
5925								AggregateValue::Int(v) => agg_expr.gte(*v),
5926								AggregateValue::Float(v) => agg_expr.gte(*v),
5927							},
5928							ComparisonOp::Lt => match value {
5929								AggregateValue::Int(v) => agg_expr.lt(*v),
5930								AggregateValue::Float(v) => agg_expr.lt(*v),
5931							},
5932							ComparisonOp::Lte => match value {
5933								AggregateValue::Int(v) => agg_expr.lte(*v),
5934								AggregateValue::Float(v) => agg_expr.lte(*v),
5935							},
5936						};
5937
5938						stmt.and_having(having_expr);
5939					}
5940				}
5941			}
5942
5943			// Apply ORDER BY
5944			for order_field in &self.order_by_fields {
5945				let (field, is_desc) = if let Some(stripped) = order_field.strip_prefix('-') {
5946					(stripped, true)
5947				} else {
5948					(order_field.as_str(), false)
5949				};
5950
5951				let col_ref = parse_column_reference(field);
5952				let expr = Expr::col(col_ref);
5953				if is_desc {
5954					stmt.order_by_expr(expr, Order::Desc);
5955				} else {
5956					stmt.order_by_expr(expr, Order::Asc);
5957				}
5958			}
5959
5960			// Apply LIMIT/OFFSET
5961			if let Some(limit) = self.limit {
5962				stmt.limit(limit as u64);
5963			}
5964			if let Some(offset) = self.offset {
5965				stmt.offset(offset as u64);
5966			}
5967
5968			stmt.to_owned()
5969		} else {
5970			// SELECT with JOINs for select_related
5971			self.select_related_query()
5972		};
5973
5974		// Add annotations to SELECT clause if any using reinhardt-query API
5975		// Collect annotation SQL strings first to handle lifetime issues
5976		// Note: Use to_sql_expr() to get expression without alias (reinhardt-query adds alias via expr_as)
5977		let annotation_exprs: Vec<_> = self
5978			.annotations
5979			.iter()
5980			.map(|a| (a.value.to_sql_expr(), a.alias.clone()))
5981			.collect();
5982
5983		for (value_sql, alias) in annotation_exprs {
5984			stmt.expr_as(Expr::cust(value_sql), Alias::new(alias));
5985		}
5986
5987		use reinhardt_query::prelude::PostgresQueryBuilder;
5988		let mut select_sql = stmt.to_string(PostgresQueryBuilder);
5989
5990		// Insert LATERAL JOIN clauses after FROM clause
5991		if !self.lateral_joins.is_empty() {
5992			let lateral_sql = self.lateral_joins.to_sql().join(" ");
5993
5994			// Find insertion point: after FROM clause, before WHERE/ORDER BY/LIMIT
5995			// Look for WHERE, ORDER BY, or end of string
5996			let insert_pos = select_sql
5997				.find(" WHERE ")
5998				.or_else(|| select_sql.find(" ORDER BY "))
5999				.or_else(|| select_sql.find(" LIMIT "))
6000				.unwrap_or(select_sql.len());
6001
6002			select_sql.insert_str(insert_pos, &format!(" {}", lateral_sql));
6003		}
6004
6005		// Replace FROM table with FROM subquery if from_subquery_sql is set
6006		if let Some(ref subquery_sql) = self.from_subquery_sql
6007			&& let Some(ref alias) = self.from_alias
6008		{
6009			// Pattern: FROM "table_name" AS "alias" or FROM "table_name"
6010			let from_pattern_with_alias = format!("FROM \"{}\" AS \"{}\"", T::table_name(), alias);
6011			let from_pattern_simple = format!("FROM \"{}\"", T::table_name());
6012
6013			let from_replacement = format!("FROM {} AS \"{}\"", subquery_sql, alias);
6014
6015			// Try to replace with alias pattern first, then simple pattern
6016			if select_sql.contains(&from_pattern_with_alias) {
6017				select_sql = select_sql.replace(&from_pattern_with_alias, &from_replacement);
6018			} else if select_sql.contains(&from_pattern_simple) {
6019				select_sql = select_sql.replace(&from_pattern_simple, &from_replacement);
6020			}
6021		}
6022
6023		// Prepend CTE clause if any CTEs are defined
6024		if let Some(cte_sql) = self.ctes.to_sql() {
6025			format!("{} {}", cte_sql, select_sql)
6026		} else {
6027			select_sql
6028		}
6029	}
6030
6031	/// Select specific values from the QuerySet
6032	///
6033	/// Returns only the specified fields instead of all columns.
6034	/// Useful for optimizing queries when you don't need all model fields.
6035	///
6036	/// # Examples
6037	///
6038	/// ```no_run
6039	/// # use reinhardt_db::orm::Model;
6040	/// # use reinhardt_db::orm::{Filter, FilterOperator, FilterValue};
6041	/// # use serde::{Serialize, Deserialize};
6042	/// # #[derive(Clone, Serialize, Deserialize)]
6043	/// # struct User { id: Option<i64> }
6044	/// # #[derive(Clone)]
6045	/// # struct UserFields;
6046	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
6047	/// #     fn with_alias(self, _alias: &str) -> Self { self }
6048	/// # }
6049	/// # impl Model for User {
6050	/// #     type PrimaryKey = i64;
6051	/// #     type Fields = UserFields;
6052	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
6053	/// #     fn table_name() -> &'static str { "users" }
6054	/// #     fn new_fields() -> Self::Fields { UserFields }
6055	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
6056	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
6057	/// # }
6058	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
6059	/// // Select only specific fields
6060	/// let users = User::objects()
6061	///     .values(&["id", "username", "email"])
6062	///     .all()
6063	///     .await?;
6064	/// // Generates: SELECT id, username, email FROM users
6065	///
6066	/// // Combine with filters
6067	/// let active_user_names = User::objects()
6068	///     .filter(Filter::new("is_active", FilterOperator::Eq, FilterValue::Boolean(true)))
6069	///     .values(&["username"])
6070	///     .all()
6071	///     .await?;
6072	/// # Ok(())
6073	/// # }
6074	/// ```
6075	pub fn values(mut self, fields: &[&str]) -> Self {
6076		self.selected_fields = Some(fields.iter().map(|s| s.to_string()).collect());
6077		self
6078	}
6079
6080	/// Select specific values as a list
6081	///
6082	/// Alias for `values()` - returns tuple-like results with specified fields.
6083	/// In Django, this returns tuples instead of dictionaries, but in Rust
6084	/// the behavior is the same as `values()` due to type safety.
6085	///
6086	/// # Examples
6087	///
6088	/// ```no_run
6089	/// # use reinhardt_db::orm::Model;
6090	/// # use serde::{Serialize, Deserialize};
6091	/// # #[derive(Clone, Serialize, Deserialize)]
6092	/// # struct User { id: Option<i64> }
6093	/// # #[derive(Clone)]
6094	/// # struct UserFields;
6095	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
6096	/// #     fn with_alias(self, _alias: &str) -> Self { self }
6097	/// # }
6098	/// # impl Model for User {
6099	/// #     type PrimaryKey = i64;
6100	/// #     type Fields = UserFields;
6101	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
6102	/// #     fn table_name() -> &'static str { "users" }
6103	/// #     fn new_fields() -> Self::Fields { UserFields }
6104	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
6105	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
6106	/// # }
6107	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
6108	/// // Same as values()
6109	/// let user_data = User::objects()
6110	///     .values_list(&["id", "username"])
6111	///     .all()
6112	///     .await?;
6113	/// # Ok(())
6114	/// # }
6115	/// ```
6116	pub fn values_list(self, fields: &[&str]) -> Self {
6117		self.values(fields)
6118	}
6119
6120	/// Order the QuerySet by specified fields
6121	///
6122	/// # Examples
6123	///
6124	/// ```no_run
6125	/// # use reinhardt_db::orm::Model;
6126	/// # use serde::{Serialize, Deserialize};
6127	/// # #[derive(Clone, Serialize, Deserialize)]
6128	/// # struct User { id: Option<i64> }
6129	/// # #[derive(Clone)]
6130	/// # struct UserFields;
6131	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
6132	/// #     fn with_alias(self, _alias: &str) -> Self { self }
6133	/// # }
6134	/// # impl Model for User {
6135	/// #     type PrimaryKey = i64;
6136	/// #     type Fields = UserFields;
6137	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
6138	/// #     fn table_name() -> &'static str { "users" }
6139	/// #     fn new_fields() -> Self::Fields { UserFields }
6140	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
6141	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
6142	/// # }
6143	/// # fn example() {
6144	/// // Ascending order
6145	/// User::objects().order_by(&["name"]);
6146	///
6147	/// // Descending order (prefix with '-')
6148	/// User::objects().order_by(&["-created_at"]);
6149	///
6150	/// // Multiple fields
6151	/// User::objects().order_by(&["department", "-salary"]);
6152	/// # }
6153	/// ```
6154	pub fn order_by(mut self, fields: &[&str]) -> Self {
6155		self.order_by_fields = fields.iter().map(|s| s.to_string()).collect();
6156		self
6157	}
6158
6159	/// Return only distinct results
6160	pub fn distinct(mut self) -> Self {
6161		self.distinct_enabled = true;
6162		self
6163	}
6164
6165	/// Clear DISTINCT for a single-row mutation lookup.
6166	pub fn without_distinct(mut self) -> Self {
6167		self.distinct_enabled = false;
6168		self
6169	}
6170
6171	/// Set LIMIT clause
6172	///
6173	/// Limits the number of records returned by the query.
6174	/// Corresponds to Django's QuerySet slicing `[:limit]`.
6175	///
6176	/// # Examples
6177	///
6178	/// ```no_run
6179	/// # use reinhardt_db::orm::Model;
6180	/// # use serde::{Serialize, Deserialize};
6181	/// # #[derive(Clone, Serialize, Deserialize)]
6182	/// # struct User { id: Option<i64> }
6183	/// # #[derive(Clone)]
6184	/// # struct UserFields;
6185	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
6186	/// #     fn with_alias(self, _alias: &str) -> Self { self }
6187	/// # }
6188	/// # impl Model for User {
6189	/// #     type PrimaryKey = i64;
6190	/// #     type Fields = UserFields;
6191	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
6192	/// #     fn table_name() -> &'static str { "users" }
6193	/// #     fn new_fields() -> Self::Fields { UserFields }
6194	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
6195	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
6196	/// # }
6197	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
6198	/// let users = User::objects()
6199	///     .limit(10)
6200	///     .all()
6201	///     .await?;
6202	/// # Ok(())
6203	/// # }
6204	/// ```
6205	pub fn limit(mut self, limit: usize) -> Self {
6206		self.limit = Some(limit);
6207		self
6208	}
6209
6210	/// Set OFFSET clause
6211	///
6212	/// Skips the specified number of records before returning results.
6213	/// Corresponds to Django's QuerySet slicing `[offset:]`.
6214	///
6215	/// # Examples
6216	///
6217	/// ```no_run
6218	/// # use reinhardt_db::orm::Model;
6219	/// # use serde::{Serialize, Deserialize};
6220	/// # #[derive(Clone, Serialize, Deserialize)]
6221	/// # struct User { id: Option<i64> }
6222	/// # #[derive(Clone)]
6223	/// # struct UserFields;
6224	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
6225	/// #     fn with_alias(self, _alias: &str) -> Self { self }
6226	/// # }
6227	/// # impl Model for User {
6228	/// #     type PrimaryKey = i64;
6229	/// #     type Fields = UserFields;
6230	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
6231	/// #     fn table_name() -> &'static str { "users" }
6232	/// #     fn new_fields() -> Self::Fields { UserFields }
6233	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
6234	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
6235	/// # }
6236	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
6237	/// let users = User::objects()
6238	///     .offset(20)
6239	///     .limit(10)
6240	///     .all()
6241	///     .await?;
6242	/// # Ok(())
6243	/// # }
6244	/// ```
6245	pub fn offset(mut self, offset: usize) -> Self {
6246		self.offset = Some(offset);
6247		self
6248	}
6249
6250	/// Remove result slicing before evaluating a detail or mutation query.
6251	pub fn without_slicing(mut self) -> Self {
6252		self.limit = None;
6253		self.offset = None;
6254		self
6255	}
6256
6257	/// Paginate results using page number and page size
6258	///
6259	/// Convenience method that calculates offset automatically.
6260	/// Corresponds to Django REST framework's PageNumberPagination.
6261	///
6262	/// # Examples
6263	///
6264	/// ```no_run
6265	/// # use reinhardt_db::orm::Model;
6266	/// # use serde::{Serialize, Deserialize};
6267	/// # #[derive(Clone, Serialize, Deserialize)]
6268	/// # struct User { id: Option<i64> }
6269	/// # #[derive(Clone)]
6270	/// # struct UserFields;
6271	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
6272	/// #     fn with_alias(self, _alias: &str) -> Self { self }
6273	/// # }
6274	/// # impl Model for User {
6275	/// #     type PrimaryKey = i64;
6276	/// #     type Fields = UserFields;
6277	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
6278	/// #     fn table_name() -> &'static str { "users" }
6279	/// #     fn new_fields() -> Self::Fields { UserFields }
6280	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
6281	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
6282	/// # }
6283	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
6284	/// // Page 3, 10 items per page (offset=20, limit=10)
6285	/// let users = User::objects()
6286	///     .paginate(3, 10)
6287	///     .all()
6288	///     .await?;
6289	/// # Ok(())
6290	/// # }
6291	/// ```
6292	pub fn paginate(self, page: usize, page_size: usize) -> Self {
6293		let offset = page.saturating_sub(1) * page_size;
6294		self.offset(offset).limit(page_size)
6295	}
6296
6297	/// Convert QuerySet to a subquery
6298	///
6299	/// Returns the QuerySet as a SQL subquery wrapped in parentheses,
6300	/// suitable for use in IN clauses, EXISTS clauses, or as a derived table.
6301	///
6302	/// # Examples
6303	///
6304	/// ```no_run
6305	/// # use reinhardt_db::orm::Model;
6306	/// # use reinhardt_db::orm::{Filter, FilterOperator, FilterValue};
6307	/// # use serde::{Serialize, Deserialize};
6308	/// # #[derive(Clone, Serialize, Deserialize)]
6309	/// # struct User { id: Option<i64> }
6310	/// # #[derive(Clone)]
6311	/// # struct UserFields;
6312	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
6313	/// #     fn with_alias(self, _alias: &str) -> Self { self }
6314	/// # }
6315	/// # impl Model for User {
6316	/// #     type PrimaryKey = i64;
6317	/// #     type Fields = UserFields;
6318	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
6319	/// #     fn table_name() -> &'static str { "users" }
6320	/// #     fn new_fields() -> Self::Fields { UserFields }
6321	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
6322	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
6323	/// # }
6324	/// # #[derive(Clone, Serialize, Deserialize)]
6325	/// # struct Post { id: Option<i64> }
6326	/// # #[derive(Clone)]
6327	/// # struct PostFields;
6328	/// # impl reinhardt_db::orm::model::FieldSelector for PostFields {
6329	/// #     fn with_alias(self, _alias: &str) -> Self { self }
6330	/// # }
6331	/// # impl Model for Post {
6332	/// #     type PrimaryKey = i64;
6333	/// #     type Fields = PostFields;
6334	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
6335	/// #     fn table_name() -> &'static str { "posts" }
6336	/// #     fn new_fields() -> Self::Fields { PostFields }
6337	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
6338	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
6339	/// # }
6340	/// // Use in IN clause
6341	/// let active_user_ids = User::objects()
6342	///     .filter(Filter::new("is_active", FilterOperator::Eq, FilterValue::Bool(true)))
6343	///     .values(&["id"])
6344	///     .as_subquery();
6345	/// // Generates: (SELECT id FROM users WHERE is_active = $1)
6346	///
6347	/// // Use as derived table
6348	/// let subquery = Post::objects()
6349	///     .filter(Filter::new("published", FilterOperator::Eq, FilterValue::Bool(true)))
6350	///     .as_subquery();
6351	/// // Generates: (SELECT * FROM posts WHERE published = $1)
6352	/// ```
6353	pub fn as_subquery(self) -> String {
6354		format!("({})", self.to_sql())
6355	}
6356
6357	/// Defer loading of specific fields
6358	///
6359	/// Marks specific fields for deferred loading (lazy loading).
6360	/// The specified fields will be excluded from the initial query.
6361	///
6362	/// # Examples
6363	///
6364	/// ```no_run
6365	/// # use reinhardt_db::orm::Model;
6366	/// # use serde::{Serialize, Deserialize};
6367	/// # #[derive(Clone, Serialize, Deserialize)]
6368	/// # struct User { id: Option<i64>, username: String, email: String }
6369	/// # #[derive(Clone)]
6370	/// # struct UserFields;
6371	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
6372	/// #     fn with_alias(self, _alias: &str) -> Self { self }
6373	/// # }
6374	/// # impl Model for User {
6375	/// #     type PrimaryKey = i64;
6376	/// #     type Fields = UserFields;
6377	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
6378	/// #     fn table_name() -> &'static str { "users" }
6379	/// #     fn new_fields() -> Self::Fields { UserFields }
6380	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
6381	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
6382	/// # }
6383	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
6384	/// // Defer large text fields
6385	/// let users = User::objects()
6386	///     .defer(&["bio", "profile_picture"])
6387	///     .all()
6388	///     .await?;
6389	/// // Generates: SELECT id, username, email FROM users (excluding bio, profile_picture)
6390	/// # Ok(())
6391	/// # }
6392	/// ```
6393	pub fn defer(mut self, fields: &[&str]) -> Self {
6394		self.deferred_fields = fields.iter().map(|s| s.to_string()).collect();
6395		self
6396	}
6397
6398	/// Load only specific fields
6399	///
6400	/// Alias for `values()` - specifies which fields to load immediately.
6401	/// In Django, this is used for deferred loading optimization, but in Rust
6402	/// it behaves the same as `values()`.
6403	///
6404	/// # Examples
6405	///
6406	/// ```no_run
6407	/// # use reinhardt_db::orm::Model;
6408	/// # use serde::{Serialize, Deserialize};
6409	/// # #[derive(Clone, Serialize, Deserialize)]
6410	/// # struct User { id: Option<i64>, username: String }
6411	/// # #[derive(Clone)]
6412	/// # struct UserFields;
6413	/// # impl reinhardt_db::orm::model::FieldSelector for UserFields {
6414	/// #     fn with_alias(self, _alias: &str) -> Self { self }
6415	/// # }
6416	/// # impl Model for User {
6417	/// #     type PrimaryKey = i64;
6418	/// #     type Fields = UserFields;
6419	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
6420	/// #     fn table_name() -> &'static str { "users" }
6421	/// #     fn new_fields() -> Self::Fields { UserFields }
6422	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
6423	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
6424	/// # }
6425	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
6426	/// // Load only specific fields
6427	/// let users = User::objects()
6428	///     .only(&["id", "username"])
6429	///     .all()
6430	///     .await?;
6431	/// // Generates: SELECT id, username FROM users
6432	/// # Ok(())
6433	/// # }
6434	/// ```
6435	pub fn only(self, fields: &[&str]) -> Self {
6436		self.values(fields)
6437	}
6438
6439	// ==================== PostgreSQL-specific convenience methods ====================
6440
6441	/// Filter by PostgreSQL full-text search
6442	///
6443	/// This method adds a filter for full-text search using PostgreSQL's `@@` operator.
6444	/// The query is converted using `plainto_tsquery` for simple word matching.
6445	///
6446	/// # Arguments
6447	///
6448	/// * `field` - The tsvector field to search
6449	/// * `query` - The search query string
6450	///
6451	/// # Examples
6452	///
6453	/// ```no_run
6454	/// # use reinhardt_db::orm::Model;
6455	/// # use serde::{Serialize, Deserialize};
6456	/// # #[derive(Clone, Serialize, Deserialize)]
6457	/// # struct Article { id: Option<i64>, title: String }
6458	/// # #[derive(Clone)]
6459	/// # struct ArticleFields;
6460	/// # impl reinhardt_db::orm::model::FieldSelector for ArticleFields {
6461	/// #     fn with_alias(self, _alias: &str) -> Self { self }
6462	/// # }
6463	/// # impl Model for Article {
6464	/// #     type PrimaryKey = i64;
6465	/// #     type Fields = ArticleFields;
6466	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
6467	/// #     fn table_name() -> &'static str { "articles" }
6468	/// #     fn new_fields() -> Self::Fields { ArticleFields }
6469	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
6470	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
6471	/// # }
6472	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
6473	/// // Search articles for "rust programming"
6474	/// let articles = Article::objects()
6475	///     .full_text_search("search_vector", "rust programming")
6476	///     .all()
6477	///     .await?;
6478	/// // Generates: WHERE search_vector @@ plainto_tsquery('english', 'rust programming')
6479	/// # Ok(())
6480	/// # }
6481	/// ```
6482	pub fn full_text_search(self, field: &str, query: &str) -> Self {
6483		self.filter(Filter::new(
6484			field,
6485			FilterOperator::FullTextMatch,
6486			FilterValue::String(query.to_string()),
6487		))
6488	}
6489
6490	/// Filter by PostgreSQL array overlap
6491	///
6492	/// Returns rows where the array field has at least one element in common with the given values.
6493	///
6494	/// # Arguments
6495	///
6496	/// * `field` - The array field name
6497	/// * `values` - Values to check for overlap
6498	///
6499	/// # Examples
6500	///
6501	/// ```no_run
6502	/// # use reinhardt_db::orm::Model;
6503	/// # use serde::{Serialize, Deserialize};
6504	/// # #[derive(Clone, Serialize, Deserialize)]
6505	/// # struct Post { id: Option<i64>, title: String }
6506	/// # #[derive(Clone)]
6507	/// # struct PostFields;
6508	/// # impl reinhardt_db::orm::model::FieldSelector for PostFields {
6509	/// #     fn with_alias(self, _alias: &str) -> Self { self }
6510	/// # }
6511	/// # impl Model for Post {
6512	/// #     type PrimaryKey = i64;
6513	/// #     type Fields = PostFields;
6514	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
6515	/// #     fn table_name() -> &'static str { "posts" }
6516	/// #     fn new_fields() -> Self::Fields { PostFields }
6517	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
6518	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
6519	/// # }
6520	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
6521	/// // Find posts with any of these tags
6522	/// let posts = Post::objects()
6523	///     .filter_array_overlap("tags", &["rust", "programming"])
6524	///     .all()
6525	///     .await?;
6526	/// // Generates: WHERE tags && ARRAY['rust', 'programming']
6527	/// # Ok(())
6528	/// # }
6529	/// ```
6530	pub fn filter_array_overlap(self, field: &str, values: &[&str]) -> Self {
6531		self.filter(Filter::new(
6532			field,
6533			FilterOperator::ArrayOverlap,
6534			FilterValue::Array(values.iter().map(|s| s.to_string()).collect()),
6535		))
6536	}
6537
6538	/// Filter by PostgreSQL array containment
6539	///
6540	/// Returns rows where the array field contains all the given values.
6541	///
6542	/// # Arguments
6543	///
6544	/// * `field` - The array field name
6545	/// * `values` - Values that must all be present in the array
6546	///
6547	/// # Examples
6548	///
6549	/// ```no_run
6550	/// # use reinhardt_db::orm::Model;
6551	/// # use serde::{Serialize, Deserialize};
6552	/// # #[derive(Clone, Serialize, Deserialize)]
6553	/// # struct Post { id: Option<i64>, title: String }
6554	/// # #[derive(Clone)]
6555	/// # struct PostFields;
6556	/// # impl reinhardt_db::orm::model::FieldSelector for PostFields {
6557	/// #     fn with_alias(self, _alias: &str) -> Self { self }
6558	/// # }
6559	/// # impl Model for Post {
6560	/// #     type PrimaryKey = i64;
6561	/// #     type Fields = PostFields;
6562	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
6563	/// #     fn table_name() -> &'static str { "posts" }
6564	/// #     fn new_fields() -> Self::Fields { PostFields }
6565	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
6566	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
6567	/// # }
6568	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
6569	/// // Find posts that have both "rust" and "async" tags
6570	/// let posts = Post::objects()
6571	///     .filter_array_contains("tags", &["rust", "async"])
6572	///     .all()
6573	///     .await?;
6574	/// // Generates: WHERE tags @> ARRAY['rust', 'async']
6575	/// # Ok(())
6576	/// # }
6577	/// ```
6578	pub fn filter_array_contains(self, field: &str, values: &[&str]) -> Self {
6579		self.filter(Filter::new(
6580			field,
6581			FilterOperator::ArrayContains,
6582			FilterValue::Array(values.iter().map(|s| s.to_string()).collect()),
6583		))
6584	}
6585
6586	/// Filter by PostgreSQL JSONB containment
6587	///
6588	/// Returns rows where the JSONB field contains the given JSON object.
6589	///
6590	/// # Arguments
6591	///
6592	/// * `field` - The JSONB field name
6593	/// * `json` - JSON string to check for containment
6594	///
6595	/// # Examples
6596	///
6597	/// ```no_run
6598	/// # use reinhardt_db::orm::Model;
6599	/// # use serde::{Serialize, Deserialize};
6600	/// # #[derive(Clone, Serialize, Deserialize)]
6601	/// # struct Product { id: Option<i64>, name: String }
6602	/// # #[derive(Clone)]
6603	/// # struct ProductFields;
6604	/// # impl reinhardt_db::orm::model::FieldSelector for ProductFields {
6605	/// #     fn with_alias(self, _alias: &str) -> Self { self }
6606	/// # }
6607	/// # impl Model for Product {
6608	/// #     type PrimaryKey = i64;
6609	/// #     type Fields = ProductFields;
6610	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
6611	/// #     fn table_name() -> &'static str { "products" }
6612	/// #     fn new_fields() -> Self::Fields { ProductFields }
6613	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
6614	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
6615	/// # }
6616	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
6617	/// // Find products with specific metadata
6618	/// let products = Product::objects()
6619	///     .filter_jsonb_contains("metadata", r#"{"active": true}"#)
6620	///     .all()
6621	///     .await?;
6622	/// // Generates: WHERE metadata @> '{"active": true}'::jsonb
6623	/// # Ok(())
6624	/// # }
6625	/// ```
6626	pub fn filter_jsonb_contains(self, field: &str, json: &str) -> Self {
6627		self.filter(Filter::new(
6628			field,
6629			FilterOperator::JsonbContains,
6630			FilterValue::String(json.to_string()),
6631		))
6632	}
6633
6634	/// Filter by PostgreSQL JSONB key existence
6635	///
6636	/// Returns rows where the JSONB field contains the given key.
6637	///
6638	/// # Arguments
6639	///
6640	/// * `field` - The JSONB field name
6641	/// * `key` - Key to check for existence
6642	///
6643	/// # Examples
6644	///
6645	/// ```no_run
6646	/// # use reinhardt_db::orm::Model;
6647	/// # use serde::{Serialize, Deserialize};
6648	/// # #[derive(Clone, Serialize, Deserialize)]
6649	/// # struct Product { id: Option<i64>, name: String }
6650	/// # #[derive(Clone)]
6651	/// # struct ProductFields;
6652	/// # impl reinhardt_db::orm::model::FieldSelector for ProductFields {
6653	/// #     fn with_alias(self, _alias: &str) -> Self { self }
6654	/// # }
6655	/// # impl Model for Product {
6656	/// #     type PrimaryKey = i64;
6657	/// #     type Fields = ProductFields;
6658	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
6659	/// #     fn table_name() -> &'static str { "products" }
6660	/// #     fn new_fields() -> Self::Fields { ProductFields }
6661	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
6662	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
6663	/// # }
6664	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
6665	/// // Find products with "sale_price" in metadata
6666	/// let products = Product::objects()
6667	///     .filter_jsonb_key_exists("metadata", "sale_price")
6668	///     .all()
6669	///     .await?;
6670	/// // Generates: WHERE metadata ? 'sale_price'
6671	/// # Ok(())
6672	/// # }
6673	/// ```
6674	pub fn filter_jsonb_key_exists(self, field: &str, key: &str) -> Self {
6675		self.filter(Filter::new(
6676			field,
6677			FilterOperator::JsonbKeyExists,
6678			FilterValue::String(key.to_string()),
6679		))
6680	}
6681
6682	/// Filter by PostgreSQL range containment
6683	///
6684	/// Returns rows where the range field contains the given value.
6685	///
6686	/// # Arguments
6687	///
6688	/// * `field` - The range field name
6689	/// * `value` - Value to check for containment in the range
6690	///
6691	/// # Examples
6692	///
6693	/// ```no_run
6694	/// # use reinhardt_db::orm::Model;
6695	/// # use serde::{Serialize, Deserialize};
6696	/// # #[derive(Clone, Serialize, Deserialize)]
6697	/// # struct Event { id: Option<i64>, name: String }
6698	/// # #[derive(Clone)]
6699	/// # struct EventFields;
6700	/// # impl reinhardt_db::orm::model::FieldSelector for EventFields {
6701	/// #     fn with_alias(self, _alias: &str) -> Self { self }
6702	/// # }
6703	/// # impl Model for Event {
6704	/// #     type PrimaryKey = i64;
6705	/// #     type Fields = EventFields;
6706	/// #     type Objects = reinhardt_db::orm::Manager<Self>;
6707	/// #     fn table_name() -> &'static str { "events" }
6708	/// #     fn new_fields() -> Self::Fields { EventFields }
6709	/// #     fn primary_key(&self) -> Option<Self::PrimaryKey> { self.id }
6710	/// #     fn set_primary_key(&mut self, value: Self::PrimaryKey) { self.id = Some(value); }
6711	/// # }
6712	/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
6713	/// // Find events that include a specific date
6714	/// let events = Event::objects()
6715	///     .filter_range_contains("date_range", "2024-06-15")
6716	///     .all()
6717	///     .await?;
6718	/// // Generates: WHERE date_range @> '2024-06-15'
6719	/// # Ok(())
6720	/// # }
6721	/// ```
6722	pub fn filter_range_contains(self, field: &str, value: &str) -> Self {
6723		self.filter(Filter::new(
6724			field,
6725			FilterOperator::RangeContains,
6726			FilterValue::String(value.to_string()),
6727		))
6728	}
6729}
6730
6731impl<T> Default for QuerySet<T>
6732where
6733	T: super::Model,
6734{
6735	fn default() -> Self {
6736		Self::new()
6737	}
6738}
6739
6740// Convenience conversions for FilterValue
6741impl FilterValue {
6742	/// Create a String variant from any value that can be converted to String
6743	///
6744	/// Accepts any type that implements `ToString`, including:
6745	/// - String, &str
6746	/// - Uuid (via Display)
6747	/// - Numeric types (i64, u64, etc. via Display)
6748	pub fn string(value: impl ToString) -> Self {
6749		Self::String(value.to_string())
6750	}
6751}
6752
6753// ============================================================================
6754// Helper Functions
6755// ============================================================================
6756
6757/// Quote a SQL identifier to prevent injection via field names.
6758/// Uses PostgreSQL double-quote escaping (also valid for SQLite).
6759/// Handles dot-separated qualified names (e.g., "table.column" becomes "table"."column").
6760pub(crate) fn quote_identifier(field: &str) -> String {
6761	if field.contains('\0') {
6762		panic!("SQL identifier must not contain null bytes");
6763	}
6764
6765	fn quote_single(name: &str) -> String {
6766		format!("\"{}\"", name.replace('"', "\"\""))
6767	}
6768
6769	if field.contains('.') {
6770		field
6771			.split('.')
6772			.map(quote_single)
6773			.collect::<Vec<_>>()
6774			.join(".")
6775	} else {
6776		quote_single(field)
6777	}
6778}
6779
6780fn filter_lhs_expr(filter: &Filter) -> Expr {
6781	match &filter.field_source {
6782		FilterField::Column => Expr::col(parse_column_reference(&filter.field)),
6783		FilterField::Expression { sql, .. } if filter.field == *sql => Expr::cust(sql.clone()),
6784		FilterField::Expression { .. } => Expr::col(parse_column_reference(&filter.field)),
6785	}
6786}
6787
6788fn filter_lhs_sql(filter: &Filter) -> String {
6789	match &filter.field_source {
6790		FilterField::Column => quote_identifier(&filter.field),
6791		FilterField::Expression { sql, .. } if filter.field == *sql => sql.clone(),
6792		FilterField::Expression { .. } => quote_identifier(&filter.field),
6793	}
6794}
6795
6796/// Parse field reference into reinhardt-query column expression
6797///
6798/// Handles both qualified (`table.column`) and unqualified (`column`) references.
6799///
6800/// # Examples
6801///
6802/// - `"id"` → `ColumnRef::Column("id")`
6803/// - `"users.id"` → `ColumnRef::Column("users.id")` (qualified name as-is)
6804///
6805/// Note: For reinhardt-query v1.0.0-rc.29+, we use the full qualified name as a column identifier.
6806/// This works for most databases that support qualified column references.
6807///
6808/// This function also detects raw SQL expressions (containing parentheses, like `COUNT(*)`,
6809/// `AVG(price)`) and returns them wrapped in `Expr::cust()` instead of as column references.
6810pub(crate) fn parse_column_reference(field: &str) -> reinhardt_query::prelude::ColumnRef {
6811	use reinhardt_query::prelude::ColumnRef;
6812
6813	// Detect raw SQL expressions by checking for parentheses
6814	// Examples: COUNT(*), AVG(price), SUM(amount), MAX(value)
6815	if field.contains('(') && field.contains(')') {
6816		// Use column reference with raw expression name
6817		ColumnRef::column(Alias::new(field))
6818	} else if field.contains('.') {
6819		// Qualified column reference (table.column format)
6820		let parts: Vec<&str> = field.split('.').collect();
6821		match parts.as_slice() {
6822			[table, column] => {
6823				// Produces: "table"."column" instead of "table.column"
6824				ColumnRef::table_column(Alias::new(*table), Alias::new(*column))
6825			}
6826			[schema, table, column] => {
6827				// Produces: "schema"."table"."column"
6828				ColumnRef::schema_table_column(
6829					Alias::new(*schema),
6830					Alias::new(*table),
6831					Alias::new(*column),
6832				)
6833			}
6834			_ => {
6835				// Fallback for unexpected formats (4+ parts)
6836				ColumnRef::column(Alias::new(field))
6837			}
6838		}
6839	} else {
6840		// Simple column reference
6841		ColumnRef::column(Alias::new(field))
6842	}
6843}
6844
6845#[derive(Debug, Clone, Copy)]
6846enum LikePattern {
6847	Exact,
6848	Contains,
6849	StartsWith,
6850	EndsWith,
6851}
6852
6853impl LikePattern {
6854	fn apply(self, value: &str) -> String {
6855		let escaped = escape_like_pattern(value);
6856		match self {
6857			Self::Exact => escaped,
6858			Self::Contains => format!("%{}%", escaped),
6859			Self::StartsWith => format!("{}%", escaped),
6860			Self::EndsWith => format!("%{}", escaped),
6861		}
6862	}
6863}
6864
6865fn escape_like_pattern(value: &str) -> String {
6866	let mut escaped = String::with_capacity(value.len());
6867	for ch in value.chars() {
6868		if matches!(ch, '\\' | '%' | '_') {
6869			escaped.push('\\');
6870		}
6871		escaped.push(ch);
6872	}
6873	escaped
6874}
6875
6876fn build_select_statement(
6877	statement: &SelectStatement,
6878	backend: super::connection::DatabaseBackend,
6879) -> reinhardt_core::exception::Result<(String, Vec<QueryValue>)> {
6880	let (sql, values) = match backend {
6881		super::connection::DatabaseBackend::Postgres => statement.build(PostgresQueryBuilder),
6882		super::connection::DatabaseBackend::MySql => statement.build(MySqlQueryBuilder),
6883		super::connection::DatabaseBackend::Sqlite => statement.build(SqliteQueryBuilder),
6884	};
6885
6886	let params = values
6887		.into_iter()
6888		.map(query_value_from_sea_value)
6889		.collect::<reinhardt_core::exception::Result<Vec<_>>>()?;
6890	Ok((sql, params))
6891}
6892
6893#[cfg(test)]
6894fn render_select_statement(
6895	statement: &SelectStatement,
6896	backend: super::connection::DatabaseBackend,
6897) -> String {
6898	let (sql, values) = build_select_statement(statement, backend)
6899		.expect("test statements must contain bind values supported by QueryValue");
6900	inline_query_params(&sql, &values)
6901}
6902
6903fn query_value_from_sea_value(value: Value) -> reinhardt_core::exception::Result<QueryValue> {
6904	let value = match value {
6905		Value::Bool(Some(v)) => QueryValue::Bool(v),
6906		Value::TinyInt(Some(v)) => QueryValue::Int(i64::from(v)),
6907		Value::SmallInt(Some(v)) => QueryValue::Int(i64::from(v)),
6908		Value::Int(Some(v)) => QueryValue::Int(i64::from(v)),
6909		Value::BigInt(Some(v)) => QueryValue::Int(v),
6910		Value::TinyUnsigned(Some(v)) => QueryValue::Int(i64::from(v)),
6911		Value::SmallUnsigned(Some(v)) => QueryValue::Int(i64::from(v)),
6912		Value::Unsigned(Some(v)) => QueryValue::Int(i64::from(v)),
6913		Value::BigUnsigned(Some(v)) => QueryValue::Int(i64::try_from(v).map_err(|_| {
6914			reinhardt_core::exception::Error::Database(format!(
6915				"Unsigned query parameter {v} exceeds the supported i64 range"
6916			))
6917		})?),
6918		Value::Float(Some(v)) => QueryValue::Float(f64::from(v)),
6919		Value::Double(Some(v)) => QueryValue::Float(v),
6920		Value::Char(Some(v)) => QueryValue::String(v.to_string()),
6921		Value::String(Some(v)) => QueryValue::String(*v),
6922		Value::Bytes(Some(v)) => QueryValue::Bytes(*v),
6923		Value::ChronoDateTimeUtc(Some(v)) => QueryValue::Timestamp(*v),
6924		Value::Uuid(Some(v)) => QueryValue::Uuid(*v),
6925		_ => QueryValue::Null,
6926	};
6927	Ok(value)
6928}
6929
6930#[cfg(test)]
6931fn inline_query_params(sql: &str, params: &[QueryValue]) -> String {
6932	let mut rendered = sql.to_string();
6933	for value in params {
6934		rendered = rendered.replacen('?', &query_value_to_sql_literal(value), 1);
6935	}
6936	rendered
6937}
6938
6939#[cfg(test)]
6940fn query_value_to_sql_literal(value: &QueryValue) -> String {
6941	match value {
6942		QueryValue::Null => "NULL".to_string(),
6943		QueryValue::Bool(v) => v.to_string(),
6944		QueryValue::Int(v) => v.to_string(),
6945		QueryValue::Float(v) => v.to_string(),
6946		QueryValue::String(v) => format!("'{}'", v.replace('\\', "\\\\").replace('\'', "''")),
6947		QueryValue::Bytes(v) => format!(
6948			"X'{}'",
6949			v.iter().map(|b| format!("{b:02X}")).collect::<String>()
6950		),
6951		QueryValue::Timestamp(v) => format!("'{}'", v.to_rfc3339()),
6952		QueryValue::Uuid(v) => format!("'{}'", v),
6953		QueryValue::Now => "NOW()".to_string(),
6954	}
6955}
6956
6957#[cfg(test)]
6958mod tests {
6959	use super::{
6960		AggregateFunc, AggregateValue, ComparisonOp, FilterCondition, HavingCondition,
6961		MAX_FILTER_CONDITION_DEPTH, build_select_statement, render_select_statement,
6962	};
6963	use crate::orm::connection::DatabaseBackend;
6964	use crate::orm::query::{FieldAssignment, UpdateValue};
6965	use crate::orm::{FilterOperator, FilterValue, Manager, Model, QuerySet, query::Filter};
6966	use reinhardt_query::prelude::{ExprTrait, PostgresQueryBuilder, QueryStatementBuilder};
6967	use rstest::rstest;
6968	use serde::{Deserialize, Serialize};
6969	use std::collections::HashMap;
6970
6971	#[test]
6972	fn render_select_statement_uses_mysql_identifier_quoting() {
6973		// Arrange
6974		let mut statement = reinhardt_query::prelude::Query::select();
6975		statement
6976			.column(reinhardt_query::prelude::Alias::new("id"))
6977			.from(reinhardt_query::prelude::Alias::new("articles"));
6978
6979		// Act
6980		let sql = render_select_statement(&statement, DatabaseBackend::MySql);
6981
6982		// Assert
6983		assert_eq!(sql, "SELECT `id` FROM `articles`");
6984	}
6985
6986	#[test]
6987	fn build_select_statement_keeps_mysql_filter_values_bound() {
6988		// Arrange
6989		let payload = "\\' OR 1=1 -- ";
6990		let mut statement = reinhardt_query::prelude::Query::select();
6991		statement
6992			.column(reinhardt_query::prelude::Alias::new("id"))
6993			.from(reinhardt_query::prelude::Alias::new("users"))
6994			.and_where(
6995				reinhardt_query::prelude::Expr::col(reinhardt_query::prelude::Alias::new("name"))
6996					.eq(payload),
6997			);
6998
6999		// Act
7000		let (sql, params) = build_select_statement(&statement, DatabaseBackend::MySql)
7001			.expect("string filter should fit in QueryValue");
7002
7003		// Assert
7004		assert_eq!(sql, "SELECT `id` FROM `users` WHERE `name` = ?");
7005		assert_eq!(
7006			params,
7007			vec![crate::backends::types::QueryValue::String(
7008				payload.to_string()
7009			)]
7010		);
7011	}
7012
7013	#[test]
7014	fn build_select_statement_rejects_oversized_unsigned_parameters() {
7015		// Arrange
7016		let mut statement = reinhardt_query::prelude::Query::select();
7017		statement
7018			.column(reinhardt_query::prelude::Alias::new("id"))
7019			.from(reinhardt_query::prelude::Alias::new("users"))
7020			.limit((i64::MAX as u64) + 1);
7021
7022		// Act
7023		let error = build_select_statement(&statement, DatabaseBackend::MySql)
7024			.expect_err("oversized unsigned parameters must not be clamped");
7025
7026		// Assert
7027		assert_eq!(
7028			error.to_string(),
7029			"Database error: Unsigned query parameter 9223372036854775808 exceeds the supported i64 range"
7030		);
7031	}
7032
7033	#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
7034	struct TestUser {
7035		id: Option<i64>,
7036		username: String,
7037		email: String,
7038	}
7039
7040	impl TestUser {
7041		// Allow dead_code: test helper constructor for query tests
7042		#[allow(dead_code)]
7043		fn new(username: String, email: String) -> Self {
7044			Self {
7045				id: None,
7046				username,
7047				email,
7048			}
7049		}
7050
7051		const fn field_id() -> crate::orm::expressions::FieldRef<TestUser, i64> {
7052			crate::orm::expressions::FieldRef::new("id")
7053		}
7054
7055		const fn field_username() -> crate::orm::expressions::FieldRef<TestUser, String> {
7056			crate::orm::expressions::FieldRef::new("username")
7057		}
7058
7059		const fn field_email() -> crate::orm::expressions::FieldRef<TestUser, String> {
7060			crate::orm::expressions::FieldRef::new("email")
7061		}
7062
7063		const fn field_created_at() -> crate::orm::expressions::FieldRef<TestUser, String> {
7064			crate::orm::expressions::FieldRef::new("created_at")
7065		}
7066
7067		const fn field_tags() -> crate::orm::expressions::FieldRef<TestUser, Vec<String>> {
7068			crate::orm::expressions::FieldRef::new("tags")
7069		}
7070
7071		const fn field_metadata() -> crate::orm::expressions::FieldRef<TestUser, String> {
7072			crate::orm::expressions::FieldRef::new("metadata")
7073		}
7074
7075		const fn field_active_period() -> crate::orm::expressions::FieldRef<TestUser, String> {
7076			crate::orm::expressions::FieldRef::new("active_period")
7077		}
7078	}
7079
7080	#[derive(Debug, Clone)]
7081	struct TestUserFields;
7082
7083	impl crate::orm::model::FieldSelector for TestUserFields {
7084		fn with_alias(self, _alias: &str) -> Self {
7085			self
7086		}
7087	}
7088
7089	impl Model for TestUser {
7090		type PrimaryKey = i64;
7091		type Fields = TestUserFields;
7092		type Objects = Manager<Self>;
7093
7094		fn table_name() -> &'static str {
7095			"test_users"
7096		}
7097
7098		fn primary_key(&self) -> Option<Self::PrimaryKey> {
7099			self.id
7100		}
7101
7102		fn set_primary_key(&mut self, value: Self::PrimaryKey) {
7103			self.id = Some(value);
7104		}
7105
7106		fn primary_key_field() -> &'static str {
7107			"id"
7108		}
7109
7110		fn new_fields() -> Self::Fields {
7111			TestUserFields
7112		}
7113	}
7114
7115	#[test]
7116	fn queryset_maps_in_and_not_in_subquery_fields() {
7117		let mut queryset = QuerySet::<TestUser>::new()
7118			.filter_in_subquery("username", |subquery: QuerySet<TestUser>| subquery)
7119			.filter_not_in_subquery("email", |subquery: QuerySet<TestUser>| subquery);
7120
7121		assert_eq!(
7122			queryset.subquery_fields().collect::<Vec<_>>(),
7123			vec!["username", "email"]
7124		);
7125
7126		queryset.map_subquery_fields(|field| field.push_str("_column"));
7127
7128		assert_eq!(
7129			queryset.subquery_fields().collect::<Vec<_>>(),
7130			vec!["username_column", "email_column"]
7131		);
7132	}
7133
7134	#[test]
7135	fn queryset_tracks_correlated_exists_fields() {
7136		let mut queryset = QuerySet::<TestUser>::new()
7137			.filter_exists(|subquery: QuerySet<TestUser>| {
7138				subquery.filter(Filter::new(
7139					"tenant_id",
7140					FilterOperator::Eq,
7141					FilterValue::FieldRef(crate::orm::expressions::F::new("items.tenant_slug")),
7142				))
7143			})
7144			.filter_not_exists(|subquery: QuerySet<TestUser>| {
7145				subquery.filter(Filter::new(
7146					"organization_id",
7147					FilterOperator::Eq,
7148					FilterValue::OuterRef(crate::orm::expressions::OuterRef::new(
7149						"items.organization_id",
7150					)),
7151				))
7152			});
7153
7154		assert_eq!(
7155			queryset.subquery_fields().collect::<Vec<_>>(),
7156			vec!["items.tenant_slug", "items.organization_id"]
7157		);
7158
7159		queryset.map_subquery_fields(|field| {
7160			*field = match field.as_str() {
7161				"items.tenant_slug" => "items.tenant_id".to_owned(),
7162				"items.organization_id" => "items.organization_key".to_owned(),
7163				field => format!("{field}_column"),
7164			};
7165		});
7166
7167		assert_eq!(
7168			queryset.subquery_fields().collect::<Vec<_>>(),
7169			vec!["items.tenant_id", "items.organization_key"]
7170		);
7171
7172		let sql = queryset.to_sql();
7173		assert_eq!(
7174			sql,
7175			r#"SELECT * FROM "test_users" WHERE (EXISTS (SELECT * FROM "test_users" WHERE "tenant_id" = "items"."tenant_id") AND NOT EXISTS (SELECT * FROM "test_users" WHERE "organization_id" = "items"."organization_key"))"#
7176		);
7177	}
7178
7179	#[test]
7180	fn map_subquery_fields_does_not_cascade_replacements() {
7181		let mut queryset =
7182			QuerySet::<TestUser>::new().filter_exists(|subquery: QuerySet<TestUser>| {
7183				subquery
7184					.filter(Filter::new(
7185						"tenant_id",
7186						FilterOperator::Eq,
7187						FilterValue::FieldRef(crate::orm::expressions::F::new("items.a")),
7188					))
7189					.filter(Filter::new(
7190						"organization_id",
7191						FilterOperator::Eq,
7192						FilterValue::FieldRef(crate::orm::expressions::F::new("items.b")),
7193					))
7194			});
7195
7196		queryset.map_subquery_fields(|field| {
7197			*field = match field.as_str() {
7198				"items.a" => "items.b".to_owned(),
7199				"items.b" => "items.c".to_owned(),
7200				field => field.to_owned(),
7201			};
7202		});
7203
7204		assert_eq!(
7205			queryset.to_sql(),
7206			r#"SELECT * FROM "test_users" WHERE EXISTS (SELECT * FROM "test_users" WHERE ("tenant_id" = "items"."b" AND "organization_id" = "items"."c"))"#
7207		);
7208	}
7209
7210	#[test]
7211	fn full_model_select_keeps_filter_order_limit_and_bound_value() {
7212		let queryset = QuerySet::<TestUser>::new()
7213			.filter(Filter::new(
7214				"username",
7215				FilterOperator::Eq,
7216				FilterValue::String("alice".to_owned()),
7217			))
7218			.order_by(&["-id"])
7219			.limit(1);
7220		let statement = queryset.build_full_model_select_statement().unwrap();
7221		let (sql, values) = statement.build(PostgresQueryBuilder);
7222		assert_eq!(
7223			sql,
7224			r#"SELECT * FROM "test_users" WHERE "username" = $1 ORDER BY "id" DESC LIMIT $2"#
7225		);
7226		assert_eq!(
7227			values.0,
7228			vec![
7229				reinhardt_query::value::Value::String(Some(Box::new("alice".to_owned()))),
7230				reinhardt_query::value::Value::BigUnsigned(Some(1)),
7231			]
7232		);
7233	}
7234
7235	#[test]
7236	fn full_model_select_rejects_non_model_shapes() {
7237		fn assert_rejected(queryset: QuerySet<TestUser>) {
7238			assert_eq!(
7239				queryset
7240					.build_full_model_select_statement()
7241					.unwrap_err()
7242					.to_string(),
7243				"Database error: Session::list requires a model-shaped QuerySet"
7244			);
7245		}
7246
7247		assert_rejected(QuerySet::<TestUser>::new().values(&["id"]));
7248		assert_rejected(QuerySet::<TestUser>::new().defer(&["email"]));
7249		let annotated =
7250			QuerySet::<TestUser>::new().annotate(crate::orm::annotation::Annotation::new(
7251				"answer",
7252				crate::orm::annotation::AnnotationValue::Value(crate::orm::annotation::Value::Int(
7253					42,
7254				)),
7255			));
7256		assert!(
7257			annotated
7258				.build_full_model_select_statement()
7259				.expect("annotations must remain available to model sessions")
7260				.to_string(PostgresQueryBuilder)
7261				.contains("42 AS \"answer\"")
7262		);
7263		assert_rejected(QuerySet::<TestUser>::new().select_related(&["profile"]));
7264		assert_eq!(
7265			QuerySet::<TestUser>::new()
7266				.prefetch_related(&["groups"])
7267				.build_full_model_select_statement()
7268				.expect("prefetch must not change the root model projection")
7269				.to_string(PostgresQueryBuilder),
7270			r#"SELECT * FROM "test_users""#
7271		);
7272		fn assert_supported(queryset: QuerySet<TestUser>, fragment: &str) {
7273			let sql = queryset
7274				.build_full_model_select_statement()
7275				.expect("structural clauses must remain executable")
7276				.to_string(PostgresQueryBuilder);
7277			assert!(
7278				sql.contains(fragment),
7279				"SQL `{sql}` must contain `{fragment}`"
7280			);
7281		}
7282
7283		assert_supported(
7284			QuerySet::<TestUser>::new().with_cte(crate::orm::cte::CTE::new("active", "SELECT 1")),
7285			"WITH \"active\" AS (SELECT 1)",
7286		);
7287		assert_supported(
7288			QuerySet::<TestUser>::new().with_lateral_join(
7289				crate::orm::lateral_join::LateralJoin::new("latest", "SELECT 1"),
7290			),
7291			"LEFT JOIN LATERAL (SELECT 1) AS \"latest\" ON true",
7292		);
7293		assert_supported(
7294			QuerySet::<TestUser>::new().inner_join::<TestUser>("id", "id"),
7295			"INNER JOIN \"test_users\" ON",
7296		);
7297
7298		let mut grouped = QuerySet::<TestUser>::new();
7299		grouped.group_by_fields.push("id".to_owned());
7300		assert_supported(grouped, "GROUP BY \"id\"");
7301
7302		let mut having = QuerySet::<TestUser>::new();
7303		having
7304			.having_conditions
7305			.push(HavingCondition::AggregateCompare {
7306				func: AggregateFunc::Count,
7307				field: "*".to_owned(),
7308				operator: ComparisonOp::Gt,
7309				value: AggregateValue::Int(0),
7310			});
7311		assert_supported(having, "HAVING COUNT(*) >");
7312
7313		assert_supported(
7314			QuerySet::<TestUser>::new().from_as("users_alias"),
7315			"FROM \"test_users\" AS \"users_alias\"",
7316		);
7317		assert_supported(
7318			QuerySet::<TestUser>::from_subquery(
7319				|queryset: QuerySet<TestUser>| queryset,
7320				"users_subquery",
7321			),
7322			"FROM (SELECT * FROM \"test_users\") AS \"users_subquery\"",
7323		);
7324	}
7325
7326	#[test]
7327	fn for_model_session_discards_manager_result_modifiers() {
7328		let queryset = QuerySet::<TestUser>::new()
7329			.values(&["id"])
7330			.defer(&["email"])
7331			.annotate(crate::orm::annotation::Annotation::new(
7332				"answer",
7333				crate::orm::annotation::AnnotationValue::Value(crate::orm::annotation::Value::Int(
7334					42,
7335				)),
7336			))
7337			.select_related(&["profile"])
7338			.prefetch_related(&["groups"]);
7339
7340		let statement = queryset
7341			.for_model_session()
7342			.build_full_model_select_statement()
7343			.expect("manager result modifiers must not block model decoding");
7344
7345		assert_eq!(
7346			statement.to_string(PostgresQueryBuilder),
7347			r#"SELECT *, 42 AS "answer" FROM "test_users""#
7348		);
7349	}
7350
7351	#[test]
7352	fn test_field_assignment_from_generated_field_ref_tuple() {
7353		let timestamp = chrono::DateTime::parse_from_rfc3339("2026-06-19T00:00:00Z")
7354			.expect("valid timestamp")
7355			.with_timezone(&chrono::Utc);
7356
7357		let assignment: FieldAssignment = (TestUser::field_created_at(), timestamp).into();
7358
7359		assert_eq!(assignment.field(), "created_at");
7360		assert!(matches!(assignment.value(), UpdateValue::Timestamp(_)));
7361	}
7362
7363	#[test]
7364	fn test_typed_timestamp_filter_binds_as_timestamp() {
7365		// Arrange
7366		let timestamp = chrono::DateTime::parse_from_rfc3339("2026-06-19T00:00:00Z")
7367			.expect("valid timestamp")
7368			.with_timezone(&chrono::Utc);
7369		let value: FilterValue = timestamp.into();
7370
7371		// Act
7372		let bound = QuerySet::<TestUser>::filter_value_to_sea_value(&value);
7373
7374		// Assert
7375		assert!(matches!(value, FilterValue::Timestamp(_)));
7376		assert!(matches!(
7377			bound,
7378			reinhardt_query::value::Value::ChronoDateTimeUtc(Some(_))
7379		));
7380	}
7381
7382	#[test]
7383	fn test_typed_uuid_filter_binds_as_uuid() {
7384		// Arrange
7385		let uuid =
7386			uuid::Uuid::parse_str("123e4567-e89b-12d3-a456-426614174000").expect("valid UUID");
7387		let value: FilterValue = uuid.into();
7388
7389		// Act
7390		let bound = QuerySet::<TestUser>::filter_value_to_sea_value(&value);
7391
7392		// Assert
7393		assert!(matches!(value, FilterValue::Uuid(_)));
7394		assert!(matches!(
7395			bound,
7396			reinhardt_query::value::Value::Uuid(Some(_))
7397		));
7398	}
7399
7400	#[test]
7401	fn test_field_assignment_from_field_ref_assign_helper() {
7402		let assignment = TestUser::field_username().assign("alice");
7403
7404		assert_eq!(assignment.field(), "username");
7405		assert!(matches!(
7406			assignment.value(),
7407			UpdateValue::String(value) if value == "alice"
7408		));
7409	}
7410
7411	#[test]
7412	fn test_update_fields_sql_preserves_queryset_predicates() {
7413		let timestamp = chrono::DateTime::parse_from_rfc3339("2026-06-19T00:00:00Z")
7414			.expect("valid timestamp")
7415			.with_timezone(&chrono::Utc);
7416		let queryset = QuerySet::<TestUser>::new()
7417			.filter(TestUser::field_id().eq(7))
7418			.filter(TestUser::field_email().is_null());
7419
7420		let (sql, params) = queryset
7421			.update_fields_sql([(TestUser::field_created_at(), timestamp)])
7422			.expect("update fields sql");
7423
7424		assert_eq!(
7425			sql,
7426			"UPDATE \"test_users\" SET \"created_at\" = $1 WHERE (\"id\" = $2 AND \"email\" IS NULL)"
7427		);
7428		assert_eq!(params.len(), 2);
7429		assert_eq!(params[0], "2026-06-19T00:00:00+00:00");
7430		assert_eq!(params[1], "7");
7431	}
7432
7433	#[test]
7434	fn test_update_fields_sql_rejects_empty_assignments() {
7435		let queryset = QuerySet::<TestUser>::new().filter(TestUser::field_id().eq(7));
7436
7437		let error = queryset
7438			.update_fields_sql(std::iter::empty::<FieldAssignment>())
7439			.expect_err("empty assignments should fail");
7440
7441		assert!(matches!(
7442			error,
7443			reinhardt_core::exception::Error::Validation(message)
7444				if message.contains("field assignment")
7445		));
7446	}
7447
7448	#[test]
7449	fn test_update_fields_sql_rejects_missing_predicate() {
7450		let queryset = QuerySet::<TestUser>::new();
7451
7452		let error = queryset
7453			.update_fields_sql([("username", "alice")])
7454			.expect_err("missing predicate should fail");
7455
7456		assert!(matches!(
7457			error,
7458			reinhardt_core::exception::Error::Validation(message)
7459				if message.contains("filter predicate")
7460		));
7461	}
7462
7463	#[test]
7464	fn test_update_fields_sql_rejects_empty_and_predicate() {
7465		let queryset = QuerySet::<TestUser>::new().filter(FilterCondition::and(Vec::new()));
7466
7467		let error = queryset
7468			.update_fields_sql([("username", "alice")])
7469			.expect_err("empty AND predicate should fail");
7470
7471		assert!(matches!(
7472			error,
7473			reinhardt_core::exception::Error::Validation(message)
7474				if message == "QuerySet::update_fields requires at least one non-empty filter predicate"
7475		));
7476	}
7477
7478	#[test]
7479	fn test_update_fields_sql_rejects_empty_not_in_predicate() {
7480		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
7481			"id".to_string(),
7482			FilterOperator::NotIn,
7483			FilterValue::List(vec![]),
7484		));
7485
7486		let error = queryset
7487			.update_fields_sql([("username", "alice")])
7488			.expect_err("empty NOT IN predicate should fail");
7489
7490		assert!(matches!(
7491			error,
7492			reinhardt_core::exception::Error::Validation(message)
7493				if message == "QuerySet::update_fields requires at least one non-empty filter predicate"
7494		));
7495	}
7496
7497	#[tokio::test]
7498	async fn test_queryset_create_with_manager() {
7499		// Test QuerySet::create() with explicit manager
7500		let manager = std::sync::Arc::new(TestUser::objects());
7501		let queryset = QuerySet::with_manager(manager);
7502
7503		let user = TestUser {
7504			id: None,
7505			username: "testuser".to_string(),
7506			email: "test@example.com".to_string(),
7507		};
7508
7509		// Note: This will fail without a real database connection
7510		// In actual integration tests, we would set up a test database
7511		let result = queryset.create(user).await;
7512
7513		// In unit tests, we expect this to fail due to no database
7514		// In integration tests with TestContainers, this would succeed
7515		assert!(result.is_err() || result.is_ok());
7516	}
7517
7518	#[tokio::test]
7519	async fn test_queryset_create_without_manager() {
7520		// Test QuerySet::create() fallback without manager
7521		let queryset = QuerySet::<TestUser>::new();
7522
7523		let user = TestUser {
7524			id: None,
7525			username: "fallback_user".to_string(),
7526			email: "fallback@example.com".to_string(),
7527		};
7528
7529		// Note: This will fail without a real database connection
7530		let result = queryset.create(user).await;
7531
7532		// In unit tests, we expect this to fail due to no database
7533		assert!(result.is_err() || result.is_ok());
7534	}
7535
7536	#[test]
7537	fn test_queryset_with_manager() {
7538		let manager = std::sync::Arc::new(TestUser::objects());
7539		let queryset = QuerySet::with_manager(manager.clone());
7540
7541		// Verify manager is set
7542		assert!(queryset.manager.is_some());
7543	}
7544
7545	#[test]
7546	fn test_queryset_filter_preserves_manager() {
7547		let manager = std::sync::Arc::new(TestUser::objects());
7548		let queryset = QuerySet::with_manager(manager);
7549
7550		let filter = Filter::new(
7551			"username".to_string(),
7552			FilterOperator::Eq,
7553			FilterValue::String("alice".to_string()),
7554		);
7555
7556		let filtered = queryset.filter(filter);
7557
7558		// Verify manager is preserved after filter
7559		assert!(filtered.manager.is_some());
7560	}
7561
7562	#[test]
7563	fn test_queryset_select_related_preserves_manager() {
7564		let manager = std::sync::Arc::new(TestUser::objects());
7565		let queryset = QuerySet::with_manager(manager);
7566
7567		let selected = queryset.select_related(&["profile", "posts"]);
7568
7569		// Verify manager is preserved after select_related
7570		assert!(selected.manager.is_some());
7571		assert_eq!(selected.select_related_fields, vec!["profile", "posts"]);
7572	}
7573
7574	#[test]
7575	fn test_queryset_prefetch_related_preserves_manager() {
7576		let manager = std::sync::Arc::new(TestUser::objects());
7577		let queryset = QuerySet::with_manager(manager);
7578
7579		let prefetched = queryset.prefetch_related(&["comments", "likes"]);
7580
7581		// Verify manager is preserved after prefetch_related
7582		assert!(prefetched.manager.is_some());
7583		assert_eq!(
7584			prefetched.prefetch_related_fields,
7585			vec!["comments", "likes"]
7586		);
7587	}
7588
7589	#[tokio::test]
7590	async fn test_get_composite_validation_error() {
7591		use std::collections::HashMap;
7592
7593		let queryset = QuerySet::<TestUser>::new();
7594		let pk_values = HashMap::new(); // Empty HashMap - should fail validation
7595
7596		let result = queryset.get_composite(&pk_values).await;
7597
7598		// Expect error because TestUser doesn't have a composite primary key
7599		assert!(result.is_err());
7600		let err = result.unwrap_err();
7601		assert!(err.to_string().contains("composite primary key"));
7602	}
7603
7604	// SQL Generation Tests
7605
7606	#[test]
7607	fn test_update_sql_single_field_single_filter() {
7608		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
7609			"id".to_string(),
7610			FilterOperator::Eq,
7611			FilterValue::Integer(1),
7612		));
7613
7614		let mut updates = HashMap::new();
7615		updates.insert(
7616			"username".to_string(),
7617			UpdateValue::String("alice".to_string()),
7618		);
7619		let (sql, params) = queryset.update_sql(&updates);
7620
7621		assert_eq!(
7622			sql,
7623			"UPDATE \"test_users\" SET \"username\" = $1 WHERE \"id\" = $2"
7624		);
7625		assert_eq!(params, vec!["alice", "1"]);
7626	}
7627
7628	#[test]
7629	fn test_update_sql_multiple_fields_multiple_filters() {
7630		let queryset = QuerySet::<TestUser>::new()
7631			.filter(Filter::new(
7632				"id".to_string(),
7633				FilterOperator::Gt,
7634				FilterValue::Integer(10),
7635			))
7636			.filter(Filter::new(
7637				"email".to_string(),
7638				FilterOperator::Contains,
7639				FilterValue::String("example.com".to_string()),
7640			));
7641
7642		let mut updates = HashMap::new();
7643		updates.insert(
7644			"username".to_string(),
7645			UpdateValue::String("bob".to_string()),
7646		);
7647		updates.insert(
7648			"email".to_string(),
7649			UpdateValue::String("bob@test.com".to_string()),
7650		);
7651		let (sql, params) = queryset.update_sql(&updates);
7652
7653		// HashMap iteration order is not guaranteed, so we check both possible orderings
7654		let valid_sql_1 = "UPDATE \"test_users\" SET \"username\" = $1, \"email\" = $2 WHERE (\"id\" > $3 AND \"email\" LIKE $4 ESCAPE '\\')";
7655		let valid_sql_2 = "UPDATE \"test_users\" SET \"email\" = $1, \"username\" = $2 WHERE (\"id\" > $3 AND \"email\" LIKE $4 ESCAPE '\\')";
7656		assert!(
7657			sql == valid_sql_1 || sql == valid_sql_2,
7658			"Generated SQL '{}' does not match either expected pattern",
7659			sql
7660		);
7661
7662		// Check that all expected values are present (order may vary for SET clause)
7663		assert!(
7664			params.contains(&"bob".to_string()) || params.contains(&"bob@test.com".to_string())
7665		);
7666		assert_eq!(params[2], "10");
7667		assert_eq!(params[3], "%example.com%");
7668	}
7669
7670	#[test]
7671	fn test_delete_sql_single_filter() {
7672		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
7673			"id".to_string(),
7674			FilterOperator::Eq,
7675			FilterValue::Integer(1),
7676		));
7677
7678		let (sql, params) = queryset.delete_sql();
7679
7680		assert_eq!(sql, "DELETE FROM \"test_users\" WHERE \"id\" = $1");
7681		assert_eq!(params, vec!["1"]);
7682	}
7683
7684	#[test]
7685	fn test_delete_sql_multiple_filters() {
7686		let queryset = QuerySet::<TestUser>::new()
7687			.filter(Filter::new(
7688				"username".to_string(),
7689				FilterOperator::Eq,
7690				FilterValue::String("alice".to_string()),
7691			))
7692			.filter(Filter::new(
7693				"email".to_string(),
7694				FilterOperator::StartsWith,
7695				FilterValue::String("alice@".to_string()),
7696			));
7697
7698		let (sql, params) = queryset.delete_sql();
7699
7700		assert_eq!(
7701			sql,
7702			"DELETE FROM \"test_users\" WHERE (\"username\" = $1 AND \"email\" LIKE $2 ESCAPE '\\')"
7703		);
7704		assert_eq!(params, vec!["alice", "alice@%"]);
7705	}
7706
7707	#[test]
7708	#[should_panic(
7709		expected = "DELETE without WHERE clause is not allowed. Use .filter() to specify which rows to delete."
7710	)]
7711	fn test_delete_sql_without_filters_panics() {
7712		let queryset = QuerySet::<TestUser>::new();
7713		let _ = queryset.delete_sql();
7714	}
7715
7716	#[test]
7717	#[should_panic(
7718		expected = "DELETE without WHERE clause is not allowed. Use .filter() to specify which rows to delete."
7719	)]
7720	fn test_delete_sql_with_empty_composite_filter_panics() {
7721		let queryset = QuerySet::<TestUser>::new().filter(FilterCondition::and(Vec::new()));
7722		let _ = queryset.delete_sql();
7723	}
7724
7725	#[test]
7726	#[should_panic(
7727		expected = "DELETE without WHERE clause is not allowed. Use .filter() to specify which rows to delete."
7728	)]
7729	fn test_delete_sql_with_nested_empty_and_filter_panics() {
7730		let queryset = QuerySet::<TestUser>::new()
7731			.filter(FilterCondition::and(vec![FilterCondition::and(Vec::new())]));
7732		let _ = queryset.delete_sql();
7733	}
7734
7735	#[test]
7736	fn test_delete_sql_with_empty_or_filter_matches_no_rows() {
7737		let queryset = QuerySet::<TestUser>::new().filter(FilterCondition::or(Vec::new()));
7738
7739		let (sql, params) = queryset.delete_sql();
7740
7741		assert_eq!(sql, r#"DELETE FROM "test_users" WHERE FALSE"#);
7742		assert!(params.is_empty());
7743	}
7744
7745	#[test]
7746	fn test_delete_sql_keeps_real_filter_beside_empty_and() {
7747		let queryset = QuerySet::<TestUser>::new()
7748			.filter(FilterCondition::and(Vec::new()))
7749			.filter(Filter::new(
7750				"id".to_string(),
7751				FilterOperator::Eq,
7752				FilterValue::Integer(1),
7753			));
7754
7755		let (sql, params) = queryset.delete_sql();
7756
7757		assert_eq!(
7758			sql,
7759			r#"DELETE FROM "test_users" WHERE ("id" = $1 AND TRUE)"#
7760		);
7761		assert_eq!(params, vec!["1"]);
7762	}
7763
7764	#[test]
7765	#[should_panic(
7766		expected = "DELETE without WHERE clause is not allowed. Use .filter() to specify which rows to delete."
7767	)]
7768	fn test_delete_sql_with_empty_not_in_list_panics() {
7769		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
7770			"id".to_string(),
7771			FilterOperator::NotIn,
7772			FilterValue::List(vec![]),
7773		));
7774		let _ = queryset.delete_sql();
7775	}
7776
7777	#[test]
7778	#[should_panic(
7779		expected = "DELETE without WHERE clause is not allowed. Use .filter() to specify which rows to delete."
7780	)]
7781	fn test_delete_sql_with_empty_not_in_array_panics() {
7782		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
7783			"id".to_string(),
7784			FilterOperator::NotIn,
7785			FilterValue::Array(vec![]),
7786		));
7787		let _ = queryset.delete_sql();
7788	}
7789
7790	#[test]
7791	#[should_panic(
7792		expected = "DELETE without WHERE clause is not allowed. Use .filter() to specify which rows to delete."
7793	)]
7794	fn test_delete_sql_with_empty_not_in_single_condition_panics() {
7795		let queryset = QuerySet::<TestUser>::new().filter(FilterCondition::and(vec![
7796			FilterCondition::Single(Filter::new(
7797				"id".to_string(),
7798				FilterOperator::NotIn,
7799				FilterValue::List(vec![]),
7800			)),
7801		]));
7802		let _ = queryset.delete_sql();
7803	}
7804
7805	#[test]
7806	#[should_panic(
7807		expected = "DELETE without WHERE clause is not allowed. Use .filter() to specify which rows to delete."
7808	)]
7809	fn test_delete_sql_with_not_empty_in_panics() {
7810		let queryset = QuerySet::<TestUser>::new().filter(FilterCondition::not(Filter::new(
7811			"id".to_string(),
7812			FilterOperator::In,
7813			FilterValue::List(vec![]),
7814		)));
7815		let _ = queryset.delete_sql();
7816	}
7817
7818	#[test]
7819	fn test_delete_sql_with_empty_in_list_matches_no_rows() {
7820		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
7821			"id".to_string(),
7822			FilterOperator::In,
7823			FilterValue::List(vec![]),
7824		));
7825
7826		let (sql, params) = queryset.delete_sql();
7827
7828		assert_eq!(sql, r#"DELETE FROM "test_users" WHERE FALSE"#);
7829		assert!(params.is_empty());
7830	}
7831
7832	#[test]
7833	fn test_delete_sql_keeps_real_filter_beside_empty_not_in() {
7834		let queryset = QuerySet::<TestUser>::new()
7835			.filter(Filter::new(
7836				"id".to_string(),
7837				FilterOperator::Eq,
7838				FilterValue::Integer(1),
7839			))
7840			.filter(Filter::new(
7841				"id".to_string(),
7842				FilterOperator::NotIn,
7843				FilterValue::List(vec![]),
7844			));
7845
7846		let (sql, params) = queryset.delete_sql();
7847
7848		assert_eq!(
7849			sql,
7850			r#"DELETE FROM "test_users" WHERE ("id" = $1 AND TRUE)"#
7851		);
7852		assert_eq!(params, vec!["1"]);
7853	}
7854
7855	#[test]
7856	fn test_empty_and_filter_condition_is_always_true() {
7857		assert!(FilterCondition::and(Vec::new()).is_always_true());
7858		assert!(!FilterCondition::and(Vec::new()).is_always_false());
7859		assert!(!FilterCondition::or(Vec::new()).is_always_true());
7860		assert!(FilterCondition::or(Vec::new()).is_always_false());
7861		assert!(!FilterCondition::not(FilterCondition::and(Vec::new())).is_always_true());
7862		assert!(FilterCondition::not(FilterCondition::and(Vec::new())).is_always_false());
7863
7864		let empty_not_in = Filter::new(
7865			"id".to_string(),
7866			FilterOperator::NotIn,
7867			FilterValue::List(vec![]),
7868		);
7869		assert!(empty_not_in.is_always_true());
7870		assert!(!empty_not_in.is_always_false());
7871		assert!(FilterCondition::Single(empty_not_in.clone()).is_always_true());
7872		assert!(!FilterCondition::Single(empty_not_in.clone()).is_always_false());
7873		assert!(
7874			FilterCondition::and(vec![FilterCondition::Single(empty_not_in.clone())])
7875				.is_always_true()
7876		);
7877
7878		let empty_in = Filter::new(
7879			"id".to_string(),
7880			FilterOperator::In,
7881			FilterValue::List(vec![]),
7882		);
7883		assert!(!empty_in.is_always_true());
7884		assert!(empty_in.is_always_false());
7885		assert!(FilterCondition::not(empty_in.clone()).is_always_true());
7886		assert!(!FilterCondition::not(empty_in).is_always_false());
7887		assert!(!FilterCondition::not(empty_not_in).is_always_true());
7888	}
7889
7890	#[test]
7891	fn test_filter_operators() {
7892		let queryset = QuerySet::<TestUser>::new()
7893			.filter(Filter::new(
7894				"id".to_string(),
7895				FilterOperator::Gte,
7896				FilterValue::Integer(5),
7897			))
7898			.filter(Filter::new(
7899				"username".to_string(),
7900				FilterOperator::Ne,
7901				FilterValue::String("admin".to_string()),
7902			));
7903
7904		let (sql, params) = queryset.delete_sql();
7905
7906		assert_eq!(
7907			sql,
7908			"DELETE FROM \"test_users\" WHERE (\"id\" >= $1 AND \"username\" <> $2)"
7909		);
7910		assert_eq!(params, vec!["5", "admin"]);
7911	}
7912
7913	#[test]
7914	fn test_null_value_filter() {
7915		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
7916			"email".to_string(),
7917			FilterOperator::Eq,
7918			FilterValue::Null,
7919		));
7920
7921		let (sql, params) = queryset.delete_sql();
7922
7923		assert_eq!(sql, "DELETE FROM \"test_users\" WHERE \"email\" IS NULL");
7924		assert_eq!(params, Vec::<String>::new());
7925	}
7926
7927	#[test]
7928	fn test_not_null_value_filter() {
7929		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
7930			"email".to_string(),
7931			FilterOperator::Ne,
7932			FilterValue::Null,
7933		));
7934
7935		let (sql, params) = queryset.delete_sql();
7936
7937		assert_eq!(
7938			sql,
7939			"DELETE FROM \"test_users\" WHERE \"email\" IS NOT NULL"
7940		);
7941		assert_eq!(params, Vec::<String>::new());
7942	}
7943
7944	// Query Optimization Tests
7945
7946	#[test]
7947	fn test_select_related_query_generation() {
7948		// Test that select_related_query() generates SelectStatement correctly
7949		let queryset = QuerySet::<TestUser>::new().select_related(&["profile", "department"]);
7950
7951		let stmt = queryset.select_related_query();
7952
7953		// Convert to SQL to verify structure
7954		use reinhardt_query::prelude::{PostgresQueryBuilder, QueryStatementBuilder};
7955		let sql = stmt.build(PostgresQueryBuilder).0;
7956
7957		assert!(sql.contains("SELECT"));
7958		assert!(sql.contains("test_users"));
7959		assert!(sql.contains("LEFT JOIN"));
7960	}
7961
7962	#[test]
7963	fn test_prefetch_related_queries_generation() {
7964		// Test that prefetch_related_queries() generates correct queries
7965		let queryset = QuerySet::<TestUser>::new().prefetch_related(&["posts", "comments"]);
7966		let pk_values = vec![1, 2, 3];
7967
7968		let queries = queryset.prefetch_related_queries(&pk_values);
7969
7970		// Should generate 2 queries (one for each prefetch field)
7971		assert_eq!(queries.len(), 2);
7972
7973		// Each query should be a (field_name, SelectStatement) tuple
7974		assert_eq!(queries[0].0, "posts");
7975		assert_eq!(queries[1].0, "comments");
7976	}
7977
7978	#[test]
7979	fn test_prefetch_related_queries_empty_pk_values() {
7980		let queryset = QuerySet::<TestUser>::new().prefetch_related(&["posts", "comments"]);
7981		let pk_values = vec![];
7982
7983		let queries = queryset.prefetch_related_queries(&pk_values);
7984
7985		// Should return empty vector when no PK values provided
7986		assert_eq!(queries.len(), 0);
7987	}
7988
7989	#[test]
7990	fn test_select_related_and_prefetch_together() {
7991		// Test that both can be used together
7992		let queryset = QuerySet::<TestUser>::new()
7993			.select_related(&["profile"])
7994			.prefetch_related(&["posts", "comments"]);
7995
7996		// Check select_related generates query
7997		let select_stmt = queryset.select_related_query();
7998		use reinhardt_query::prelude::{PostgresQueryBuilder, QueryStatementBuilder};
7999		let select_sql = select_stmt.build(PostgresQueryBuilder).0;
8000		assert!(select_sql.contains("LEFT JOIN"));
8001
8002		// Check prefetch_related generates queries
8003		let pk_values = vec![1, 2, 3];
8004		let prefetch_queries = queryset.prefetch_related_queries(&pk_values);
8005		assert_eq!(prefetch_queries.len(), 2);
8006	}
8007
8008	// SmallVec Optimization Tests
8009
8010	#[test]
8011	fn test_smallvec_stack_allocation_within_capacity() {
8012		// Test with exactly 10 filters (at capacity)
8013		let mut queryset = QuerySet::<TestUser>::new();
8014
8015		for i in 0..10 {
8016			queryset = queryset.filter(Filter::new(
8017				format!("field{}", i),
8018				FilterOperator::Eq,
8019				FilterValue::Integer(i as i64),
8020			));
8021		}
8022
8023		// Verify all filters are stored
8024		assert_eq!(queryset.filters.len(), 10);
8025
8026		// Generate SQL to ensure filters work correctly
8027		let (sql, params) = queryset.delete_sql();
8028		assert!(sql.contains("WHERE"));
8029		assert_eq!(params.len(), 10);
8030	}
8031
8032	#[test]
8033	fn test_smallvec_heap_fallback_over_capacity() {
8034		// Test with 15 filters (5 over capacity, should trigger heap allocation)
8035		let mut queryset = QuerySet::<TestUser>::new();
8036
8037		for i in 0..15 {
8038			queryset = queryset.filter(Filter::new(
8039				format!("field{}", i),
8040				FilterOperator::Eq,
8041				FilterValue::Integer(i as i64),
8042			));
8043		}
8044
8045		// Verify all filters are stored (SmallVec automatically spills to heap)
8046		assert_eq!(queryset.filters.len(), 15);
8047
8048		// Generate SQL to ensure filters work correctly even after heap fallback
8049		let (sql, params) = queryset.delete_sql();
8050		assert!(sql.contains("WHERE"));
8051		assert_eq!(params.len(), 15);
8052	}
8053
8054	#[test]
8055	fn test_smallvec_typical_use_case_1_5_filters() {
8056		// Test typical use case: 1-5 filters (well within stack capacity)
8057		let queryset = QuerySet::<TestUser>::new()
8058			.filter(Filter::new(
8059				"username".to_string(),
8060				FilterOperator::StartsWith,
8061				FilterValue::String("admin".to_string()),
8062			))
8063			.filter(Filter::new(
8064				"email".to_string(),
8065				FilterOperator::Contains,
8066				FilterValue::String("example.com".to_string()),
8067			))
8068			.filter(Filter::new(
8069				"id".to_string(),
8070				FilterOperator::Gt,
8071				FilterValue::Integer(100),
8072			));
8073
8074		// Verify filters stored correctly
8075		assert_eq!(queryset.filters.len(), 3);
8076
8077		// Generate SQL
8078		let (sql, params) = queryset.delete_sql();
8079		assert!(sql.contains("WHERE"));
8080		assert!(sql.contains("\"username\" LIKE"));
8081		assert!(sql.contains("\"email\" LIKE"));
8082		assert!(sql.contains("\"id\" >"));
8083		assert_eq!(params.len(), 3);
8084	}
8085
8086	#[test]
8087	fn test_smallvec_empty_initialization() {
8088		// Test that empty SmallVec is initialized correctly
8089		let queryset = QuerySet::<TestUser>::new();
8090
8091		assert_eq!(queryset.filters.len(), 0);
8092		assert!(queryset.filters.is_empty());
8093
8094		// Generate SQL with no filters should not include WHERE clause
8095		let (where_clause, params) = queryset.build_where_clause();
8096		assert!(where_clause.is_empty());
8097		assert!(params.is_empty());
8098	}
8099
8100	#[test]
8101	fn test_smallvec_single_filter() {
8102		// Test single filter (minimal usage)
8103		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8104			"id".to_string(),
8105			FilterOperator::Eq,
8106			FilterValue::Integer(1),
8107		));
8108
8109		assert_eq!(queryset.filters.len(), 1);
8110
8111		let (sql, params) = queryset.delete_sql();
8112		assert_eq!(sql, "DELETE FROM \"test_users\" WHERE \"id\" = $1");
8113		assert_eq!(params, vec!["1"]);
8114	}
8115
8116	#[rstest]
8117	#[case("username", r#""username""#)]
8118	#[case("user_id", r#""user_id""#)]
8119	#[case(r#"a"b"#, r#""a""b""#)]
8120	#[case("field; DROP TABLE users", r#""field; DROP TABLE users""#)]
8121	#[case("", r#""""#)]
8122	#[case("authors.id", r#""authors"."id""#)]
8123	#[case("schema.table.column", r#""schema"."table"."column""#)]
8124	fn test_quote_identifier(#[case] input: &str, #[case] expected: &str) {
8125		// Arrange
8126		// input and expected provided by rstest cases
8127
8128		// Act
8129		let result = super::quote_identifier(input);
8130
8131		// Assert
8132		assert_eq!(result, expected);
8133	}
8134
8135	#[rstest]
8136	fn test_outerref_filter_uses_safe_quoting() {
8137		// Arrange
8138		use crate::orm::expressions::OuterRef;
8139		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8140			"author_id".to_string(),
8141			FilterOperator::Eq,
8142			FilterValue::OuterRef(OuterRef::new("id")),
8143		));
8144
8145		// Act
8146		let sql = queryset.to_sql();
8147
8148		// Assert
8149		assert_eq!(
8150			sql,
8151			r#"SELECT * FROM "test_users" WHERE "author_id" = "id""#
8152		);
8153	}
8154
8155	#[rstest]
8156	fn test_array_contains_filter_quotes_field() {
8157		// Arrange
8158		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8159			"tags".to_string(),
8160			FilterOperator::ArrayContains,
8161			FilterValue::Array(vec!["rust".to_string(), "web".to_string()]),
8162		));
8163
8164		// Act
8165		let sql = queryset.to_sql();
8166
8167		// Assert
8168		assert_eq!(
8169			sql,
8170			r#"SELECT * FROM "test_users" WHERE "tags" @> ARRAY['rust', 'web']"#
8171		);
8172	}
8173
8174	#[rstest]
8175	fn test_outerref_dot_separated_renders_qualified_column() {
8176		// Arrange
8177		use crate::orm::expressions::OuterRef;
8178		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8179			"author_id".to_string(),
8180			FilterOperator::Eq,
8181			FilterValue::OuterRef(OuterRef::new("authors.id")),
8182		));
8183
8184		// Act
8185		let sql = queryset.to_sql();
8186
8187		// Assert
8188		assert_eq!(
8189			sql,
8190			r#"SELECT * FROM "test_users" WHERE "author_id" = "authors"."id""#
8191		);
8192	}
8193
8194	#[rstest]
8195	fn test_injection_attempt_in_field_name_is_quoted() {
8196		// Arrange
8197		// Attempt SQL injection via field name with double quote
8198		let malicious_field = r#"id" OR 1=1 --"#.to_string();
8199
8200		// Act
8201		let quoted = super::quote_identifier(&malicious_field);
8202
8203		// Assert
8204		// The double quote inside is escaped, preventing injection
8205		assert_eq!(quoted, r#""id"" OR 1=1 --""#);
8206		// Verify the quote is not broken out of
8207		assert!(quoted.starts_with('"'));
8208		assert!(quoted.ends_with('"'));
8209	}
8210
8211	#[rstest]
8212	#[should_panic(expected = "SQL identifier must not contain null bytes")]
8213	fn test_quote_identifier_rejects_null_bytes() {
8214		// Arrange
8215		let field_with_null = "field\0name";
8216
8217		// Act
8218		super::quote_identifier(field_with_null);
8219
8220		// Assert - should panic before reaching here
8221	}
8222
8223	#[rstest]
8224	#[case(FilterOperator::Ne, "<>")]
8225	#[case(FilterOperator::Gt, ">")]
8226	#[case(FilterOperator::Gte, ">=")]
8227	#[case(FilterOperator::Lt, "<")]
8228	#[case(FilterOperator::Lte, "<=")]
8229	fn test_outerref_comparison_operators(#[case] op: FilterOperator, #[case] sql_op: &str) {
8230		// Arrange
8231		use crate::orm::expressions::OuterRef;
8232		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8233			"author_id".to_string(),
8234			op,
8235			FilterValue::OuterRef(OuterRef::new("id")),
8236		));
8237
8238		// Act
8239		let sql = queryset.to_sql();
8240
8241		// Assert
8242		let expected = format!(
8243			r#"SELECT * FROM "test_users" WHERE "author_id" {} "id""#,
8244			sql_op
8245		);
8246		assert_eq!(sql, expected);
8247	}
8248
8249	#[rstest]
8250	fn test_array_contained_by_filter_quotes_field() {
8251		// Arrange
8252		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8253			"tags".to_string(),
8254			FilterOperator::ArrayContainedBy,
8255			FilterValue::Array(vec!["rust".to_string()]),
8256		));
8257
8258		// Act
8259		let sql = queryset.to_sql();
8260
8261		// Assert
8262		assert_eq!(
8263			sql,
8264			r#"SELECT * FROM "test_users" WHERE "tags" <@ ARRAY['rust']"#
8265		);
8266	}
8267
8268	#[rstest]
8269	fn test_array_overlap_filter_quotes_field() {
8270		// Arrange
8271		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8272			"tags".to_string(),
8273			FilterOperator::ArrayOverlap,
8274			FilterValue::Array(vec!["rust".to_string()]),
8275		));
8276
8277		// Act
8278		let sql = queryset.to_sql();
8279
8280		// Assert
8281		assert_eq!(
8282			sql,
8283			r#"SELECT * FROM "test_users" WHERE "tags" && ARRAY['rust']"#
8284		);
8285	}
8286
8287	#[rstest]
8288	fn test_full_text_match_filter_quotes_field() {
8289		// Arrange
8290		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8291			"content".to_string(),
8292			FilterOperator::FullTextMatch,
8293			FilterValue::String("search term".to_string()),
8294		));
8295
8296		// Act
8297		let sql = queryset.to_sql();
8298
8299		// Assert
8300		assert_eq!(
8301			sql,
8302			r#"SELECT * FROM "test_users" WHERE "content" @@ plainto_tsquery('english', 'search term')"#
8303		);
8304	}
8305
8306	#[rstest]
8307	fn test_jsonb_contains_filter_quotes_field() {
8308		// Arrange
8309		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8310			"metadata".to_string(),
8311			FilterOperator::JsonbContains,
8312			FilterValue::String(r#"{"key": "value"}"#.to_string()),
8313		));
8314
8315		// Act
8316		let sql = queryset.to_sql();
8317
8318		// Assert
8319		assert_eq!(
8320			sql,
8321			r#"SELECT * FROM "test_users" WHERE "metadata" @> '{"key": "value"}'::jsonb"#
8322		);
8323	}
8324
8325	#[rstest]
8326	fn test_jsonb_contained_by_filter_quotes_field() {
8327		// Arrange
8328		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8329			"metadata".to_string(),
8330			FilterOperator::JsonbContainedBy,
8331			FilterValue::String(r#"{"key": "value"}"#.to_string()),
8332		));
8333
8334		// Act
8335		let sql = queryset.to_sql();
8336
8337		// Assert
8338		assert_eq!(
8339			sql,
8340			r#"SELECT * FROM "test_users" WHERE "metadata" <@ '{"key": "value"}'::jsonb"#
8341		);
8342	}
8343
8344	#[rstest]
8345	fn test_jsonb_key_exists_filter_quotes_field() {
8346		// Arrange
8347		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8348			"metadata".to_string(),
8349			FilterOperator::JsonbKeyExists,
8350			FilterValue::String("key".to_string()),
8351		));
8352
8353		// Act
8354		let sql = queryset.to_sql();
8355
8356		// Assert
8357		assert_eq!(
8358			sql,
8359			r#"SELECT * FROM "test_users" WHERE "metadata" ? 'key'"#
8360		);
8361	}
8362
8363	#[rstest]
8364	fn test_jsonb_any_key_exists_filter_quotes_field() {
8365		// Arrange
8366		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8367			"metadata".to_string(),
8368			FilterOperator::JsonbAnyKeyExists,
8369			FilterValue::Array(vec!["key1".to_string(), "key2".to_string()]),
8370		));
8371
8372		// Act
8373		let sql = queryset.to_sql();
8374
8375		// Assert
8376		assert_eq!(
8377			sql,
8378			r#"SELECT * FROM "test_users" WHERE "metadata" ?| array['key1', 'key2']"#
8379		);
8380	}
8381
8382	#[rstest]
8383	fn test_jsonb_all_keys_exist_filter_quotes_field() {
8384		// Arrange
8385		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8386			"metadata".to_string(),
8387			FilterOperator::JsonbAllKeysExist,
8388			FilterValue::Array(vec!["key1".to_string(), "key2".to_string()]),
8389		));
8390
8391		// Act
8392		let sql = queryset.to_sql();
8393
8394		// Assert
8395		assert_eq!(
8396			sql,
8397			r#"SELECT * FROM "test_users" WHERE "metadata" ?& array['key1', 'key2']"#
8398		);
8399	}
8400
8401	#[rstest]
8402	fn test_jsonb_path_exists_filter_quotes_field() {
8403		// Arrange
8404		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8405			"metadata".to_string(),
8406			FilterOperator::JsonbPathExists,
8407			FilterValue::String("$.key".to_string()),
8408		));
8409
8410		// Act
8411		let sql = queryset.to_sql();
8412
8413		// Assert
8414		assert_eq!(
8415			sql,
8416			r#"SELECT * FROM "test_users" WHERE "metadata" @'$.key' "#
8417		);
8418	}
8419
8420	#[rstest]
8421	#[case(
8422		Filter::new("username", FilterOperator::IExact, FilterValue::String("Alice".to_string())),
8423		r#"SELECT * FROM "test_users" WHERE "username" ILIKE 'Alice' ESCAPE '\'"#
8424	)]
8425	#[case(
8426		Filter::new("email", FilterOperator::IContains, FilterValue::String("example.com".to_string())),
8427		r#"SELECT * FROM "test_users" WHERE "email" ILIKE '%example.com%' ESCAPE '\'"#
8428	)]
8429	#[case(
8430		Filter::new("username", FilterOperator::IStartsWith, FilterValue::String("ali".to_string())),
8431		r#"SELECT * FROM "test_users" WHERE "username" ILIKE 'ali%' ESCAPE '\'"#
8432	)]
8433	#[case(
8434		Filter::new("username", FilterOperator::IEndsWith, FilterValue::String("ice".to_string())),
8435		r#"SELECT * FROM "test_users" WHERE "username" ILIKE '%ice' ESCAPE '\'"#
8436	)]
8437	#[case(
8438		Filter::new("username", FilterOperator::Regex, FilterValue::String("^a".to_string())),
8439		r#"SELECT * FROM "test_users" WHERE "username" ~ '^a'"#
8440	)]
8441	#[case(
8442		Filter::new("username", FilterOperator::IRegex, FilterValue::String("^a".to_string())),
8443		r#"SELECT * FROM "test_users" WHERE "username" ~* '^a'"#
8444	)]
8445	fn test_django_style_string_lookup_filters(#[case] filter: Filter, #[case] expected: &str) {
8446		// Arrange
8447		let queryset = QuerySet::<TestUser>::new().filter(filter);
8448
8449		// Act
8450		let sql = queryset.to_sql();
8451
8452		// Assert
8453		assert_eq!(sql, expected);
8454	}
8455
8456	#[rstest]
8457	fn test_filter_or_chain_generates_expected_sql() {
8458		// Arrange
8459		let condition = TestUser::field_username()
8460			.exact("alice")
8461			.or(TestUser::field_email().icontains("example.com"));
8462		let queryset = QuerySet::<TestUser>::new().filter(condition);
8463
8464		// Act
8465		let sql = queryset.to_sql();
8466
8467		// Assert
8468		assert_eq!(
8469			sql,
8470			r#"SELECT * FROM "test_users" WHERE ("username" = 'alice' OR "email" ILIKE '%example.com%' ESCAPE '\')"#
8471		);
8472	}
8473
8474	#[rstest]
8475	fn test_filter_and_chain_generates_expected_sql() {
8476		// Arrange
8477		let condition = TestUser::field_username()
8478			.exact("alice")
8479			.and(TestUser::field_id().gte(10));
8480		let queryset = QuerySet::<TestUser>::new().filter(condition);
8481
8482		// Act
8483		let sql = queryset.to_sql();
8484
8485		// Assert
8486		assert_eq!(
8487			sql,
8488			r#"SELECT * FROM "test_users" WHERE ("username" = 'alice' AND "id" >= 10)"#
8489		);
8490	}
8491
8492	#[rstest]
8493	fn test_filter_not_chain_generates_expected_sql() {
8494		// Arrange
8495		let condition = TestUser::field_username().exact("alice").not();
8496		let queryset = QuerySet::<TestUser>::new().filter(condition);
8497
8498		// Act
8499		let sql = queryset.to_sql();
8500
8501		// Assert
8502		assert_eq!(
8503			sql,
8504			r#"SELECT * FROM "test_users" WHERE NOT "username" = 'alice'"#
8505		);
8506	}
8507
8508	#[rstest]
8509	fn test_composite_only_filter_is_recognized_by_delete_sql() {
8510		// Arrange
8511		let queryset = QuerySet::<TestUser>::new().filter(
8512			TestUser::field_username()
8513				.exact("alice")
8514				.or(TestUser::field_email().icontains("example.com")),
8515		);
8516
8517		// Act
8518		let (sql, params) = queryset.delete_sql();
8519
8520		// Assert
8521		assert_eq!(
8522			sql,
8523			r#"DELETE FROM "test_users" WHERE ("username" = $1 OR "email" ILIKE $2 ESCAPE '\')"#
8524		);
8525		assert_eq!(params, vec!["alice", "%example.com%"]);
8526	}
8527
8528	#[rstest]
8529	fn test_over_deep_filter_condition_returns_error_and_to_sql_stays_safe() {
8530		// Arrange
8531		let mut condition = FilterCondition::Single(TestUser::field_username().exact("alice"));
8532		for _ in 0..=MAX_FILTER_CONDITION_DEPTH {
8533			condition = FilterCondition::not(condition);
8534		}
8535		let queryset = QuerySet::<TestUser>::new().filter(condition);
8536
8537		// Act
8538		let result = queryset.build_where_condition();
8539		let sql = queryset.to_sql();
8540
8541		// Assert
8542		assert!(matches!(
8543			result,
8544			Err(reinhardt_core::exception::Error::Validation(_))
8545		));
8546		assert_eq!(sql, r#"SELECT * FROM "test_users" WHERE FALSE"#);
8547	}
8548
8549	#[rstest]
8550	fn test_empty_or_filter_condition_is_false() {
8551		let queryset = QuerySet::<TestUser>::new().filter(FilterCondition::Or(Vec::new()));
8552
8553		assert_eq!(
8554			queryset.to_sql(),
8555			r#"SELECT * FROM "test_users" WHERE FALSE"#
8556		);
8557	}
8558
8559	#[rstest]
8560	fn test_empty_not_in_filter_condition_is_always_true() {
8561		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8562			"id",
8563			FilterOperator::NotIn,
8564			FilterValue::List(vec![]),
8565		));
8566
8567		assert_eq!(
8568			queryset.to_sql(),
8569			r#"SELECT * FROM "test_users" WHERE TRUE"#
8570		);
8571	}
8572
8573	#[rstest]
8574	fn test_not_empty_and_filter_condition_is_false() {
8575		let queryset = QuerySet::<TestUser>::new().filter(FilterCondition::Not(Box::new(
8576			FilterCondition::And(Vec::new()),
8577		)));
8578
8579		assert_eq!(
8580			queryset.to_sql(),
8581			r#"SELECT * FROM "test_users" WHERE NOT TRUE"#
8582		);
8583	}
8584
8585	#[rstest]
8586	#[case(
8587		Filter::new("email", FilterOperator::IContains, FilterValue::String("100%_match\\".to_string())),
8588		r#"SELECT * FROM "test_users" WHERE "email" ILIKE '%100\%\_match\\%' ESCAPE '\'"#
8589	)]
8590	#[case(
8591		Filter::new("username", FilterOperator::IExact, FilterValue::String("alice_admin".to_string())),
8592		r#"SELECT * FROM "test_users" WHERE "username" ILIKE 'alice\_admin' ESCAPE '\'"#
8593	)]
8594	fn test_django_style_case_insensitive_like_filters_escape_metacharacters(
8595		#[case] filter: Filter,
8596		#[case] expected: &str,
8597	) {
8598		// Arrange
8599		let queryset = QuerySet::<TestUser>::new().filter(filter);
8600
8601		// Act
8602		let sql = queryset.to_sql();
8603
8604		// Assert
8605		assert_eq!(sql, expected);
8606	}
8607
8608	#[rstest]
8609	#[case(
8610		Filter::new("email", FilterOperator::Contains, FilterValue::String("100%_match\\".to_string())),
8611		r#"SELECT * FROM "test_users" WHERE "email" LIKE '%100\%\_match\\%' ESCAPE '\'"#
8612	)]
8613	#[case(
8614		Filter::new("username", FilterOperator::StartsWith, FilterValue::String("alice_admin".to_string())),
8615		r#"SELECT * FROM "test_users" WHERE "username" LIKE 'alice\_admin%' ESCAPE '\'"#
8616	)]
8617	#[case(
8618		Filter::new("username", FilterOperator::EndsWith, FilterValue::String("100%".to_string())),
8619		r#"SELECT * FROM "test_users" WHERE "username" LIKE '%100\%' ESCAPE '\'"#
8620	)]
8621	fn test_django_style_case_sensitive_like_filters_escape_metacharacters(
8622		#[case] filter: Filter,
8623		#[case] expected: &str,
8624	) {
8625		// Arrange
8626		let queryset = QuerySet::<TestUser>::new().filter(filter);
8627
8628		// Act
8629		let sql = queryset.to_sql();
8630
8631		// Assert
8632		assert_eq!(sql, expected);
8633	}
8634
8635	#[rstest]
8636	fn test_django_style_is_in_filter_accepts_typed_values() {
8637		// Arrange
8638		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8639			"id",
8640			FilterOperator::In,
8641			FilterValue::List(vec![FilterValue::Integer(1), FilterValue::Integer(2)]),
8642		));
8643
8644		// Act
8645		let sql = queryset.to_sql();
8646
8647		// Assert
8648		assert_eq!(sql, r#"SELECT * FROM "test_users" WHERE "id" IN (1, 2)"#);
8649	}
8650
8651	#[rstest]
8652	fn test_django_style_between_range_filter() {
8653		// Arrange
8654		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8655			"id",
8656			FilterOperator::Range,
8657			FilterValue::Range(
8658				Box::new(FilterValue::Integer(10)),
8659				Box::new(FilterValue::Integer(20)),
8660			),
8661		));
8662
8663		// Act
8664		let sql = queryset.to_sql();
8665
8666		// Assert
8667		assert_eq!(
8668			sql,
8669			r#"SELECT * FROM "test_users" WHERE "id" BETWEEN 10 AND 20"#
8670		);
8671	}
8672
8673	#[rstest]
8674	fn test_django_style_date_part_filter_expression() {
8675		// Arrange
8676		let queryset = QuerySet::<TestUser>::new().filter(Filter::expression(
8677			"EXTRACT(YEAR FROM \"created_at\")",
8678			FilterOperator::Eq,
8679			FilterValue::Integer(2026),
8680		));
8681
8682		// Act
8683		let sql = queryset.to_sql();
8684
8685		// Assert
8686		assert_eq!(
8687			sql,
8688			r#"SELECT * FROM "test_users" WHERE EXTRACT(YEAR FROM "created_at") = 2026"#
8689		);
8690	}
8691
8692	#[rstest]
8693	fn test_public_filter_new_treats_expression_like_field_as_quoted_column() {
8694		// Arrange
8695		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8696			"__reinhardt_filter_expr:EXTRACT(YEAR FROM \"created_at\")",
8697			FilterOperator::Eq,
8698			FilterValue::Integer(2026),
8699		));
8700
8701		// Act
8702		let sql = queryset.to_sql();
8703
8704		// Assert
8705		assert_eq!(
8706			sql,
8707			r#"SELECT * FROM "test_users" WHERE "__reinhardt_filter_expr:EXTRACT(YEAR FROM ""created_at"")" = 2026"#
8708		);
8709	}
8710
8711	#[rstest]
8712	fn test_public_column_filter_uses_mutated_field_consistently() {
8713		// Arrange
8714		let mut filter = Filter::new(
8715			"username",
8716			FilterOperator::Eq,
8717			FilterValue::String("alice".into()),
8718		);
8719		filter.field = "email".to_string();
8720		let queryset = QuerySet::<TestUser>::new().filter(filter);
8721
8722		// Act
8723		let sql = queryset.to_sql();
8724
8725		// Assert
8726		assert_eq!(sql, r#"SELECT * FROM "test_users" WHERE "email" = 'alice'"#);
8727	}
8728
8729	#[rstest]
8730	fn test_mutated_transformed_filter_field_falls_back_to_quoted_column() {
8731		// Arrange
8732		let mut filter = TestUser::field_created_at().year().eq(2026);
8733		filter.field = "EXTRACT(MONTH FROM \"created_at\")".to_string();
8734		let queryset = QuerySet::<TestUser>::new().filter(filter);
8735
8736		// Act
8737		let sql = queryset.to_sql();
8738
8739		// Assert
8740		assert_eq!(
8741			sql,
8742			r#"SELECT * FROM "test_users" WHERE "EXTRACT(MONTH FROM ""created_at"")" = 2026"#
8743		);
8744	}
8745
8746	#[rstest]
8747	fn test_field_accessor_lookup_helpers_generate_expected_sql() {
8748		// Arrange
8749		let queryset = QuerySet::<TestUser>::new()
8750			.filter(TestUser::field_username().exact("alice"))
8751			.filter(TestUser::field_email().icontains("example.com"))
8752			.filter(TestUser::field_id().is_in([1_i64, 2, 3]))
8753			.filter(TestUser::field_created_at().year().gte(2026));
8754
8755		// Act
8756		let sql = queryset.to_sql();
8757
8758		// Assert
8759		assert_eq!(
8760			sql,
8761			r#"SELECT * FROM "test_users" WHERE ("username" = 'alice' AND "email" ILIKE '%example.com%' ESCAPE '\' AND "id" IN (1, 2, 3) AND EXTRACT(YEAR FROM "created_at") >= 2026)"#
8762		);
8763	}
8764
8765	#[rstest]
8766	fn test_field_accessor_null_not_in_and_range_helpers_generate_expected_sql() {
8767		// Arrange
8768		let queryset = QuerySet::<TestUser>::new()
8769			.filter(TestUser::field_email().is_not_null())
8770			.filter(TestUser::field_id().not_in([10_i64, 20]))
8771			.filter(TestUser::field_id().range(100_i64, 200));
8772
8773		// Act
8774		let sql = queryset.to_sql();
8775
8776		// Assert
8777		assert_eq!(
8778			sql,
8779			r#"SELECT * FROM "test_users" WHERE ("email" IS NOT NULL AND "id" NOT IN (10, 20) AND "id" BETWEEN 100 AND 200)"#
8780		);
8781	}
8782
8783	#[rstest]
8784	fn test_field_accessor_string_lookup_variants_generate_expected_sql() {
8785		// Arrange
8786		let queryset = QuerySet::<TestUser>::new()
8787			.filter(TestUser::field_username().contains("lic"))
8788			.filter(TestUser::field_username().starts_with("a"))
8789			.filter(TestUser::field_username().ends_with("e"))
8790			.filter(TestUser::field_username().istarts_with("AL"))
8791			.filter(TestUser::field_username().iends_with("CE"))
8792			.filter(TestUser::field_username().regex("^a.*e$"))
8793			.filter(TestUser::field_username().iregex("^A.*E$"));
8794
8795		// Act
8796		let sql = queryset.to_sql();
8797
8798		// Assert
8799		assert_eq!(
8800			sql,
8801			r#"SELECT * FROM "test_users" WHERE ("username" LIKE '%lic%' ESCAPE '\' AND "username" LIKE 'a%' ESCAPE '\' AND "username" LIKE '%e' ESCAPE '\' AND "username" ILIKE 'AL%' ESCAPE '\' AND "username" ILIKE '%CE' ESCAPE '\' AND "username" ~ '^a.*e$' AND "username" ~* '^A.*E$')"#
8802		);
8803	}
8804
8805	#[rstest]
8806	#[case(TestUser::field_created_at().date().eq("2026-06-10"), r#"SELECT * FROM "test_users" WHERE DATE("created_at") = '2026-06-10'"#)]
8807	#[case(TestUser::field_created_at().time().eq("05:00:00"), r#"SELECT * FROM "test_users" WHERE TIME("created_at") = '05:00:00'"#)]
8808	#[case(TestUser::field_created_at().month().eq(6), r#"SELECT * FROM "test_users" WHERE EXTRACT(MONTH FROM "created_at") = 6"#)]
8809	#[case(TestUser::field_created_at().day().eq(10), r#"SELECT * FROM "test_users" WHERE EXTRACT(DAY FROM "created_at") = 10"#)]
8810	#[case(TestUser::field_created_at().week().eq(24), r#"SELECT * FROM "test_users" WHERE EXTRACT(WEEK FROM "created_at") = 24"#)]
8811	#[case(TestUser::field_created_at().week_day().eq(4), r#"SELECT * FROM "test_users" WHERE (EXTRACT(DOW FROM "created_at") + 1) = 4"#)]
8812	#[case(TestUser::field_created_at().iso_week_day().eq(3), r#"SELECT * FROM "test_users" WHERE EXTRACT(ISODOW FROM "created_at") = 3"#)]
8813	#[case(TestUser::field_created_at().quarter().eq(2), r#"SELECT * FROM "test_users" WHERE EXTRACT(QUARTER FROM "created_at") = 2"#)]
8814	#[case(TestUser::field_created_at().hour().gte(5), r#"SELECT * FROM "test_users" WHERE EXTRACT(HOUR FROM "created_at") >= 5"#)]
8815	#[case(TestUser::field_created_at().minute().lt(30), r#"SELECT * FROM "test_users" WHERE EXTRACT(MINUTE FROM "created_at") < 30"#)]
8816	#[case(TestUser::field_created_at().second().lte(59), r#"SELECT * FROM "test_users" WHERE EXTRACT(SECOND FROM "created_at") <= 59"#)]
8817	fn test_field_accessor_date_time_transforms_generate_expected_sql(
8818		#[case] filter: Filter,
8819		#[case] expected: &str,
8820	) {
8821		// Arrange
8822		let queryset = QuerySet::<TestUser>::new().filter(filter);
8823
8824		// Act
8825		let sql = queryset.to_sql();
8826
8827		// Assert
8828		assert_eq!(sql, expected);
8829	}
8830
8831	#[rstest]
8832	fn test_field_accessor_postgres_array_jsonb_and_range_helpers_generate_expected_sql() {
8833		// Arrange
8834		let queryset = QuerySet::<TestUser>::new()
8835			.filter(TestUser::field_tags().array_contains(["rust", "async"]))
8836			.filter(TestUser::field_tags().array_overlap(["web", "orm"]))
8837			.filter(TestUser::field_metadata().jsonb_contains(r#"{"active": true}"#))
8838			.filter(TestUser::field_metadata().jsonb_has_any_keys(["tier", "plan"]))
8839			.filter(TestUser::field_active_period().range_overlaps("[2026-01-01,2027-01-01)"));
8840
8841		// Act
8842		let sql = queryset.to_sql();
8843
8844		// Assert
8845		assert_eq!(
8846			sql,
8847			r#"SELECT * FROM "test_users" WHERE ("tags" @> ARRAY['rust', 'async'] AND "tags" && ARRAY['web', 'orm'] AND "metadata" @> '{"active": true}'::jsonb AND "metadata" ?| array['tier', 'plan'] AND "active_period" && '[2026-01-01,2027-01-01)')"#
8848		);
8849	}
8850
8851	#[rstest]
8852	fn test_complex_django_style_lookup_query_combines_order_distinct_and_limit() {
8853		// Arrange
8854		let queryset = QuerySet::<TestUser>::new()
8855			.filter(TestUser::field_email().icontains("example.com"))
8856			.filter(TestUser::field_username().is_not_null())
8857			.filter(TestUser::field_created_at().year().range(2024, 2026))
8858			.distinct()
8859			.order_by(&["-created_at", "username"])
8860			.limit(25)
8861			.offset(50);
8862
8863		// Act
8864		let sql = queryset.to_sql();
8865
8866		// Assert
8867		assert_eq!(
8868			sql,
8869			r#"SELECT DISTINCT * FROM "test_users" WHERE ("email" ILIKE '%example.com%' ESCAPE '\' AND "username" IS NOT NULL AND EXTRACT(YEAR FROM "created_at") BETWEEN 2024 AND 2026) ORDER BY "created_at" DESC, "username" ASC LIMIT 25 OFFSET 50"#
8870		);
8871	}
8872
8873	#[rstest]
8874	fn test_range_contains_filter_quotes_field() {
8875		// Arrange
8876		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8877			"age_range".to_string(),
8878			FilterOperator::RangeContains,
8879			FilterValue::String("25".to_string()),
8880		));
8881
8882		// Act
8883		let sql = queryset.to_sql();
8884
8885		// Assert
8886		assert_eq!(
8887			sql,
8888			r#"SELECT * FROM "test_users" WHERE "age_range" @> '25'"#
8889		);
8890	}
8891
8892	#[rstest]
8893	fn test_range_contained_by_filter_quotes_field() {
8894		// Arrange
8895		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8896			"age_range".to_string(),
8897			FilterOperator::RangeContainedBy,
8898			FilterValue::String("[20, 30]".to_string()),
8899		));
8900
8901		// Act
8902		let sql = queryset.to_sql();
8903
8904		// Assert
8905		assert_eq!(
8906			sql,
8907			r#"SELECT * FROM "test_users" WHERE "age_range" <@ '[20, 30]'"#
8908		);
8909	}
8910
8911	#[rstest]
8912	fn test_range_overlaps_filter_quotes_field() {
8913		// Arrange
8914		let queryset = QuerySet::<TestUser>::new().filter(Filter::new(
8915			"age_range".to_string(),
8916			FilterOperator::RangeOverlaps,
8917			FilterValue::String("[20, 30]".to_string()),
8918		));
8919
8920		// Act
8921		let sql = queryset.to_sql();
8922
8923		// Assert
8924		assert_eq!(
8925			sql,
8926			r#"SELECT * FROM "test_users" WHERE "age_range" && '[20, 30]'"#
8927		);
8928	}
8929}