elif_orm/query/
performance_optimized.rs1use super::builder::QueryBuilder;
7use once_cell::sync::Lazy;
8use std::collections::HashMap;
9use std::sync::{Arc, RwLock};
10
11#[allow(dead_code)]
13static QUERY_TEMPLATE_CACHE: Lazy<RwLock<HashMap<String, String>>> =
14 Lazy::new(|| RwLock::new(HashMap::new()));
15
16static PLACEHOLDER_CACHE: Lazy<RwLock<HashMap<usize, String>>> =
18 Lazy::new(|| RwLock::new(HashMap::new()));
19
20impl<M> QueryBuilder<M> {
22 pub fn generate_placeholders_cached(count: usize) -> String {
24 if let Ok(cache) = PLACEHOLDER_CACHE.read() {
26 if let Some(cached) = cache.get(&count) {
27 return cached.clone();
28 }
29 }
30
31 let placeholders = (1..=count)
33 .map(|i| format!("${}", i))
34 .collect::<Vec<_>>()
35 .join(", ");
36
37 if let Ok(mut cache) = PLACEHOLDER_CACHE.write() {
39 cache.insert(count, placeholders.clone());
40 }
41
42 placeholders
43 }
44
45 pub fn generate_sequential_placeholders(start_index: usize, count: usize) -> String {
48 if count == 0 {
49 return String::new();
50 }
51
52 let placeholders = (start_index..start_index + count)
53 .map(|i| format!("${}", i))
54 .collect::<Vec<_>>()
55 .join(", ");
56
57 placeholders
58 }
59
60 pub fn to_sql_optimized(&self) -> String {
62 let estimated_length = self.estimate_sql_length();
64 let mut sql = String::with_capacity(estimated_length);
65
66 match self.query_type {
67 super::types::QueryType::Select => {
68 self.build_select_sql_optimized(&mut sql);
69 }
70 _ => {
71 return self.to_sql();
73 }
74 }
75
76 sql
77 }
78
79 fn estimate_sql_length(&self) -> usize {
81 let mut length = 100; for field in &self.select_fields {
85 length += field.len() + 2; }
87
88 for table in &self.from_tables {
90 length += table.len() + 10; }
92
93 for condition in &self.where_conditions {
95 length += condition.column.len() + 20; }
97
98 for join in &self.joins {
100 length += join.table.len() + 30; }
102
103 length
104 }
105
106 fn build_select_sql_optimized(&self, sql: &mut String) {
108 let mut param_counter = 1usize;
109 if self.distinct {
111 sql.push_str("SELECT DISTINCT ");
112 } else {
113 sql.push_str("SELECT ");
114 }
115
116 if self.select_fields.is_empty() {
118 sql.push('*');
119 } else {
120 for (i, field) in self.select_fields.iter().enumerate() {
121 if i > 0 {
122 sql.push_str(", ");
123 }
124 sql.push_str(field);
125 }
126 }
127
128 if !self.from_tables.is_empty() {
130 sql.push_str(" FROM ");
131 for (i, table) in self.from_tables.iter().enumerate() {
132 if i > 0 {
133 sql.push_str(", ");
134 }
135 sql.push_str(table);
136 }
137 }
138
139 for join in &self.joins {
141 sql.push(' ');
142 match join.join_type {
143 super::types::JoinType::Inner => sql.push_str("INNER JOIN"),
144 super::types::JoinType::Left => sql.push_str("LEFT JOIN"),
145 super::types::JoinType::Right => sql.push_str("RIGHT JOIN"),
146 super::types::JoinType::Full => sql.push_str("FULL JOIN"),
147 }
148 sql.push(' ');
149 sql.push_str(&join.table);
150 sql.push_str(" ON ");
151
152 for (i, (left_col, right_col)) in join.on_conditions.iter().enumerate() {
154 if i > 0 {
155 sql.push_str(" AND ");
156 }
157 sql.push_str(left_col);
158 sql.push_str(" = ");
159 sql.push_str(right_col);
160 }
161 }
162
163 if !self.where_conditions.is_empty() {
165 sql.push_str(" WHERE ");
166 for (i, condition) in self.where_conditions.iter().enumerate() {
167 if i > 0 {
168 sql.push_str(" AND ");
169 }
170
171 if condition.column == "RAW" {
173 if let Some(ref value) = condition.value {
174 if let serde_json::Value::String(raw_sql) = value {
175 sql.push_str(raw_sql);
176 }
177 }
178 } else if condition.column == "EXISTS" || condition.column == "NOT EXISTS" {
179 sql.push_str(&condition.column);
180 sql.push(' ');
181 if let Some(ref value) = condition.value {
182 if let serde_json::Value::String(subquery) = value {
183 sql.push_str(subquery);
184 }
185 }
186 } else {
187 sql.push_str(&condition.column);
189
190 match condition.operator {
191 super::types::QueryOperator::Equal => sql.push_str(" = "),
192 super::types::QueryOperator::NotEqual => sql.push_str(" != "),
193 super::types::QueryOperator::GreaterThan => sql.push_str(" > "),
194 super::types::QueryOperator::LessThan => sql.push_str(" < "),
195 super::types::QueryOperator::GreaterThanOrEqual => sql.push_str(" >= "),
196 super::types::QueryOperator::LessThanOrEqual => sql.push_str(" <= "),
197 super::types::QueryOperator::Like => sql.push_str(" LIKE "),
198 super::types::QueryOperator::NotLike => sql.push_str(" NOT LIKE "),
199 super::types::QueryOperator::In => {
200 sql.push_str(" IN (");
201 let placeholder_count = condition.values.len();
202 if placeholder_count > 0 {
203 let placeholders = Self::generate_sequential_placeholders(
204 param_counter,
205 placeholder_count,
206 );
207 sql.push_str(&placeholders);
208 param_counter += placeholder_count;
209 }
210 sql.push(')');
211 continue; }
213 super::types::QueryOperator::NotIn => {
214 sql.push_str(" NOT IN (");
215 let placeholder_count = condition.values.len();
216 if placeholder_count > 0 {
217 let placeholders = Self::generate_sequential_placeholders(
218 param_counter,
219 placeholder_count,
220 );
221 sql.push_str(&placeholders);
222 param_counter += placeholder_count;
223 }
224 sql.push(')');
225 continue; }
227 super::types::QueryOperator::IsNull => {
228 sql.push_str(" IS NULL");
229 continue;
230 }
231 super::types::QueryOperator::IsNotNull => {
232 sql.push_str(" IS NOT NULL");
233 continue;
234 }
235 super::types::QueryOperator::Between => {
236 sql.push_str(&format!(
237 " BETWEEN ${} AND ${}",
238 param_counter,
239 param_counter + 1
240 ));
241 param_counter += 2;
242 continue;
243 }
244 super::types::QueryOperator::Raw => {
245 if let Some(ref value) = condition.value {
247 if let serde_json::Value::String(raw_expr) = value {
248 sql.push(' ');
249 sql.push_str(raw_expr);
250 }
251 }
252 continue;
253 }
254 }
255
256 sql.push_str(&format!("${}", param_counter));
258 param_counter += 1;
259 }
260 }
261 }
262
263 if !self.group_by.is_empty() {
265 sql.push_str(" GROUP BY ");
266 for (i, column) in self.group_by.iter().enumerate() {
267 if i > 0 {
268 sql.push_str(", ");
269 }
270 sql.push_str(column);
271 }
272 }
273
274 if !self.having_conditions.is_empty() {
276 sql.push_str(" HAVING ");
277 for (i, condition) in self.having_conditions.iter().enumerate() {
278 if i > 0 {
279 sql.push_str(" AND ");
280 }
281 sql.push_str(&condition.column);
282
283 match condition.operator {
285 super::types::QueryOperator::Equal => sql.push_str(" = "),
286 super::types::QueryOperator::GreaterThan => sql.push_str(" > "),
287 super::types::QueryOperator::LessThan => sql.push_str(" < "),
288 _ => sql.push_str(" = "), }
290
291 sql.push_str(&format!("${}", param_counter));
292 param_counter += 1;
293 }
294 }
295
296 if !self.order_by.is_empty() {
298 sql.push_str(" ORDER BY ");
299 for (i, (column, direction)) in self.order_by.iter().enumerate() {
300 if i > 0 {
301 sql.push_str(", ");
302 }
303 sql.push_str(column);
304 match direction {
305 super::types::OrderDirection::Asc => sql.push_str(" ASC"),
306 super::types::OrderDirection::Desc => sql.push_str(" DESC"),
307 }
308 }
309 }
310
311 if let Some(limit) = self.limit_count {
313 sql.push_str(" LIMIT ");
314 sql.push_str(&limit.to_string());
315 }
316
317 if let Some(offset) = self.offset_value {
319 sql.push_str(" OFFSET ");
320 sql.push_str(&offset.to_string());
321 }
322 }
323}
324
325pub struct QueryBuilderPool {
327 pool: Arc<RwLock<Vec<QueryBuilder<()>>>>,
328 max_size: usize,
329}
330
331impl QueryBuilderPool {
332 pub fn new(max_size: usize) -> Self {
333 Self {
334 pool: Arc::new(RwLock::new(Vec::with_capacity(max_size))),
335 max_size,
336 }
337 }
338
339 pub fn acquire(&self) -> QueryBuilder<()> {
341 if let Ok(mut pool) = self.pool.write() {
342 if let Some(mut builder) = pool.pop() {
343 builder.reset();
345 return builder;
346 }
347 }
348
349 QueryBuilder::new()
351 }
352
353 pub fn release(&self, builder: QueryBuilder<()>) {
355 if let Ok(mut pool) = self.pool.write() {
356 if pool.len() < self.max_size {
357 pool.push(builder);
358 }
359 }
361 }
362}
363
364impl<M> QueryBuilder<M> {
365 pub fn reset(&mut self) {
367 self.query_type = super::types::QueryType::Select;
368 self.select_fields.clear();
369 self.from_tables.clear();
370 self.insert_table = None;
371 self.update_table = None;
372 self.delete_table = None;
373 self.set_clauses.clear();
374 self.where_conditions.clear();
375 self.joins.clear();
376 self.order_by.clear();
377 self.group_by.clear();
378 self.having_conditions.clear();
379 self.limit_count = None;
380 self.offset_value = None;
381 self.distinct = false;
382 }
383}
384
385static GLOBAL_QUERY_POOL: Lazy<QueryBuilderPool> = Lazy::new(|| {
387 QueryBuilderPool::new(100) });
389
390pub fn acquire_query_builder() -> QueryBuilder<()> {
392 GLOBAL_QUERY_POOL.acquire()
393}
394
395pub fn release_query_builder(builder: QueryBuilder<()>) {
397 GLOBAL_QUERY_POOL.release(builder);
398}
399
400#[cfg(test)]
401mod tests {
402 use super::*;
403
404 #[test]
405 fn test_placeholder_caching() {
406 let placeholders1 = QueryBuilder::<()>::generate_placeholders_cached(3);
407 let placeholders2 = QueryBuilder::<()>::generate_placeholders_cached(3);
408
409 assert_eq!(placeholders1, "$1, $2, $3");
410 assert_eq!(placeholders1, placeholders2);
411 }
412
413 #[test]
414 fn test_query_builder_pool() {
415 let pool = QueryBuilderPool::new(2);
416
417 let builder1 = pool.acquire();
418 let builder2 = pool.acquire();
419
420 pool.release(builder1);
421 pool.release(builder2);
422
423 let builder3 = pool.acquire(); assert!(!builder3.from_tables.is_empty() || builder3.from_tables.is_empty());
425 }
427
428 #[test]
429 fn test_optimized_sql_generation() {
430 let query: QueryBuilder<()> = QueryBuilder::new()
431 .from("users")
432 .select("id, name, email")
433 .where_eq("active", "true");
434
435 let sql = query.to_sql_optimized();
436 assert!(sql.contains("SELECT"));
437 assert!(sql.contains("FROM users"));
438 assert!(sql.contains("WHERE"));
439 }
440}