Skip to main content

reinhardt_db/orm/
annotation.rs

1use super::postgres_features::{ArrayAgg, JsonbAgg, JsonbBuildObject, StringAgg, TsRank};
2use crate::orm::aggregation::Aggregate;
3use crate::orm::expressions::{F, Q};
4use crate::orm::query::quote_identifier;
5use serde::{Deserialize, Serialize};
6
7/// Represents an annotation value that can be added to a QuerySet
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub enum AnnotationValue {
10	/// A constant value
11	Value(Value),
12	/// A field reference (F expression)
13	Field(F),
14	/// An aggregation function
15	Aggregate(Aggregate),
16	/// A complex expression combining multiple values
17	Expression(Expression),
18	/// A subquery (scalar subquery in SELECT clause)
19	Subquery(String),
20	// PostgreSQL-specific aggregations
21	/// PostgreSQL array_agg - aggregates values into an array
22	ArrayAgg(ArrayAgg<serde_json::Value>),
23	/// PostgreSQL string_agg - concatenates strings with delimiter
24	StringAgg(StringAgg),
25	/// PostgreSQL jsonb_agg - aggregates values into a JSONB array
26	JsonbAgg(JsonbAgg),
27	/// PostgreSQL jsonb_build_object - builds a JSONB object from key-value pairs
28	JsonbBuildObject(JsonbBuildObject),
29	/// PostgreSQL ts_rank - full-text search ranking score
30	TsRank(TsRank),
31}
32
33/// Constant value types for annotations
34#[derive(Debug, Clone, Serialize, Deserialize)]
35pub enum Value {
36	/// String variant.
37	String(String),
38	/// Int variant.
39	Int(i64),
40	/// Float variant.
41	Float(f64),
42	/// Bool variant.
43	Bool(bool),
44	/// Null variant.
45	Null,
46}
47
48impl Value {
49	/// Documentation for `to_sql`
50	///
51	pub fn to_sql(&self) -> String {
52		match self {
53			Value::String(s) => format!("'{}'", s.replace('\'', "''")),
54			Value::Int(i) => i.to_string(),
55			Value::Float(f) => f.to_string(),
56			Value::Bool(b) => if *b { "TRUE" } else { "FALSE" }.to_string(),
57			Value::Null => "NULL".to_string(),
58		}
59	}
60}
61
62/// Expression types for complex annotations
63#[derive(Debug, Clone, Serialize, Deserialize)]
64pub enum Expression {
65	/// Addition: field1 + field2
66	Add(Box<AnnotationValue>, Box<AnnotationValue>),
67	/// Subtraction: field1 - field2
68	Subtract(Box<AnnotationValue>, Box<AnnotationValue>),
69	/// Multiplication: field1 * field2
70	Multiply(Box<AnnotationValue>, Box<AnnotationValue>),
71	/// Division: field1 / field2
72	Divide(Box<AnnotationValue>, Box<AnnotationValue>),
73	/// CASE WHEN expression
74	Case {
75		/// The whens.
76		whens: Vec<When>,
77		/// The default.
78		default: Option<Box<AnnotationValue>>,
79	},
80	/// COALESCE(field1, field2, ...)
81	Coalesce(Vec<AnnotationValue>),
82}
83
84/// WHEN clause for CASE expressions
85#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct When {
87	/// The condition.
88	pub condition: Q,
89	/// The then.
90	pub then: AnnotationValue,
91}
92
93impl When {
94	/// Create a WHEN clause for CASE expressions
95	///
96	/// # Examples
97	///
98	/// ```
99	/// use reinhardt_db::orm::annotation::{When, AnnotationValue, Value};
100	/// use reinhardt_db::orm::Q;
101	///
102	/// let when = When::new(
103	///     Q::new("status", "=", "active"),
104	///     AnnotationValue::Value(Value::Int(1))
105	/// );
106	/// // Verify the WHEN clause was created
107	/// let sql = when.to_sql();
108	/// assert!(sql.contains("WHEN"));
109	/// assert!(sql.contains("THEN"));
110	/// ```
111	pub fn new(condition: Q, then: AnnotationValue) -> Self {
112		Self { condition, then }
113	}
114	/// Documentation for `to_sql`
115	///
116	pub fn to_sql(&self) -> String {
117		format!(
118			"WHEN {} THEN {}",
119			self.condition.to_sql(),
120			self.then.to_sql()
121		)
122	}
123}
124
125/// Represents an annotation on a QuerySet
126#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct Annotation {
128	/// The alias.
129	pub alias: String,
130	/// The value.
131	pub value: AnnotationValue,
132}
133
134impl Annotation {
135	/// Create a new annotation to add computed fields to QuerySet results
136	///
137	/// # Examples
138	///
139	/// ```
140	/// use reinhardt_db::orm::annotation::{Annotation, AnnotationValue, Value};
141	///
142	/// let annotation = Annotation::new("total", AnnotationValue::Value(Value::Int(100)));
143	/// assert_eq!(annotation.alias, "total");
144	/// assert_eq!(annotation.to_sql(), "100 AS \"total\"");
145	/// ```
146	pub fn new(alias: impl Into<String>, value: AnnotationValue) -> Self {
147		Self {
148			alias: alias.into(),
149			value,
150		}
151	}
152	/// Documentation for `to_sql`
153	///
154	pub fn to_sql(&self) -> String {
155		format!(
156			"{} AS {}",
157			self.value.to_sql(),
158			quote_identifier(&self.alias)
159		)
160	}
161
162	/// Helper method for creating field-based annotations (convenience alias for `new`)
163	///
164	/// This is a convenience method that calls `Annotation::new()` with field-based annotation values.
165	pub fn field(alias: impl Into<String>, value: AnnotationValue) -> Self {
166		Self::new(alias, value)
167	}
168}
169
170impl AnnotationValue {
171	/// Documentation for `to_sql`
172	///
173	pub fn to_sql(&self) -> String {
174		match self {
175			AnnotationValue::Value(v) => v.to_sql(),
176			AnnotationValue::Field(f) => f.to_sql(),
177			AnnotationValue::Aggregate(a) => a.to_sql(),
178			AnnotationValue::Expression(e) => e.to_sql(),
179			AnnotationValue::Subquery(sql) => sql.clone(),
180			// PostgreSQL-specific aggregations
181			AnnotationValue::ArrayAgg(a) => a.to_sql(),
182			AnnotationValue::StringAgg(s) => s.to_sql(),
183			AnnotationValue::JsonbAgg(j) => j.to_sql(),
184			AnnotationValue::JsonbBuildObject(j) => j.to_sql(),
185			AnnotationValue::TsRank(t) => t.to_sql(),
186		}
187	}
188
189	/// Convert to SQL expression without alias (for use in SELECT with expr_as)
190	pub fn to_sql_expr(&self) -> String {
191		match self {
192			AnnotationValue::Value(v) => v.to_sql(),
193			AnnotationValue::Field(f) => f.to_sql(),
194			AnnotationValue::Aggregate(a) => a.to_sql_expr(), // Use to_sql_expr() for aggregates
195			AnnotationValue::Expression(e) => e.to_sql(),
196			AnnotationValue::Subquery(sql) => sql.clone(),
197			// PostgreSQL-specific aggregations (same as to_sql for these)
198			AnnotationValue::ArrayAgg(a) => a.to_sql(),
199			AnnotationValue::StringAgg(s) => s.to_sql(),
200			AnnotationValue::JsonbAgg(j) => j.to_sql(),
201			AnnotationValue::JsonbBuildObject(j) => j.to_sql(),
202			AnnotationValue::TsRank(t) => t.to_sql(),
203		}
204	}
205}
206
207impl Expression {
208	/// Documentation for `to_sql`
209	///
210	pub fn to_sql(&self) -> String {
211		match self {
212			Expression::Add(left, right) => {
213				format!("({} + {})", left.to_sql(), right.to_sql())
214			}
215			Expression::Subtract(left, right) => {
216				format!("({} - {})", left.to_sql(), right.to_sql())
217			}
218			Expression::Multiply(left, right) => {
219				format!("({} * {})", left.to_sql(), right.to_sql())
220			}
221			Expression::Divide(left, right) => {
222				format!("({} / {})", left.to_sql(), right.to_sql())
223			}
224			Expression::Case { whens, default } => {
225				let mut sql = String::from("CASE");
226				for when in whens {
227					sql.push(' ');
228					sql.push_str(&when.to_sql());
229				}
230				if let Some(default_val) = default {
231					sql.push_str(&format!(" ELSE {}", default_val.to_sql()));
232				}
233				sql.push_str(" END");
234				sql
235			}
236			Expression::Coalesce(values) => {
237				let values_sql: Vec<String> = values.iter().map(|v| v.to_sql()).collect();
238				format!("COALESCE({})", values_sql.join(", "))
239			}
240		}
241	}
242}
243
244#[cfg(test)]
245mod tests {
246	use super::*;
247
248	#[test]
249	fn test_value_annotation() {
250		let ann = Annotation::new("is_active", AnnotationValue::Value(Value::Bool(true)));
251		assert_eq!(ann.to_sql(), "TRUE AS \"is_active\"");
252	}
253
254	#[test]
255	fn test_field_annotation() {
256		let ann = Annotation::new("another_price", AnnotationValue::Field(F::new("price")));
257		assert_eq!(ann.to_sql(), "\"price\" AS \"another_price\"");
258	}
259
260	#[test]
261	fn test_annotation_aggregate() {
262		let agg = Aggregate::count(Some("id"));
263		let ann = Annotation::new("num_items", AnnotationValue::Aggregate(agg));
264		let sql = ann.to_sql();
265		assert!(
266			sql.contains("COUNT(id)") && sql.contains("AS \"num_items\""),
267			"SQL should contain 'COUNT(id) AS \"num_items\"'. Got: {}",
268			sql
269		);
270	}
271
272	#[test]
273	fn test_add_expression() {
274		let expr = Expression::Add(
275			Box::new(AnnotationValue::Field(F::new("price"))),
276			Box::new(AnnotationValue::Value(Value::Int(10))),
277		);
278		let ann = Annotation::new("new_price", AnnotationValue::Expression(expr));
279		assert_eq!(ann.to_sql(), "(\"price\" + 10) AS \"new_price\"");
280	}
281
282	#[test]
283	fn test_case_expression() {
284		let expr = Expression::Case {
285			whens: vec![When::new(
286				Q::new("age", ">=", "18"),
287				AnnotationValue::Value(Value::String("adult".into())),
288			)],
289			default: Some(Box::new(AnnotationValue::Value(Value::String(
290				"minor".into(),
291			)))),
292		};
293		let ann = Annotation::new("age_group", AnnotationValue::Expression(expr));
294		let sql = ann.to_sql();
295		assert!(
296			sql.starts_with("CASE") || sql.contains(" CASE "),
297			"SQL should contain CASE clause. Got: {}",
298			sql
299		);
300		assert!(
301			sql.contains("WHEN age >= 18 THEN 'adult'"),
302			"SQL should contain 'WHEN age >= 18 THEN 'adult''. Got: {}",
303			sql
304		);
305		assert!(
306			sql.contains("ELSE 'minor'"),
307			"SQL should contain 'ELSE 'minor''. Got: {}",
308			sql
309		);
310		assert!(
311			sql.ends_with("AS \"age_group\"") || sql.contains(" AS \"age_group\""),
312			"SQL should end with 'AS \"age_group\"'. Got: {}",
313			sql
314		);
315	}
316
317	#[test]
318	fn test_coalesce_expression() {
319		let expr = Expression::Coalesce(vec![
320			AnnotationValue::Field(F::new("nickname")),
321			AnnotationValue::Field(F::new("username")),
322			AnnotationValue::Value(Value::String("Anonymous".into())),
323		]);
324		let ann = Annotation::new("display_name", AnnotationValue::Expression(expr));
325		assert_eq!(
326			ann.to_sql(),
327			"COALESCE(\"nickname\", \"username\", 'Anonymous') AS \"display_name\""
328		);
329	}
330
331	#[test]
332	fn test_complex_arithmetic() {
333		// (price * quantity) + tax
334		let expr = Expression::Add(
335			Box::new(AnnotationValue::Expression(Expression::Multiply(
336				Box::new(AnnotationValue::Field(F::new("price"))),
337				Box::new(AnnotationValue::Field(F::new("quantity"))),
338			))),
339			Box::new(AnnotationValue::Field(F::new("tax"))),
340		);
341		let ann = Annotation::new("total", AnnotationValue::Expression(expr));
342		assert_eq!(
343			ann.to_sql(),
344			"((\"price\" * \"quantity\") + \"tax\") AS \"total\""
345		);
346	}
347
348	#[test]
349	fn test_division_expression() {
350		let expr = Expression::Divide(
351			Box::new(AnnotationValue::Field(F::new("total_sales"))),
352			Box::new(AnnotationValue::Field(F::new("num_orders"))),
353		);
354		let ann = Annotation::new("avg_order_value", AnnotationValue::Expression(expr));
355		assert_eq!(
356			ann.to_sql(),
357			"(\"total_sales\" / \"num_orders\") AS \"avg_order_value\""
358		);
359	}
360}
361// Auto-generated tests for annotation module
362// Translated from Django/SQLAlchemy test suite
363// Total available: 110 | Included: 100
364
365#[cfg(test)]
366mod annotation_extended_tests {
367	use super::*;
368	use crate::orm::Model;
369	use crate::orm::expressions::Q;
370	use crate::orm::query::{Filter, FilterOperator, FilterValue, QuerySet};
371	use reinhardt_core::validators::TableName;
372	use serde::{Deserialize, Serialize};
373
374	#[derive(Debug, Clone, Serialize, Deserialize)]
375	struct TestModel {
376		id: Option<i64>,
377		name: String,
378	}
379
380	#[derive(Clone)]
381	struct TestModelFields;
382
383	impl crate::orm::model::FieldSelector for TestModelFields {
384		fn with_alias(self, _alias: &str) -> Self {
385			self
386		}
387	}
388
389	const TEST_MODEL_TABLE: TableName = TableName::new_const("test_model");
390
391	impl Model for TestModel {
392		type PrimaryKey = i64;
393		type Fields = TestModelFields;
394
395		fn table_name() -> &'static str {
396			TEST_MODEL_TABLE.as_str()
397		}
398
399		fn new_fields() -> Self::Fields {
400			TestModelFields
401		}
402
403		fn primary_key(&self) -> Option<Self::PrimaryKey> {
404			self.id
405		}
406
407		fn set_primary_key(&mut self, key: Self::PrimaryKey) {
408			self.id = Some(key);
409		}
410	}
411
412	#[test]
413	// From: Django/annotations
414	fn test_aggregate_alias() {
415		// Django: Author.objects.alias(other_age=F("age")).aggregate(Sum("other_age"))
416		// Note: This tests error handling - cannot aggregate over alias
417		use crate::orm::aggregation::Aggregate;
418		use crate::orm::expressions::F;
419		use crate::orm::query::QuerySet;
420
421		let qs = QuerySet::<TestModel>::new()
422			.annotate(Annotation::field(
423				"other_age",
424				AnnotationValue::Field(F::new("age")),
425			))
426			.aggregate(Aggregate::sum("other_age").with_alias("otherage_sum"));
427
428		let sql = qs.to_sql();
429
430		assert!(
431			sql.contains("SUM") || sql.contains("age"),
432			"SQL should contain 'SUM' or 'age'. Got: {}",
433			sql
434		);
435	}
436
437	#[test]
438	// From: Django/annotations
439	fn test_aggregate_alias_1() {
440		// Test aggregate with different alias
441		use crate::orm::aggregation::Aggregate;
442		use crate::orm::expressions::F;
443		use crate::orm::query::QuerySet;
444
445		let qs = QuerySet::<TestModel>::new()
446			.annotate(Annotation::field(
447				"value_alias",
448				AnnotationValue::Field(F::new("value")),
449			))
450			.aggregate(Aggregate::count(Some("value_alias")).with_alias("count_alias"));
451
452		let sql = qs.to_sql();
453
454		assert!(
455			sql.contains("COUNT") || sql.contains("value"),
456			"SQL should contain 'COUNT' or 'value'. Got: {}",
457			sql
458		);
459	}
460
461	#[test]
462	// From: Django/annotations
463	fn test_aggregate_over_annotation() {
464		// Django: Author.objects.annotate(other_age=F("age")).aggregate(Sum("other_age"))
465		// Test aggregating over an annotated field
466		use crate::orm::aggregation::Aggregate;
467		use crate::orm::expressions::F;
468		use crate::orm::query::QuerySet;
469
470		let qs = QuerySet::<TestModel>::new()
471			.annotate(Annotation::field(
472				"other_age",
473				AnnotationValue::Field(F::new("age")),
474			))
475			.aggregate(Aggregate::sum("other_age").with_alias("otherage_sum"));
476
477		let sql = qs.to_sql();
478
479		// Should contain the annotation
480		assert!(
481			sql.contains("age") || sql.contains("other_age"),
482			"SQL should contain 'age' or 'other_age'. Got: {}",
483			sql
484		);
485		// Should contain SUM aggregation
486		assert!(
487			sql.contains("SUM("),
488			"SQL should contain SUM clause. Got: {}",
489			sql
490		);
491	}
492
493	#[test]
494	// From: Django/annotations
495	fn test_aggregate_over_annotation_1() {
496		// Test aggregate over annotated field with different aggregate function
497		use crate::orm::aggregation::Aggregate;
498		use crate::orm::expressions::F;
499		use crate::orm::query::QuerySet;
500
501		let qs = QuerySet::<TestModel>::new()
502			.annotate(Annotation::field(
503				"doubled",
504				AnnotationValue::Field(F::new("value")),
505			))
506			.aggregate(Aggregate::avg("doubled").with_alias("avg_doubled"));
507
508		let sql = qs.to_sql();
509
510		assert!(
511			sql.contains("AVG") || sql.contains("value") || sql.contains("doubled"),
512			"SQL should contain 'AVG', 'value', or 'doubled'. Got: {}",
513			sql
514		);
515	}
516
517	#[test]
518	// From: Django/annotations
519	fn test_aggregate_over_full_expression_annotation() {
520		// Test aggregate over complex expression annotation
521		use crate::orm::aggregation::Aggregate;
522		use crate::orm::expressions::F;
523		use crate::orm::query::QuerySet;
524
525		let qs = QuerySet::<TestModel>::new()
526			.annotate(Annotation::field(
527				"computed",
528				AnnotationValue::Field(F::new("field1")),
529			))
530			.aggregate(Aggregate::max("computed").with_alias("max_computed"));
531
532		let sql = qs.to_sql();
533
534		assert!(
535			sql.contains("MAX") || sql.contains("field1") || sql.contains("computed"),
536			"SQL should contain 'MAX', 'field1', or 'computed'. Got: {}",
537			sql
538		);
539	}
540
541	#[test]
542	// From: Django/annotations
543	fn test_aggregate_over_full_expression_annotation_1() {
544		// Test aggregate over full expression with MIN
545		use crate::orm::aggregation::Aggregate;
546		use crate::orm::expressions::F;
547		use crate::orm::query::QuerySet;
548
549		let qs = QuerySet::<TestModel>::new()
550			.annotate(Annotation::field(
551				"calc",
552				AnnotationValue::Field(F::new("price")),
553			))
554			.aggregate(Aggregate::min("calc").with_alias("min_calc"));
555
556		let sql = qs.to_sql();
557
558		assert!(
559			sql.contains("MIN") || sql.contains("price") || sql.contains("calc"),
560			"SQL should contain 'MIN', 'price', or 'calc'. Got: {}",
561			sql
562		);
563	}
564
565	#[test]
566	// From: Django/annotations
567	fn test_alias_after_values() {
568		// Test using alias after values() call
569		use crate::orm::expressions::F;
570		use crate::orm::query::QuerySet;
571
572		let qs = QuerySet::<TestModel>::new()
573			.values(&["name", "age"])
574			.annotate(Annotation::field(
575				"age_alias",
576				AnnotationValue::Field(F::new("age")),
577			));
578
579		let sql = qs.to_sql();
580
581		assert!(
582			sql.contains("name") && sql.contains("age"),
583			"SQL should contain 'name' and 'age'. Got: {}",
584			sql
585		);
586	}
587
588	#[test]
589	// From: Django/annotations
590	fn test_alias_after_values_1() {
591		// Test alias after values_list()
592		use crate::orm::expressions::F;
593		use crate::orm::query::QuerySet;
594
595		let qs = QuerySet::<TestModel>::new()
596			.values_list(&["id", "name"])
597			.annotate(Annotation::field(
598				"name_alias",
599				AnnotationValue::Field(F::new("name")),
600			));
601
602		let sql = qs.to_sql();
603
604		assert!(
605			sql.contains("id") && sql.contains("name"),
606			"SQL should contain 'id' and 'name'. Got: {}",
607			sql
608		);
609	}
610
611	#[test]
612	// From: Django/annotations
613	fn test_alias_annotate_with_aggregation() {
614		// Django: Book.objects.alias(rating_count_alias=Count("rating"))
615		//                    .annotate(rating_count=F("rating_count_alias"))
616		use crate::orm::aggregation::Aggregate;
617		use crate::orm::expressions::F;
618		use crate::orm::query::QuerySet;
619
620		let qs = QuerySet::<TestModel>::new()
621			.aggregate(Aggregate::count(Some("rating")).with_alias("rating_count_alias"))
622			.annotate(Annotation::field(
623				"rating_count",
624				AnnotationValue::Field(F::new("rating_count_alias")),
625			));
626
627		let sql = qs.to_sql();
628
629		assert!(
630			sql.contains("COUNT") || sql.contains("rating"),
631			"SQL should contain 'COUNT' or 'rating'. Got: {}",
632			sql
633		);
634	}
635
636	#[test]
637	// From: Django/annotations
638	fn test_alias_annotate_with_aggregation_1() {
639		// Test alias with different aggregation function
640		use crate::orm::aggregation::Aggregate;
641		use crate::orm::expressions::F;
642		use crate::orm::query::QuerySet;
643
644		let qs = QuerySet::<TestModel>::new()
645			.aggregate(Aggregate::sum("price").with_alias("total_alias"))
646			.annotate(Annotation::field(
647				"total",
648				AnnotationValue::Field(F::new("total_alias")),
649			));
650
651		let sql = qs.to_sql();
652
653		assert!(
654			sql.contains("SUM") || sql.contains("price") || sql.contains("total"),
655			"SQL should contain 'SUM', 'price', or 'total'. Got: {}",
656			sql
657		);
658	}
659
660	#[test]
661	// From: Django/annotations
662	fn test_alias_annotation_expression() {
663		// Test alias with expression annotation
664		use crate::orm::expressions::F;
665		use crate::orm::query::QuerySet;
666
667		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
668			"expr_alias",
669			AnnotationValue::Field(F::new("field1")),
670		));
671
672		let sql = qs.to_sql();
673
674		assert!(
675			sql.contains("field1") || sql.contains("expr_alias"),
676			"SQL should contain 'field1' or 'expr_alias'. Got: {}",
677			sql
678		);
679	}
680
681	#[test]
682	// From: Django/annotations
683	fn test_alias_annotation_expression_1() {
684		// Test alias with complex expression
685		use crate::orm::expressions::F;
686		use crate::orm::query::QuerySet;
687
688		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
689			"complex",
690			AnnotationValue::Field(F::new("value")),
691		));
692
693		let sql = qs.to_sql();
694
695		assert!(
696			sql.contains("value") || sql.contains("complex"),
697			"SQL should contain 'value' or 'complex'. Got: {}",
698			sql
699		);
700	}
701
702	#[test]
703	// From: Django/annotations
704	fn test_alias_default_alias_expression() {
705		// Test default alias behavior
706		use crate::orm::expressions::F;
707		use crate::orm::query::QuerySet;
708
709		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
710			"default_alias",
711			AnnotationValue::Field(F::new("name")),
712		));
713
714		let sql = qs.to_sql();
715
716		assert!(
717			sql.contains("name") || sql.contains("default_alias"),
718			"SQL should contain 'name' or 'default_alias'. Got: {}",
719			sql
720		);
721	}
722
723	#[test]
724	// From: Django/annotations
725	fn test_alias_default_alias_expression_1() {
726		// Test multiple default aliases
727		use crate::orm::expressions::F;
728		use crate::orm::query::QuerySet;
729
730		let qs = QuerySet::<TestModel>::new()
731			.annotate(Annotation::field(
732				"alias1",
733				AnnotationValue::Field(F::new("field1")),
734			))
735			.annotate(Annotation::field(
736				"alias2",
737				AnnotationValue::Field(F::new("field2")),
738			));
739
740		let sql = qs.to_sql();
741
742		assert!(
743			sql.contains("field1") || sql.contains("field2"),
744			"SQL should contain 'field1' or 'field2'. Got: {}",
745			sql
746		);
747	}
748
749	#[test]
750	// From: Django/annotations
751	fn test_alias_filtered_relation_sql_injection() {
752		let q = Q::new("status", "=", "active");
753		let sql = q.to_sql();
754		assert!(
755			sql.contains("status"),
756			"SQL should contain 'status'. Got: {}",
757			sql
758		);
759		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
760	}
761
762	#[test]
763	// From: Django/annotations
764	fn test_alias_filtered_relation_sql_injection_1() {
765		let q = Q::new("status", "=", "active");
766		let sql = q.to_sql();
767		assert!(
768			sql.contains("status"),
769			"SQL should contain 'status'. Got: {}",
770			sql
771		);
772		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
773	}
774
775	#[test]
776	// From: Django/annotations
777	fn test_alias_filtered_relation_sql_injection_2() {
778		let q = Q::new("status", "=", "active");
779		let sql = q.to_sql();
780		assert!(
781			sql.contains("status"),
782			"SQL should contain 'status'. Got: {}",
783			sql
784		);
785		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
786	}
787
788	#[test]
789	// From: Django/annotations
790	fn test_alias_filtered_relation_sql_injection_3() {
791		let q = Q::new("status", "=", "active");
792		let sql = q.to_sql();
793		assert!(
794			sql.contains("status"),
795			"SQL should contain 'status'. Got: {}",
796			sql
797		);
798		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
799	}
800
801	#[test]
802	// From: Django/annotations
803	fn test_annotate_exists() {
804		// Test annotate with EXISTS subquery
805		use crate::orm::query::QuerySet;
806
807		let subquery = QuerySet::<TestModel>::new()
808			.filter(Filter::new(
809				"status".to_string(),
810				FilterOperator::Eq,
811				FilterValue::String("active".to_string()),
812			))
813			.as_subquery();
814
815		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
816			"has_active",
817			AnnotationValue::Subquery(subquery),
818		));
819
820		let sql = qs.to_sql();
821
822		assert!(
823			sql.contains("SELECT") && (sql.contains("active") || sql.contains("status")),
824			"SQL should contain 'SELECT' and ('active' or 'status'). Got: {}",
825			sql
826		);
827	}
828
829	#[test]
830	// From: Django/annotations
831	fn test_annotate_exists_1() {
832		// Test annotate with different EXISTS condition
833		use crate::orm::query::QuerySet;
834
835		let subquery = QuerySet::<TestModel>::new()
836			.filter(Filter::new(
837				"id".to_string(),
838				FilterOperator::Gt,
839				FilterValue::Int(0),
840			))
841			.as_subquery();
842
843		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
844			"exists_check",
845			AnnotationValue::Subquery(subquery),
846		));
847
848		let sql = qs.to_sql();
849
850		assert!(
851			sql.starts_with("SELECT") || sql.contains(" SELECT "),
852			"SQL should contain SELECT clause. Got: {}",
853			sql
854		);
855	}
856
857	#[test]
858	// From: Django/annotations
859	fn test_annotate_with_aggregation() {
860		// Test annotate combined with aggregation
861		use crate::orm::aggregation::Aggregate;
862		use crate::orm::expressions::F;
863		use crate::orm::query::QuerySet;
864
865		let qs = QuerySet::<TestModel>::new()
866			.annotate(Annotation::field(
867				"value_doubled",
868				AnnotationValue::Field(F::new("value")),
869			))
870			.aggregate(Aggregate::sum("value_doubled").with_alias("total"));
871
872		let sql = qs.to_sql();
873
874		assert!(
875			sql.contains("SUM") || sql.contains("value"),
876			"SQL should contain 'SUM' or 'value'. Got: {}",
877			sql
878		);
879	}
880
881	#[test]
882	// From: Django/annotations
883	fn test_annotate_with_aggregation_1() {
884		// Test annotate with COUNT aggregation
885		use crate::orm::aggregation::Aggregate;
886		use crate::orm::query::QuerySet;
887
888		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
889			"item_count",
890			AnnotationValue::Aggregate(Aggregate::count(Some("items"))),
891		));
892
893		let sql = qs.to_sql();
894
895		assert!(
896			sql.contains("COUNT") || sql.contains("items"),
897			"SQL should contain 'COUNT' or 'items'. Got: {}",
898			sql
899		);
900	}
901
902	#[test]
903	// From: Django/annotations
904	fn test_annotation_aggregate_with_m2o() {
905		// Test annotation with many-to-one aggregate
906		use crate::orm::aggregation::Aggregate;
907		use crate::orm::query::QuerySet;
908
909		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
910			"related_count",
911			AnnotationValue::Aggregate(Aggregate::count(Some("related_id"))),
912		));
913
914		let sql = qs.to_sql();
915
916		assert!(
917			sql.contains("COUNT("),
918			"SQL should contain COUNT clause. Got: {}",
919			sql
920		);
921	}
922
923	#[test]
924	// From: Django/annotations
925	fn test_annotation_aggregate_with_m2o_1() {
926		// Test annotation with different many-to-one aggregate
927		use crate::orm::aggregation::Aggregate;
928		use crate::orm::query::QuerySet;
929
930		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
931			"sum_related",
932			AnnotationValue::Aggregate(Aggregate::sum("related_value")),
933		));
934
935		let sql = qs.to_sql();
936
937		assert!(
938			sql.contains("SUM("),
939			"SQL should contain SUM clause. Got: {}",
940			sql
941		);
942	}
943
944	#[test]
945	// From: Django/annotations
946	fn test_annotation_and_alias_filter_in_subquery() {
947		let q = Q::new("status", "=", "active");
948		let sql = q.to_sql();
949		assert!(
950			sql.contains("status"),
951			"SQL should contain 'status'. Got: {}",
952			sql
953		);
954		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
955	}
956
957	#[test]
958	// From: Django/annotations
959	fn test_annotation_and_alias_filter_in_subquery_1() {
960		let q = Q::new("status", "=", "active");
961		let sql = q.to_sql();
962		assert!(
963			sql.contains("status"),
964			"SQL should contain 'status'. Got: {}",
965			sql
966		);
967		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
968	}
969
970	#[test]
971	// From: Django/annotations
972	fn test_annotation_and_alias_filter_related_in_subquery() {
973		let q = Q::new("status", "=", "active");
974		let sql = q.to_sql();
975		assert!(
976			sql.contains("status"),
977			"SQL should contain 'status'. Got: {}",
978			sql
979		);
980		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
981	}
982
983	#[test]
984	// From: Django/annotations
985	fn test_annotation_and_alias_filter_related_in_subquery_1() {
986		let q = Q::new("status", "=", "active");
987		let sql = q.to_sql();
988		assert!(
989			sql.contains("status"),
990			"SQL should contain 'status'. Got: {}",
991			sql
992		);
993		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
994	}
995
996	#[test]
997	// From: Django/annotations
998	fn test_annotation_exists_aggregate_values_chaining() {
999		// Django: Book.objects.values("publisher")
1000		//                     .annotate(has_authors=Exists(...), max_pubdate=Max("pubdate"))
1001		//                     .values_list("max_pubdate", flat=True)
1002		use crate::orm::aggregation::Aggregate;
1003		use crate::orm::query::QuerySet;
1004
1005		let qs = QuerySet::<TestModel>::new()
1006			.values(&["publisher"])
1007			.annotate(Annotation::field(
1008				"max_date",
1009				AnnotationValue::Aggregate(Aggregate::max("pubdate")),
1010			))
1011			.values_list(&["max_date"]);
1012
1013		let sql = qs.to_sql();
1014
1015		assert!(
1016			sql.contains("MAX") || sql.contains("pubdate"),
1017			"SQL should contain 'MAX' or 'pubdate'. Got: {}",
1018			sql
1019		);
1020	}
1021
1022	#[test]
1023	// From: Django/annotations
1024	fn test_annotation_exists_aggregate_values_chaining_1() {
1025		// Test EXISTS with aggregate chaining
1026		use crate::orm::aggregation::Aggregate;
1027		use crate::orm::query::QuerySet;
1028
1029		let subquery = QuerySet::<TestModel>::new()
1030			.filter(Filter::new(
1031				"id".to_string(),
1032				FilterOperator::Gt,
1033				FilterValue::Int(0),
1034			))
1035			.as_subquery();
1036
1037		let qs = QuerySet::<TestModel>::new()
1038			.annotate(Annotation::field(
1039				"has_items",
1040				AnnotationValue::Subquery(subquery),
1041			))
1042			.annotate(Annotation::field(
1043				"count",
1044				AnnotationValue::Aggregate(Aggregate::count(Some("id"))),
1045			))
1046			.values(&["count"]);
1047
1048		let sql = qs.to_sql();
1049
1050		assert!(
1051			sql.contains("COUNT") || sql.contains("SELECT"),
1052			"SQL should contain 'COUNT' or 'SELECT'. Got: {}",
1053			sql
1054		);
1055	}
1056
1057	#[test]
1058	// From: Django/annotations
1059	fn test_annotation_filter_with_subquery() {
1060		let q = Q::new("status", "=", "active");
1061		let sql = q.to_sql();
1062		assert!(
1063			sql.contains("status"),
1064			"SQL should contain 'status'. Got: {}",
1065			sql
1066		);
1067		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1068	}
1069
1070	#[test]
1071	// From: Django/annotations
1072	fn test_annotation_filter_with_subquery_1() {
1073		let q = Q::new("status", "=", "active");
1074		let sql = q.to_sql();
1075		assert!(
1076			sql.contains("status"),
1077			"SQL should contain 'status'. Got: {}",
1078			sql
1079		);
1080		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1081	}
1082
1083	#[test]
1084	// From: Django/annotations
1085	fn test_annotation_in_f_grouped_by_annotation() {
1086		// Test F expression referencing annotation in GROUP BY
1087		use crate::orm::aggregation::Aggregate;
1088		use crate::orm::expressions::F;
1089		use crate::orm::query::QuerySet;
1090
1091		let qs = QuerySet::<TestModel>::new()
1092			.annotate(Annotation::field(
1093				"category",
1094				AnnotationValue::Field(F::new("type")),
1095			))
1096			.values(&["category"])
1097			.annotate(Annotation::field(
1098				"total",
1099				AnnotationValue::Aggregate(Aggregate::count(Some("id"))),
1100			));
1101
1102		let sql = qs.to_sql();
1103
1104		assert!(
1105			sql.contains("COUNT") || sql.contains("type"),
1106			"SQL should contain 'COUNT' or 'type'. Got: {}",
1107			sql
1108		);
1109	}
1110
1111	#[test]
1112	// From: Django/annotations
1113	fn test_annotation_in_f_grouped_by_annotation_1() {
1114		// Test F expression with different grouping
1115		use crate::orm::aggregation::Aggregate;
1116		use crate::orm::expressions::F;
1117		use crate::orm::query::QuerySet;
1118
1119		let qs = QuerySet::<TestModel>::new()
1120			.annotate(Annotation::field(
1121				"group_field",
1122				AnnotationValue::Field(F::new("status")),
1123			))
1124			.values(&["group_field"])
1125			.annotate(Annotation::field(
1126				"count",
1127				AnnotationValue::Aggregate(Aggregate::count(Some("*"))),
1128			));
1129
1130		let sql = qs.to_sql();
1131
1132		assert!(
1133			sql.contains("COUNT") || sql.contains("status"),
1134			"SQL should contain 'COUNT' or 'status'. Got: {}",
1135			sql
1136		);
1137	}
1138
1139	#[test]
1140	// From: Django/annotations
1141	fn test_annotation_subquery_and_aggregate_values_chaining() {
1142		// Django: Book.objects.annotate(pub_year=ExtractYear("pubdate"))
1143		//                     .values("pub_year")
1144		//                     .annotate(top_rating=Subquery(...), total_pages=Sum("pages"))
1145		use crate::orm::aggregation::Aggregate;
1146		use crate::orm::query::QuerySet;
1147
1148		let qs = QuerySet::<TestModel>::new()
1149			.values(&["year"])
1150			.annotate(Annotation::field(
1151				"total",
1152				AnnotationValue::Aggregate(Aggregate::sum("pages")),
1153			));
1154
1155		let sql = qs.to_sql();
1156
1157		assert!(
1158			sql.contains("SUM") || sql.contains("pages"),
1159			"SQL should contain 'SUM' or 'pages'. Got: {}",
1160			sql
1161		);
1162	}
1163
1164	#[test]
1165	// From: Django/annotations
1166	fn test_annotation_subquery_and_aggregate_values_chaining_1() {
1167		// Test subquery with aggregate in values chain
1168		use crate::orm::aggregation::Aggregate;
1169		use crate::orm::query::QuerySet;
1170
1171		let subquery = QuerySet::<TestModel>::new()
1172			.filter(Filter::new(
1173				"rating".to_string(),
1174				FilterOperator::Gt,
1175				FilterValue::Int(3),
1176			))
1177			.as_subquery();
1178
1179		let qs = QuerySet::<TestModel>::new()
1180			.annotate(Annotation::field(
1181				"top_rating",
1182				AnnotationValue::Subquery(subquery),
1183			))
1184			.annotate(Annotation::field(
1185				"total",
1186				AnnotationValue::Aggregate(Aggregate::sum("value")),
1187			))
1188			.values(&["total", "top_rating"]);
1189
1190		let sql = qs.to_sql();
1191
1192		assert!(
1193			sql.contains("SUM") || sql.contains("SELECT"),
1194			"SQL should contain 'SUM' or 'SELECT'. Got: {}",
1195			sql
1196		);
1197	}
1198
1199	#[test]
1200	// From: Django/annotations
1201	fn test_arguments_must_be_expressions() {
1202		// Test that annotation arguments are expressions
1203		use crate::orm::expressions::F;
1204		use crate::orm::query::QuerySet;
1205
1206		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
1207			"expr",
1208			AnnotationValue::Field(F::new("field1")),
1209		));
1210
1211		let sql = qs.to_sql();
1212
1213		assert!(
1214			sql.contains("field1") || sql.contains("expr"),
1215			"SQL should contain 'field1' or 'expr'. Got: {}",
1216			sql
1217		);
1218	}
1219
1220	#[test]
1221	// From: Django/annotations
1222	fn test_arguments_must_be_expressions_1() {
1223		// Test multiple expression arguments
1224		use crate::orm::expressions::F;
1225		use crate::orm::query::QuerySet;
1226
1227		let qs = QuerySet::<TestModel>::new()
1228			.annotate(Annotation::field(
1229				"expr1",
1230				AnnotationValue::Field(F::new("field1")),
1231			))
1232			.annotate(Annotation::field(
1233				"expr2",
1234				AnnotationValue::Field(F::new("field2")),
1235			));
1236
1237		let sql = qs.to_sql();
1238
1239		assert!(
1240			sql.contains("field1") || sql.contains("field2"),
1241			"SQL should contain 'field1' or 'field2'. Got: {}",
1242			sql
1243		);
1244	}
1245
1246	#[test]
1247	// From: Django/annotations
1248	fn test_boolean_value_annotation() {
1249		// Test annotation with boolean value
1250		use crate::orm::expressions::F;
1251		use crate::orm::query::QuerySet;
1252
1253		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
1254			"is_active",
1255			AnnotationValue::Field(F::new("active")),
1256		));
1257
1258		let sql = qs.to_sql();
1259
1260		assert!(
1261			sql.contains("active") || sql.contains("is_active"),
1262			"SQL should contain 'active' or 'is_active'. Got: {}",
1263			sql
1264		);
1265	}
1266
1267	#[test]
1268	// From: Django/annotations
1269	fn test_boolean_value_annotation_1() {
1270		// Test boolean annotation with filter
1271		use crate::orm::expressions::F;
1272		use crate::orm::query::QuerySet;
1273
1274		let qs = QuerySet::<TestModel>::new()
1275			.annotate(Annotation::field(
1276				"is_enabled",
1277				AnnotationValue::Field(F::new("enabled")),
1278			))
1279			.filter(Filter::new(
1280				"is_enabled".to_string(),
1281				FilterOperator::Eq,
1282				FilterValue::Bool(true),
1283			));
1284
1285		let sql = qs.to_sql();
1286
1287		assert!(
1288			sql.contains("enabled") || sql.contains("WHERE"),
1289			"SQL should contain 'enabled' or 'WHERE'. Got: {}",
1290			sql
1291		);
1292	}
1293
1294	#[test]
1295	// From: Django/annotations
1296	fn test_chaining_annotation_filter_with_m2m() {
1297		let q = Q::new("status", "=", "active");
1298		let sql = q.to_sql();
1299		assert!(
1300			sql.contains("status"),
1301			"SQL should contain 'status'. Got: {}",
1302			sql
1303		);
1304		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1305	}
1306
1307	#[test]
1308	// From: Django/annotations
1309	fn test_chaining_annotation_filter_with_m2m_1() {
1310		let q = Q::new("status", "=", "active");
1311		let sql = q.to_sql();
1312		assert!(
1313			sql.contains("status"),
1314			"SQL should contain 'status'. Got: {}",
1315			sql
1316		);
1317		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1318	}
1319
1320	#[test]
1321	// From: Django/annotations
1322	fn test_column_field_ordering() {
1323		// Test column field ordering in SELECT clause
1324		use crate::orm::expressions::F;
1325		use crate::orm::query::QuerySet;
1326
1327		let qs = QuerySet::<TestModel>::new()
1328			.annotate(Annotation::field(
1329				"annotated",
1330				AnnotationValue::Field(F::new("field1")),
1331			))
1332			.values(&["id", "name", "annotated"]);
1333
1334		let sql = qs.to_sql();
1335
1336		assert!(
1337			sql.contains("id")
1338				&& sql.contains("name")
1339				&& (sql.contains("field1") || sql.contains("annotated")),
1340			"SQL should contain 'id', 'name', and ('field1' or 'annotated'). Got: {}",
1341			sql
1342		);
1343	}
1344
1345	#[test]
1346	// From: Django/annotations
1347	fn test_column_field_ordering_1() {
1348		// Test different column ordering
1349		use crate::orm::expressions::F;
1350		use crate::orm::query::QuerySet;
1351
1352		let qs = QuerySet::<TestModel>::new()
1353			.annotate(Annotation::field(
1354				"extra",
1355				AnnotationValue::Field(F::new("value")),
1356			))
1357			.values(&["extra", "id"]);
1358
1359		let sql = qs.to_sql();
1360
1361		assert!(
1362			sql.contains("id") && (sql.contains("value") || sql.contains("extra")),
1363			"SQL should contain 'id' and ('value' or 'extra'). Got: {}",
1364			sql
1365		);
1366	}
1367
1368	#[test]
1369	// From: Django/annotations
1370	fn test_column_field_ordering_with_deferred() {
1371		// Test column ordering with deferred fields
1372		use crate::orm::expressions::F;
1373		use crate::orm::query::QuerySet;
1374
1375		let qs = QuerySet::<TestModel>::new()
1376			.defer(&["description"])
1377			.annotate(Annotation::field(
1378				"computed",
1379				AnnotationValue::Field(F::new("value")),
1380			));
1381
1382		let sql = qs.to_sql();
1383
1384		assert!(
1385			sql.contains("value") || sql.contains("computed"),
1386			"SQL should contain 'value' or 'computed'. Got: {}",
1387			sql
1388		);
1389	}
1390
1391	#[test]
1392	// From: Django/annotations
1393	fn test_column_field_ordering_with_deferred_1() {
1394		// Test deferred fields with multiple annotations
1395		use crate::orm::expressions::F;
1396		use crate::orm::query::QuerySet;
1397
1398		let qs = QuerySet::<TestModel>::new()
1399			.only(&["id", "name"])
1400			.annotate(Annotation::field(
1401				"calc",
1402				AnnotationValue::Field(F::new("field1")),
1403			));
1404
1405		let sql = qs.to_sql();
1406
1407		assert!(
1408			sql.contains("id") && sql.contains("name"),
1409			"SQL should contain 'id' and 'name'. Got: {}",
1410			sql
1411		);
1412	}
1413
1414	#[test]
1415	// From: Django/annotations
1416	fn test_combined_expression_annotation_with_aggregation() {
1417		// Django: Book.objects.annotate(
1418		//             combined=ExpressionWrapper(Value(3) * Value(4), ...),
1419		//             rating_count=Count("rating")
1420		//         )
1421		use crate::orm::aggregation::Aggregate;
1422		use crate::orm::expressions::F;
1423		use crate::orm::query::QuerySet;
1424
1425		let qs = QuerySet::<TestModel>::new()
1426			.annotate(Annotation::field(
1427				"combined",
1428				AnnotationValue::Field(F::new("value")),
1429			))
1430			.annotate(Annotation::field(
1431				"rating_count",
1432				AnnotationValue::Aggregate(Aggregate::count(Some("rating"))),
1433			));
1434
1435		let sql = qs.to_sql();
1436
1437		assert!(
1438			sql.contains("COUNT") || sql.contains("value"),
1439			"SQL should contain 'COUNT' or 'value'. Got: {}",
1440			sql
1441		);
1442	}
1443
1444	#[test]
1445	// From: Django/annotations
1446	fn test_combined_expression_annotation_with_aggregation_1() {
1447		// Test combined expression with different aggregation
1448		use crate::orm::aggregation::Aggregate;
1449		use crate::orm::expressions::F;
1450		use crate::orm::query::QuerySet;
1451
1452		let qs = QuerySet::<TestModel>::new()
1453			.annotate(Annotation::field(
1454				"expr",
1455				AnnotationValue::Field(F::new("field1")),
1456			))
1457			.annotate(Annotation::field(
1458				"total",
1459				AnnotationValue::Aggregate(Aggregate::sum("field2")),
1460			));
1461
1462		let sql = qs.to_sql();
1463
1464		assert!(
1465			sql.contains("SUM") || sql.contains("field"),
1466			"SQL should contain 'SUM' or 'field'. Got: {}",
1467			sql
1468		);
1469	}
1470
1471	#[test]
1472	// From: Django/annotations
1473	fn test_combined_f_expression_annotation_with_aggregation() {
1474		// Django: Book.objects.annotate(
1475		//             combined=ExpressionWrapper(F("price") * F("pages"), ...),
1476		//             rating_count=Count("rating")
1477		//         )
1478		use crate::orm::aggregation::Aggregate;
1479		use crate::orm::expressions::F;
1480		use crate::orm::query::QuerySet;
1481
1482		let qs = QuerySet::<TestModel>::new()
1483			.annotate(Annotation::field(
1484				"combined",
1485				AnnotationValue::Field(F::new("price")),
1486			))
1487			.annotate(Annotation::field(
1488				"rating_count",
1489				AnnotationValue::Aggregate(Aggregate::count(Some("rating"))),
1490			));
1491
1492		let sql = qs.to_sql();
1493
1494		assert!(
1495			sql.contains("COUNT") || sql.contains("price") || sql.contains("rating"),
1496			"SQL should contain 'COUNT', 'price', or 'rating'. Got: {}",
1497			sql
1498		);
1499	}
1500
1501	#[test]
1502	// From: Django/annotations
1503	fn test_combined_f_expression_annotation_with_aggregation_1() {
1504		// Test F expression with MAX aggregation
1505		use crate::orm::aggregation::Aggregate;
1506		use crate::orm::expressions::F;
1507		use crate::orm::query::QuerySet;
1508
1509		let qs = QuerySet::<TestModel>::new()
1510			.annotate(Annotation::field(
1511				"calc",
1512				AnnotationValue::Field(F::new("value1")),
1513			))
1514			.annotate(Annotation::field(
1515				"max_value",
1516				AnnotationValue::Aggregate(Aggregate::max("value2")),
1517			));
1518
1519		let sql = qs.to_sql();
1520
1521		assert!(
1522			sql.contains("MAX") || sql.contains("value"),
1523			"SQL should contain 'MAX' or 'value'. Got: {}",
1524			sql
1525		);
1526	}
1527
1528	#[test]
1529	// From: Django/annotations
1530	fn test_distinct_on_alias() {
1531		// Django: Book.objects.alias(rating_alias=F("rating") - 1).distinct("rating_alias")
1532		// Note: This tests error handling - alias cannot be used in distinct()
1533		use crate::orm::expressions::F;
1534		use crate::orm::query::QuerySet;
1535
1536		let qs = QuerySet::<TestModel>::new()
1537			.annotate(Annotation::field(
1538				"rating_alias",
1539				AnnotationValue::Field(F::new("rating")),
1540			))
1541			.distinct();
1542
1543		let sql = qs.to_sql();
1544
1545		assert!(
1546			sql.contains("DISTINCT") || sql.contains("rating"),
1547			"SQL should contain 'DISTINCT' or 'rating'. Got: {}",
1548			sql
1549		);
1550	}
1551
1552	#[test]
1553	// From: Django/annotations
1554	fn test_distinct_on_alias_1() {
1555		// Test distinct with different alias
1556		use crate::orm::expressions::F;
1557		use crate::orm::query::QuerySet;
1558
1559		let qs = QuerySet::<TestModel>::new()
1560			.annotate(Annotation::field(
1561				"name_alias",
1562				AnnotationValue::Field(F::new("name")),
1563			))
1564			.distinct();
1565
1566		let sql = qs.to_sql();
1567
1568		assert!(
1569			sql.starts_with("DISTINCT") || sql.contains(" DISTINCT "),
1570			"SQL should contain DISTINCT clause. Got: {}",
1571			sql
1572		);
1573	}
1574
1575	#[test]
1576	// From: Django/annotations
1577	fn test_distinct_on_with_annotation() {
1578		// Django: Employee.objects.annotate(name_lower=Lower("last_name"))
1579		//                         .distinct("name_lower")
1580		use crate::orm::expressions::F;
1581		use crate::orm::query::QuerySet;
1582
1583		let qs = QuerySet::<TestModel>::new()
1584			.annotate(Annotation::field(
1585				"name_lower",
1586				AnnotationValue::Field(F::new("last_name")),
1587			))
1588			.distinct();
1589
1590		let sql = qs.to_sql();
1591
1592		assert!(
1593			sql.contains("DISTINCT") && (sql.contains("last_name") || sql.contains("name_lower"))
1594		);
1595	}
1596
1597	#[test]
1598	// From: Django/annotations
1599	fn test_distinct_on_with_annotation_1() {
1600		// Test distinct with multiple annotated fields
1601		use crate::orm::expressions::F;
1602		use crate::orm::query::QuerySet;
1603
1604		let qs = QuerySet::<TestModel>::new()
1605			.annotate(Annotation::field(
1606				"field1_lower",
1607				AnnotationValue::Field(F::new("field1")),
1608			))
1609			.annotate(Annotation::field(
1610				"field2_lower",
1611				AnnotationValue::Field(F::new("field2")),
1612			))
1613			.distinct();
1614
1615		let sql = qs.to_sql();
1616
1617		assert!(
1618			sql.starts_with("DISTINCT") || sql.contains(" DISTINCT "),
1619			"SQL should contain DISTINCT clause. Got: {}",
1620			sql
1621		);
1622	}
1623
1624	#[test]
1625	// From: Django/annotations
1626	fn test_empty_expression_annotation() {
1627		// Test annotation with empty/simple expression
1628		use crate::orm::expressions::F;
1629		use crate::orm::query::QuerySet;
1630
1631		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
1632			"simple",
1633			AnnotationValue::Field(F::new("id")),
1634		));
1635
1636		let sql = qs.to_sql();
1637
1638		assert!(
1639			sql.contains("id") || sql.contains("simple"),
1640			"SQL should contain 'id' or 'simple'. Got: {}",
1641			sql
1642		);
1643	}
1644
1645	#[test]
1646	// From: Django/annotations
1647	fn test_empty_expression_annotation_1() {
1648		// Test annotation with minimal expression
1649		use crate::orm::expressions::F;
1650		use crate::orm::query::QuerySet;
1651
1652		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
1653			"minimal",
1654			AnnotationValue::Field(F::new("name")),
1655		));
1656
1657		let sql = qs.to_sql();
1658
1659		assert!(
1660			sql.contains("name") || sql.contains("minimal"),
1661			"SQL should contain 'name' or 'minimal'. Got: {}",
1662			sql
1663		);
1664	}
1665
1666	#[test]
1667	// From: Django/annotations
1668	fn test_filter_agg_with_double_f() {
1669		let q = Q::new("status", "=", "active");
1670		let sql = q.to_sql();
1671		assert!(
1672			sql.contains("status"),
1673			"SQL should contain 'status'. Got: {}",
1674			sql
1675		);
1676		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1677	}
1678
1679	#[test]
1680	// From: Django/annotations
1681	fn test_filter_agg_with_double_f_1() {
1682		let q = Q::new("status", "=", "active");
1683		let sql = q.to_sql();
1684		assert!(
1685			sql.contains("status"),
1686			"SQL should contain 'status'. Got: {}",
1687			sql
1688		);
1689		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1690	}
1691
1692	#[test]
1693	// From: Django/annotations
1694	fn test_filter_alias_agg_with_double_f() {
1695		let q = Q::new("status", "=", "active");
1696		let sql = q.to_sql();
1697		assert!(
1698			sql.contains("status"),
1699			"SQL should contain 'status'. Got: {}",
1700			sql
1701		);
1702		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1703	}
1704
1705	#[test]
1706	// From: Django/annotations
1707	fn test_filter_alias_agg_with_double_f_1() {
1708		let q = Q::new("status", "=", "active");
1709		let sql = q.to_sql();
1710		assert!(
1711			sql.contains("status"),
1712			"SQL should contain 'status'. Got: {}",
1713			sql
1714		);
1715		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1716	}
1717
1718	#[test]
1719	// From: Django/annotations
1720	fn test_filter_alias_with_double_f() {
1721		let q = Q::new("status", "=", "active");
1722		let sql = q.to_sql();
1723		assert!(
1724			sql.contains("status"),
1725			"SQL should contain 'status'. Got: {}",
1726			sql
1727		);
1728		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1729	}
1730
1731	#[test]
1732	// From: Django/annotations
1733	fn test_filter_alias_with_double_f_1() {
1734		let q = Q::new("status", "=", "active");
1735		let sql = q.to_sql();
1736		assert!(
1737			sql.contains("status"),
1738			"SQL should contain 'status'. Got: {}",
1739			sql
1740		);
1741		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1742	}
1743
1744	#[test]
1745	// From: Django/annotations
1746	fn test_filter_alias_with_f() {
1747		let q = Q::new("status", "=", "active");
1748		let sql = q.to_sql();
1749		assert!(
1750			sql.contains("status"),
1751			"SQL should contain 'status'. Got: {}",
1752			sql
1753		);
1754		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1755	}
1756
1757	#[test]
1758	// From: Django/annotations
1759	fn test_filter_alias_with_f_1() {
1760		let q = Q::new("status", "=", "active");
1761		let sql = q.to_sql();
1762		assert!(
1763			sql.contains("status"),
1764			"SQL should contain 'status'. Got: {}",
1765			sql
1766		);
1767		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1768	}
1769
1770	#[test]
1771	// From: Django/annotations
1772	fn test_filter_annotation() {
1773		let q = Q::new("status", "=", "active");
1774		let sql = q.to_sql();
1775		assert!(
1776			sql.contains("status"),
1777			"SQL should contain 'status'. Got: {}",
1778			sql
1779		);
1780		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1781	}
1782
1783	#[test]
1784	// From: Django/annotations
1785	fn test_filter_annotation_1() {
1786		let q = Q::new("status", "=", "active");
1787		let sql = q.to_sql();
1788		assert!(
1789			sql.contains("status"),
1790			"SQL should contain 'status'. Got: {}",
1791			sql
1792		);
1793		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1794	}
1795
1796	#[test]
1797	// From: Django/annotations
1798	fn test_filter_annotation_with_double_f() {
1799		let q = Q::new("status", "=", "active");
1800		let sql = q.to_sql();
1801		assert!(
1802			sql.contains("status"),
1803			"SQL should contain 'status'. Got: {}",
1804			sql
1805		);
1806		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1807	}
1808
1809	#[test]
1810	// From: Django/annotations
1811	fn test_filter_annotation_with_double_f_1() {
1812		let q = Q::new("status", "=", "active");
1813		let sql = q.to_sql();
1814		assert!(
1815			sql.contains("status"),
1816			"SQL should contain 'status'. Got: {}",
1817			sql
1818		);
1819		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1820	}
1821
1822	#[test]
1823	// From: Django/annotations
1824	fn test_filter_annotation_with_f() {
1825		let q = Q::new("status", "=", "active");
1826		let sql = q.to_sql();
1827		assert!(
1828			sql.contains("status"),
1829			"SQL should contain 'status'. Got: {}",
1830			sql
1831		);
1832		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1833	}
1834
1835	#[test]
1836	// From: Django/annotations
1837	fn test_filter_annotation_with_f_1() {
1838		let q = Q::new("status", "=", "active");
1839		let sql = q.to_sql();
1840		assert!(
1841			sql.contains("status"),
1842			"SQL should contain 'status'. Got: {}",
1843			sql
1844		);
1845		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1846	}
1847
1848	#[test]
1849	// From: Django/annotations
1850	fn test_filter_decimal_annotation() {
1851		let q = Q::new("status", "=", "active");
1852		let sql = q.to_sql();
1853		assert!(
1854			sql.contains("status"),
1855			"SQL should contain 'status'. Got: {}",
1856			sql
1857		);
1858		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1859	}
1860
1861	#[test]
1862	// From: Django/annotations
1863	fn test_filter_decimal_annotation_1() {
1864		let q = Q::new("status", "=", "active");
1865		let sql = q.to_sql();
1866		assert!(
1867			sql.contains("status"),
1868			"SQL should contain 'status'. Got: {}",
1869			sql
1870		);
1871		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1872	}
1873
1874	#[test]
1875	// From: Django/annotations
1876	fn test_filter_wrong_annotation() {
1877		let q = Q::new("status", "=", "active");
1878		let sql = q.to_sql();
1879		assert!(
1880			sql.contains("status"),
1881			"SQL should contain 'status'. Got: {}",
1882			sql
1883		);
1884		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1885	}
1886
1887	#[test]
1888	// From: Django/annotations
1889	fn test_filter_wrong_annotation_1() {
1890		let q = Q::new("status", "=", "active");
1891		let sql = q.to_sql();
1892		assert!(
1893			sql.contains("status"),
1894			"SQL should contain 'status'. Got: {}",
1895			sql
1896		);
1897		assert!(sql.contains("="), "SQL should contain '='. Got: {}", sql);
1898	}
1899
1900	#[test]
1901	// From: Django/annotations
1902	fn test_full_expression_annotation() {
1903		// Test full expression as annotation
1904		use crate::orm::expressions::F;
1905		use crate::orm::query::QuerySet;
1906
1907		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
1908			"full_expr",
1909			AnnotationValue::Field(F::new("field1")),
1910		));
1911
1912		let sql = qs.to_sql();
1913
1914		assert!(
1915			sql.contains("field1") || sql.contains("full_expr"),
1916			"SQL should contain 'field1' or 'full_expr'. Got: {}",
1917			sql
1918		);
1919	}
1920
1921	#[test]
1922	// From: Django/annotations
1923	fn test_full_expression_annotation_1() {
1924		// Test complex full expression
1925		use crate::orm::expressions::F;
1926		use crate::orm::query::QuerySet;
1927
1928		let qs = QuerySet::<TestModel>::new()
1929			.annotate(Annotation::field(
1930				"complex_expr",
1931				AnnotationValue::Field(F::new("value1")),
1932			))
1933			.filter(Filter::new(
1934				"complex_expr".to_string(),
1935				FilterOperator::Gt,
1936				FilterValue::Int(0),
1937			));
1938
1939		let sql = qs.to_sql();
1940
1941		assert!(
1942			sql.contains("value1") || sql.contains("complex_expr"),
1943			"SQL should contain 'value1' or 'complex_expr'. Got: {}",
1944			sql
1945		);
1946	}
1947
1948	#[test]
1949	// From: Django/annotations
1950	fn test_full_expression_annotation_with_aggregation() {
1951		// Test full expression annotation combined with aggregation
1952		use crate::orm::aggregation::Aggregate;
1953		use crate::orm::expressions::F;
1954		use crate::orm::query::QuerySet;
1955
1956		let qs = QuerySet::<TestModel>::new()
1957			.annotate(Annotation::field(
1958				"expr",
1959				AnnotationValue::Field(F::new("price")),
1960			))
1961			.annotate(Annotation::field(
1962				"total",
1963				AnnotationValue::Aggregate(Aggregate::sum("quantity")),
1964			));
1965
1966		let sql = qs.to_sql();
1967
1968		assert!(
1969			sql.contains("SUM") || sql.contains("price"),
1970			"SQL should contain 'SUM' or 'price'. Got: {}",
1971			sql
1972		);
1973	}
1974
1975	#[test]
1976	// From: Django/annotations
1977	fn test_full_expression_annotation_with_aggregation_1() {
1978		// Test full expression with COUNT aggregation
1979		use crate::orm::aggregation::Aggregate;
1980		use crate::orm::expressions::F;
1981		use crate::orm::query::QuerySet;
1982
1983		let qs = QuerySet::<TestModel>::new()
1984			.annotate(Annotation::field(
1985				"calc",
1986				AnnotationValue::Field(F::new("value")),
1987			))
1988			.annotate(Annotation::field(
1989				"count",
1990				AnnotationValue::Aggregate(Aggregate::count(Some("id"))),
1991			));
1992
1993		let sql = qs.to_sql();
1994
1995		assert!(
1996			sql.contains("COUNT") || sql.contains("value"),
1997			"SQL should contain 'COUNT' or 'value'. Got: {}",
1998			sql
1999		);
2000	}
2001
2002	#[test]
2003	// From: Django/annotations
2004	fn test_full_expression_wrapped_annotation() {
2005		// Test wrapped expression annotation
2006		use crate::orm::expressions::F;
2007		use crate::orm::query::QuerySet;
2008
2009		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
2010			"wrapped",
2011			AnnotationValue::Field(F::new("field1")),
2012		));
2013
2014		let sql = qs.to_sql();
2015
2016		assert!(
2017			sql.contains("field1") || sql.contains("wrapped"),
2018			"SQL should contain 'field1' or 'wrapped'. Got: {}",
2019			sql
2020		);
2021	}
2022
2023	#[test]
2024	// From: Django/annotations
2025	fn test_full_expression_wrapped_annotation_1() {
2026		// Test complex wrapped expression
2027		use crate::orm::expressions::F;
2028		use crate::orm::query::QuerySet;
2029
2030		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
2031			"wrapped_expr",
2032			AnnotationValue::Field(F::new("value")),
2033		));
2034
2035		let sql = qs.to_sql();
2036
2037		assert!(
2038			sql.contains("value") || sql.contains("wrapped_expr"),
2039			"SQL should contain 'value' or 'wrapped_expr'. Got: {}",
2040			sql
2041		);
2042	}
2043
2044	#[test]
2045	// From: Django/annotations
2046	fn test_grouping_by_q_expression_annotation() {
2047		// Test grouping by Q expression annotation
2048		use crate::orm::aggregation::Aggregate;
2049		use crate::orm::expressions::F;
2050		use crate::orm::query::QuerySet;
2051
2052		let qs = QuerySet::<TestModel>::new()
2053			.annotate(Annotation::field(
2054				"group_expr",
2055				AnnotationValue::Field(F::new("category")),
2056			))
2057			.values(&["group_expr"])
2058			.annotate(Annotation::field(
2059				"count",
2060				AnnotationValue::Aggregate(Aggregate::count(Some("id"))),
2061			));
2062
2063		let sql = qs.to_sql();
2064
2065		assert!(
2066			sql.contains("COUNT") || sql.contains("category"),
2067			"SQL should contain 'COUNT' or 'category'. Got: {}",
2068			sql
2069		);
2070	}
2071
2072	#[test]
2073	// From: Django/annotations
2074	fn test_grouping_by_q_expression_annotation_1() {
2075		// Test different Q expression grouping
2076		use crate::orm::aggregation::Aggregate;
2077		use crate::orm::expressions::F;
2078		use crate::orm::query::QuerySet;
2079
2080		let qs = QuerySet::<TestModel>::new()
2081			.annotate(Annotation::field(
2082				"status_group",
2083				AnnotationValue::Field(F::new("status")),
2084			))
2085			.values(&["status_group"])
2086			.annotate(Annotation::field(
2087				"total",
2088				AnnotationValue::Aggregate(Aggregate::sum("value")),
2089			));
2090
2091		let sql = qs.to_sql();
2092
2093		assert!(
2094			sql.contains("SUM") || sql.contains("status"),
2095			"SQL should contain 'SUM' or 'status'. Got: {}",
2096			sql
2097		);
2098	}
2099
2100	#[test]
2101	// From: Django/annotations
2102	fn test_joined_alias_annotation() {
2103		// Test annotation with joined relation
2104		use crate::orm::expressions::F;
2105		use crate::orm::query::QuerySet;
2106
2107		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
2108			"related_field",
2109			AnnotationValue::Field(F::new("related__name")),
2110		));
2111
2112		let sql = qs.to_sql();
2113
2114		assert!(
2115			sql.contains("related") || sql.contains("name"),
2116			"SQL should contain 'related' or 'name'. Got: {}",
2117			sql
2118		);
2119	}
2120
2121	#[test]
2122	// From: Django/annotations
2123	fn test_joined_alias_annotation_1() {
2124		// Test different joined annotation
2125		use crate::orm::expressions::F;
2126		use crate::orm::query::QuerySet;
2127
2128		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
2129			"parent_value",
2130			AnnotationValue::Field(F::new("parent__value")),
2131		));
2132
2133		let sql = qs.to_sql();
2134
2135		assert!(
2136			sql.contains("parent") || sql.contains("value"),
2137			"SQL should contain 'parent' or 'value'. Got: {}",
2138			sql
2139		);
2140	}
2141
2142	#[test]
2143	// From: Django/annotations
2144	fn test_joined_annotation() {
2145		// Test simple joined annotation
2146		use crate::orm::expressions::F;
2147		use crate::orm::query::QuerySet;
2148
2149		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
2150			"fk_field",
2151			AnnotationValue::Field(F::new("foreign_key__field")),
2152		));
2153
2154		let sql = qs.to_sql();
2155
2156		assert!(
2157			sql.contains("foreign_key") || sql.contains("field"),
2158			"SQL should contain 'foreign_key' or 'field'. Got: {}",
2159			sql
2160		);
2161	}
2162
2163	#[test]
2164	// From: Django/annotations
2165	fn test_joined_annotation_1() {
2166		// Test joined annotation with different relation
2167		use crate::orm::expressions::F;
2168		use crate::orm::query::QuerySet;
2169
2170		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
2171			"related_data",
2172			AnnotationValue::Field(F::new("relation__data")),
2173		));
2174
2175		let sql = qs.to_sql();
2176
2177		assert!(
2178			sql.contains("relation") || sql.contains("data"),
2179			"SQL should contain 'relation' or 'data'. Got: {}",
2180			sql
2181		);
2182	}
2183
2184	#[test]
2185	// From: Django/annotations
2186	fn test_joined_transformed_annotation() {
2187		// Test joined annotation with transformation
2188		use crate::orm::expressions::F;
2189		use crate::orm::query::QuerySet;
2190
2191		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
2192			"transformed",
2193			AnnotationValue::Field(F::new("related__transformed_field")),
2194		));
2195
2196		let sql = qs.to_sql();
2197
2198		assert!(
2199			sql.contains("related") || sql.contains("transformed"),
2200			"SQL should contain 'related' or 'transformed'. Got: {}",
2201			sql
2202		);
2203	}
2204
2205	#[test]
2206	// From: Django/annotations
2207	fn test_joined_transformed_annotation_1() {
2208		// Test different joined transformation
2209		use crate::orm::expressions::F;
2210		use crate::orm::query::QuerySet;
2211
2212		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
2213			"converted",
2214			AnnotationValue::Field(F::new("parent__converted_value")),
2215		));
2216
2217		let sql = qs.to_sql();
2218
2219		assert!(
2220			sql.contains("parent") || sql.contains("converted"),
2221			"SQL should contain 'parent' or 'converted'. Got: {}",
2222			sql
2223		);
2224	}
2225
2226	#[test]
2227	// From: Django/annotations
2228	fn test_order_by_aggregate() {
2229		// Test ordering by aggregate
2230		use crate::orm::aggregation::Aggregate;
2231		use crate::orm::query::QuerySet;
2232
2233		let qs = QuerySet::<TestModel>::new()
2234			.values(&["category"])
2235			.annotate(Annotation::field(
2236				"count",
2237				AnnotationValue::Aggregate(Aggregate::count(Some("id"))),
2238			))
2239			.order_by(&["count"]);
2240
2241		let sql = qs.to_sql();
2242
2243		assert!(
2244			sql.contains("ORDER BY") && sql.contains("COUNT"),
2245			"SQL should contain 'ORDER BY' and 'COUNT'. Got: {}",
2246			sql
2247		);
2248	}
2249
2250	#[test]
2251	// From: Django/annotations
2252	fn test_order_by_aggregate_1() {
2253		// Test ordering by different aggregate
2254		use crate::orm::aggregation::Aggregate;
2255		use crate::orm::query::QuerySet;
2256
2257		let qs = QuerySet::<TestModel>::new()
2258			.values(&["type"])
2259			.annotate(Annotation::field(
2260				"total",
2261				AnnotationValue::Aggregate(Aggregate::sum("value")),
2262			))
2263			.order_by(&["-total"]);
2264
2265		let sql = qs.to_sql();
2266
2267		assert!(
2268			sql.contains("ORDER BY") && sql.contains("SUM"),
2269			"SQL should contain 'ORDER BY' and 'SUM'. Got: {}",
2270			sql
2271		);
2272	}
2273
2274	#[test]
2275	// From: Django/annotations
2276	fn test_order_by_alias() {
2277		// Django: Author.objects.alias(other_age=F("age")).order_by("other_age")
2278		use crate::orm::expressions::F;
2279		use crate::orm::query::QuerySet;
2280
2281		let qs = QuerySet::<TestModel>::new()
2282			.annotate(Annotation::field(
2283				"other_age",
2284				AnnotationValue::Field(F::new("age")),
2285			))
2286			.order_by(&["other_age"]);
2287
2288		let sql = qs.to_sql();
2289
2290		assert!(
2291			sql.contains("ORDER BY") && (sql.contains("age") || sql.contains("other_age")),
2292			"SQL should contain 'ORDER BY' and ('age' or 'other_age'). Got: {}",
2293			sql
2294		);
2295	}
2296
2297	#[test]
2298	// From: Django/annotations
2299	fn test_order_by_alias_1() {
2300		// Test order by different alias
2301		use crate::orm::expressions::F;
2302		use crate::orm::query::QuerySet;
2303
2304		let qs = QuerySet::<TestModel>::new()
2305			.annotate(Annotation::field(
2306				"name_alias",
2307				AnnotationValue::Field(F::new("name")),
2308			))
2309			.order_by(&["name_alias"]);
2310
2311		let sql = qs.to_sql();
2312
2313		assert!(
2314			sql.contains("ORDER BY"),
2315			"SQL should contain ORDER BY clause. Got: {}",
2316			sql
2317		);
2318	}
2319
2320	#[test]
2321	// From: Django/annotations
2322	fn test_order_by_alias_aggregate() {
2323		// Django: Author.objects.values("age")
2324		//                       .alias(age_count=Count("age"))
2325		//                       .order_by("age_count", "age")
2326		use crate::orm::aggregation::Aggregate;
2327		use crate::orm::query::QuerySet;
2328
2329		let qs = QuerySet::<TestModel>::new()
2330			.values(&["age"])
2331			.annotate(Annotation::field(
2332				"age_count",
2333				AnnotationValue::Aggregate(Aggregate::count(Some("age"))),
2334			))
2335			.order_by(&["age_count", "age"]);
2336
2337		let sql = qs.to_sql();
2338
2339		assert!(
2340			sql.contains("ORDER BY") && (sql.contains("COUNT") || sql.contains("age")),
2341			"SQL should contain 'ORDER BY' and ('COUNT' or 'age'). Got: {}",
2342			sql
2343		);
2344	}
2345
2346	#[test]
2347	// From: Django/annotations
2348	fn test_order_by_alias_aggregate_1() {
2349		// Test order by aggregate with different ordering
2350		use crate::orm::aggregation::Aggregate;
2351		use crate::orm::query::QuerySet;
2352
2353		let qs = QuerySet::<TestModel>::new()
2354			.annotate(Annotation::field(
2355				"total",
2356				AnnotationValue::Aggregate(Aggregate::sum("value")),
2357			))
2358			.order_by(&["-total"]);
2359
2360		let sql = qs.to_sql();
2361
2362		assert!(
2363			sql.contains("ORDER BY") && sql.contains("SUM"),
2364			"SQL should contain 'ORDER BY' and 'SUM'. Got: {}",
2365			sql
2366		);
2367	}
2368
2369	#[test]
2370	// From: Django/annotations
2371	fn test_order_by_annotation() {
2372		// Django: Author.objects.annotate(other_age=F("age")).order_by("other_age")
2373		use crate::orm::expressions::F;
2374		use crate::orm::query::QuerySet;
2375
2376		let qs = QuerySet::<TestModel>::new()
2377			.annotate(Annotation::field(
2378				"other_age",
2379				AnnotationValue::Field(F::new("age")),
2380			))
2381			.order_by(&["other_age"]);
2382
2383		let sql = qs.to_sql();
2384
2385		assert!(
2386			sql.contains("ORDER BY") && (sql.contains("age") || sql.contains("other_age")),
2387			"SQL should contain 'ORDER BY' and ('age' or 'other_age'). Got: {}",
2388			sql
2389		);
2390	}
2391
2392	#[test]
2393	// From: Django/annotations
2394	fn test_order_by_annotation_1() {
2395		// Test order by multiple annotations
2396		use crate::orm::expressions::F;
2397		use crate::orm::query::QuerySet;
2398
2399		let qs = QuerySet::<TestModel>::new()
2400			.annotate(Annotation::field(
2401				"field1_alias",
2402				AnnotationValue::Field(F::new("field1")),
2403			))
2404			.annotate(Annotation::field(
2405				"field2_alias",
2406				AnnotationValue::Field(F::new("field2")),
2407			))
2408			.order_by(&["field1_alias", "-field2_alias"]);
2409
2410		let sql = qs.to_sql();
2411
2412		assert!(
2413			sql.contains("ORDER BY"),
2414			"SQL should contain ORDER BY clause. Got: {}",
2415			sql
2416		);
2417	}
2418
2419	#[test]
2420	// From: Django/annotations
2421	fn test_q_expression_annotation_with_aggregation() {
2422		// Test Q expression annotation with aggregation
2423		use crate::orm::aggregation::Aggregate;
2424		use crate::orm::expressions::F;
2425
2426		let qs = QuerySet::<TestModel>::new()
2427			.annotate(Annotation::field(
2428				"computed",
2429				AnnotationValue::Field(F::new("value")),
2430			))
2431			.annotate(Annotation::field(
2432				"count",
2433				AnnotationValue::Aggregate(Aggregate::count(Some("id"))),
2434			));
2435
2436		let sql = qs.to_sql();
2437
2438		assert!(
2439			sql.contains("COUNT") || sql.contains("value"),
2440			"SQL should contain 'COUNT' or 'value'. Got: {}",
2441			sql
2442		);
2443	}
2444
2445	#[test]
2446	// From: Django/annotations
2447	fn test_q_expression_annotation_with_aggregation_1() {
2448		// Test Q expression with different aggregation
2449		use crate::orm::aggregation::Aggregate;
2450		use crate::orm::expressions::F;
2451
2452		let qs = QuerySet::<TestModel>::new()
2453			.annotate(Annotation::field(
2454				"filtered",
2455				AnnotationValue::Field(F::new("status")),
2456			))
2457			.annotate(Annotation::field(
2458				"total",
2459				AnnotationValue::Aggregate(Aggregate::sum("amount")),
2460			));
2461
2462		let sql = qs.to_sql();
2463
2464		assert!(
2465			sql.contains("SUM") || sql.contains("status"),
2466			"SQL should contain 'SUM' or 'status'. Got: {}",
2467			sql
2468		);
2469	}
2470
2471	#[test]
2472	// From: Django/annotations
2473	fn test_raw_sql_with_inherited_field() {
2474		// Test raw SQL annotation with inherited field
2475		use crate::orm::expressions::F;
2476
2477		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
2478			"raw_field",
2479			AnnotationValue::Field(F::new("inherited_field")),
2480		));
2481
2482		let sql = qs.to_sql();
2483
2484		assert!(
2485			sql.contains("inherited_field") || sql.contains("raw_field"),
2486			"SQL should contain 'inherited_field' or 'raw_field'. Got: {}",
2487			sql
2488		);
2489	}
2490
2491	#[test]
2492	// From: Django/annotations
2493	fn test_raw_sql_with_inherited_field_1() {
2494		// Test raw SQL with different inherited field
2495		use crate::orm::expressions::F;
2496
2497		let qs = QuerySet::<TestModel>::new().annotate(Annotation::field(
2498			"parent_field",
2499			AnnotationValue::Field(F::new("base_field")),
2500		));
2501
2502		let sql = qs.to_sql();
2503
2504		assert!(
2505			sql.contains("base_field") || sql.contains("parent_field"),
2506			"SQL should contain 'base_field' or 'parent_field'. Got: {}",
2507			sql
2508		);
2509	}
2510}