without_clone/
without_clone.rs

1// Demonstrates that the query builder works without Clone derive
2// Most operations only require references, not cloning
3// cargo run --example without_clone
4
5use rust_queries_builder::{Query, JoinQuery};
6use key_paths_derive::Keypaths;
7
8// Notice: NO Clone derive! This struct cannot be cloned.
9#[derive(Debug, Keypaths)]
10struct Employee {
11    id: u32,
12    name: String,
13    email: String,
14    department: String,
15    salary: f64,
16    // Imagine this contains large data that's expensive to clone
17    large_data: Vec<u8>,
18}
19
20// Another struct without Clone
21#[derive(Debug, Keypaths)]
22struct Department {
23    id: u32,
24    name: String,
25    budget: f64,
26}
27
28fn main() {
29    println!("╔════════════════════════════════════════════════════════════╗");
30    println!("║  Query Builder Without Clone - Performance Optimization   ║");
31    println!("╚════════════════════════════════════════════════════════════╝\n");
32
33    let employees = vec![
34        Employee {
35            id: 1,
36            name: "Alice".to_string(),
37            email: "alice@example.com".to_string(),
38            department: "Engineering".to_string(),
39            salary: 95000.0,
40            large_data: vec![0; 1000], // Large data - expensive to clone!
41        },
42        Employee {
43            id: 2,
44            name: "Bob".to_string(),
45            email: "bob@example.com".to_string(),
46            department: "Engineering".to_string(),
47            salary: 87000.0,
48            large_data: vec![0; 1000],
49        },
50        Employee {
51            id: 3,
52            name: "Carol".to_string(),
53            email: "carol@example.com".to_string(),
54            department: "Sales".to_string(),
55            salary: 75000.0,
56            large_data: vec![0; 1000],
57        },
58    ];
59
60    let departments = vec![
61        Department {
62            id: 1,
63            name: "Engineering".to_string(),
64            budget: 1000000.0,
65        },
66        Department {
67            id: 2,
68            name: "Sales".to_string(),
69            budget: 500000.0,
70        },
71    ];
72
73    println!("✅ Operations that DON'T require Clone:\n");
74
75    // 1. WHERE filtering - returns Vec<&T>
76    println!("1. WHERE filtering (returns references)");
77    let query = Query::new(&employees)
78        .where_(Employee::department_r(), |dept| dept == "Engineering");
79    let engineering = query.all();
80    println!("   Found {} engineering employees", engineering.len());
81    for emp in &engineering {
82        println!("     - {}: ${:.0}", emp.name, emp.salary);
83    }
84
85    // 2. COUNT - no cloning needed
86    println!("\n2. COUNT aggregation");
87    let count = Query::new(&employees)
88        .where_(Employee::salary_r(), |&sal| sal > 80000.0)
89        .count();
90    println!("   {} employees earn over $80k", count);
91
92    // 3. SELECT - only clones the selected field
93    println!("\n3. SELECT (only selected fields are cloned)");
94    let names: Vec<String> = Query::new(&employees)
95        .select(Employee::name_r());
96    println!("   Employee names: {:?}", names);
97
98    // 4. FIRST - returns Option<&T>
99    println!("\n4. FIRST (returns reference)");
100    let query = Query::new(&employees)
101        .where_(Employee::salary_r(), |&sal| sal > 90000.0);
102    if let Some(emp) = query.first() {
103        println!("   First high earner: {} (${:.0})", emp.name, emp.salary);
104    }
105
106    // 5. SUM/AVG aggregations - no cloning
107    println!("\n5. Aggregations (SUM/AVG)");
108    let eng_query = Query::new(&employees)
109        .where_(Employee::department_r(), |dept| dept == "Engineering");
110    let total = eng_query.sum(Employee::salary_r());
111    let avg = eng_query.avg(Employee::salary_r()).unwrap_or(0.0);
112    println!("   Engineering total: ${:.0}", total);
113    println!("   Engineering average: ${:.0}", avg);
114
115    // 6. MIN/MAX - no cloning
116    println!("\n6. MIN/MAX");
117    let min = Query::new(&employees).min_float(Employee::salary_r());
118    let max = Query::new(&employees).max_float(Employee::salary_r());
119    println!("   Salary range: ${:.0} - ${:.0}", min.unwrap(), max.unwrap());
120
121    // 7. LIMIT - returns Vec<&T>
122    println!("\n7. LIMIT (returns references)");
123    let query = Query::new(&employees);
124    let first_two = query.limit(2);
125    println!("   First 2 employees:");
126    for emp in &first_two {
127        println!("     - {}", emp.name);
128    }
129
130    // 8. SKIP/Pagination - returns Vec<&T>
131    println!("\n8. SKIP/Pagination (returns references)");
132    let query = Query::new(&employees);
133    let page_2 = query.skip(2).limit(1);
134    println!("   Page 2:");
135    for emp in &page_2 {
136        println!("     - {}", emp.name);
137    }
138
139    // 9. EXISTS - just checks
140    println!("\n9. EXISTS check");
141    let has_sales = Query::new(&employees)
142        .where_(Employee::department_r(), |dept| dept == "Sales")
143        .exists();
144    println!("   Has Sales employees: {}", has_sales);
145
146    // 10. JOIN - no Clone required on L or R!
147    println!("\n10. JOIN operations (no Clone required!)");
148    let results = JoinQuery::new(&employees, &departments)
149        .inner_join(
150            Employee::department_r(),
151            Department::name_r(),
152            |emp, dept| {
153                // Mapper only clones what it needs for the result
154                (emp.name.clone(), dept.budget)
155            },
156        );
157    println!("   Employee-Department pairs:");
158    for (name, budget) in &results {
159        println!("     - {} works in dept with ${:.0} budget", name, budget);
160    }
161
162    println!("\n╔════════════════════════════════════════════════════════════╗");
163    println!("║  Operations that REQUIRE Clone (only when needed)         ║");
164    println!("╚════════════════════════════════════════════════════════════╝\n");
165
166    println!("⚠️  The following operations require Clone because they return owned Vec<T>:");
167    println!("   - order_by() / order_by_desc()");
168    println!("   - order_by_float() / order_by_float_desc()");
169    println!("   - group_by()");
170    println!("\n   To use these, add #[derive(Clone)] to your struct:");
171    println!("   ```rust");
172    println!("   #[derive(Clone, Keypaths)]  // Add Clone here");
173    println!("   struct Employee {{ ... }}");
174    println!("   ```");
175
176    println!("\n╔════════════════════════════════════════════════════════════╗");
177    println!("║  Performance Benefits                                      ║");
178    println!("╚════════════════════════════════════════════════════════════╝\n");
179
180    println!("✅ Zero cloning for most operations");
181    println!("✅ Work with large structs efficiently");
182    println!("✅ No unnecessary memory allocations");
183    println!("✅ Only clone when you actually need owned data");
184    println!("✅ Pay for what you use");
185
186    println!("\n✓ Example complete! Most operations work without Clone.\n");
187}
188