Skip to main content

bottle_orm/
query_builder.rs

1//! # Query Builder Module
2//!
3//! This module provides a fluent interface for constructing and executing SQL queries.
4//! It handles SELECT, INSERT, filtering (WHERE), pagination (LIMIT/OFFSET), and ordering operations
5//! with type-safe parameter binding across different database drivers.
6//!
7//! ## Features
8//!
9//! - **Fluent API**: Chainable methods for building complex queries
10//! - **Type-Safe Binding**: Automatic parameter binding with support for multiple types
11//! - **Multi-Driver Support**: Works with PostgreSQL, MySQL, and SQLite
12//! - **UUID Support**: Full support for UUID versions 1-7
13//! - **Pagination**: Built-in LIMIT/OFFSET support with helper methods
14//! - **Custom Filters**: Support for manual SQL construction with closures
15//!
16//! ## Example Usage
17//!
18//! ```rust,ignore
19//! use bottle_orm::{Database, Model};
20//! 
21//!
22//! // Simple query
23//! let users: Vec<User> = db.model::<User>()
24//!     .filter("age", ">=", 18)
25//!     .order("created_at DESC")
26//!     .limit(10)
27//!     .scan()
28//!     .await?;
29//!
30//! // Query with UUID filter
31//! let user_id = Uuid::new_v4();
32//! let user: User = db.model::<User>()
33//!     .filter("id", "=", user_id)
34//!     .first()
35//!     .await?;
36//!
37//! // Insert a new record
38//! let new_user = User {
39//!     id: Uuid::new_v7(uuid::Timestamp::now(uuid::NoContext)),
40//!     username: "john_doe".to_string(),
41//!     age: 25,
42//! };
43//! db.model::<User>().insert(&new_user).await?;
44//! ```
45
46// ============================================================================
47// External Crate Imports
48// ============================================================================
49
50use futures::future::BoxFuture;
51use heck::ToSnakeCase;
52use sqlx::{Any, Arguments, Decode, Encode, Type, any::AnyArguments};
53use std::marker::PhantomData;
54use std::collections::{HashMap, HashSet};
55
56
57// ============================================================================
58// Internal Crate Imports
59// ============================================================================
60
61use crate::{
62    AnyImpl, Error,
63    any_struct::FromAnyRow,
64    database::{Connection, Drivers},
65    model::{ColumnInfo, Model},
66    temporal::{self, is_temporal_type},
67    value_binding::ValueBinder,
68};
69
70// ============================================================================
71// Type Aliases
72// ============================================================================
73
74/// A type alias for filter closures that support manual SQL construction and argument binding.
75///
76/// Filter functions receive the following parameters:
77/// 1. `&mut String` - The SQL query buffer being built
78/// 2. `&mut AnyArguments` - The argument container for binding values
79/// 3. `&Drivers` - The current database driver (determines placeholder syntax)
80/// 4. `&mut usize` - The argument counter (for PostgreSQL `$n` placeholders)
81///
82/// ## Example
83///
84/// ```rust,ignore
85/// let custom_filter: FilterFn = Box::new(|query, args, driver, counter| {
86///     query.push_str(" AND age > ");
87///     match driver {
88///         Drivers::Postgres => {
89///             query.push_str(&format!("${}", counter));
90///             *counter += 1;
91///         }
92///         _ => query.push('?'),
93///     }
94///     args.add(18);
95/// });
96/// });\n/// ```
97pub type FilterFn = Box<dyn Fn(&mut String, &mut AnyArguments<'_>, &Drivers, &mut usize) + Send + Sync>;
98
99// ============================================================================
100// Update Value Traits
101// ============================================================================
102
103/// Trait for types that can be converted to an optional string value for SQL updates.
104///
105/// This trait is used by the `update` method to handle both direct values
106/// (e.g., `update("role", "admin")`) and NULL values (e.g., `update("role", None::<String>)`).
107pub trait ToUpdateValue {
108    /// Converts the value to an `Option<String>` for SQL binding.
109    ///
110    /// # Returns
111    ///
112    /// * `Some(String)` - String representation for a database value
113    /// * `None` - Represents a SQL `NULL`
114    fn to_update_value(self) -> Option<String>;
115}
116
117macro_rules! impl_update_value {
118    ($($t:ty),*) => {
119        $(
120            impl ToUpdateValue for $t {
121                fn to_update_value(self) -> Option<String> {
122                    Some(self.to_string())
123                }
124            }
125            impl ToUpdateValue for Option<$t> {
126                fn to_update_value(self) -> Option<String> {
127                    self.map(|v| v.to_string())
128                }
129            }
130        )*
131    }
132}
133
134impl_update_value!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, f32, f64, bool, String, &str, uuid::Uuid);
135impl_update_value!(chrono::DateTime<chrono::Utc>, chrono::DateTime<chrono::FixedOffset>, chrono::NaiveDateTime, chrono::NaiveDate, chrono::NaiveTime);
136
137// ============================================================================
138// Comparison Operators Enum
139// ============================================================================
140
141/// Type-safe comparison operators for filter conditions.
142///
143/// Use these instead of string operators for autocomplete support and type safety.
144///
145/// # Example
146///
147/// ```rust,ignore
148/// use bottle_orm::Op;
149///
150/// db.model::<User>()
151///     .filter(user_fields::AGE, Op::Gte, 18)
152///     .filter(user_fields::NAME, Op::Like, "%John%")
153///     .scan()
154///     .await?;
155/// ```
156#[derive(Debug, Clone, Copy, PartialEq, Eq)]
157pub enum Op {
158    /// Equal: `=`
159    Eq,
160    /// Not Equal: `!=` or `<>`
161    Ne,
162    /// Greater Than: `>`
163    Gt,
164    /// Greater Than or Equal: `>=`
165    Gte,
166    /// Less Than: `<`
167    Lt,
168    /// Less Than or Equal: `<=`
169    Lte,
170    /// SQL LIKE pattern matching
171    Like,
172    /// SQL NOT LIKE pattern matching
173    NotLike,
174    /// SQL IN (for arrays/lists)
175    In,
176    /// SQL NOT IN
177    NotIn,
178    /// SQL BETWEEN
179    Between,
180    /// SQL NOT BETWEEN
181    NotBetween,
182}
183
184impl Op {
185    /// Converts the operator to its SQL string representation.
186    pub fn as_sql(&self) -> &'static str {
187        match self {
188            Op::Eq => "=",
189            Op::Ne => "!=",
190            Op::Gt => ">",
191            Op::Gte => ">=",
192            Op::Lt => "<",
193            Op::Lte => "<=",
194            Op::Like => "LIKE",
195            Op::NotLike => "NOT LIKE",
196            Op::In => "IN",
197            Op::NotIn => "NOT IN",
198            Op::Between => "BETWEEN",
199            Op::NotBetween => "NOT BETWEEN",
200        }
201    }
202}
203
204// ============================================================================
205// QueryBuilder Struct
206// ============================================================================
207
208/// A fluent Query Builder for constructing SQL queries.
209///
210/// `QueryBuilder` provides a type-safe, ergonomic interface for building and executing
211/// SQL queries across different database backends. It supports filtering, ordering,
212/// pagination, and both SELECT and INSERT operations.
213///
214/// ## Type Parameter
215///
216/// * `'a` - Lifetime of the database reference (used for PhantomData)
217/// * `T` - The Model type this query operates on
218/// * `E` - The connection type (Database or Transaction)
219///
220/// ## Fields
221///
222/// * `db` - Reference to the database connection pool or transaction
223/// * `table_name` - Static string containing the table name
224/// * `columns_info` - Metadata about each column in the table
225/// * `columns` - List of column names in snake_case format
226/// * `select_columns` - Specific columns to select (empty = SELECT *)
227/// * `where_clauses` - List of filter functions to apply
228/// * `order_clauses` - List of ORDER BY clauses
229/// * `limit` - Maximum number of rows to return
230/// * `offset` - Number of rows to skip (for pagination)
231/// * `_marker` - PhantomData to bind the generic type T
232pub struct QueryBuilder<T, E> {
233    /// Reference to the database connection pool
234    pub(crate) tx: E,
235
236    /// Database driver type
237    pub(crate) driver: Drivers,
238
239    /// Name of the database table (in original case)
240    pub(crate) table_name: &'static str,
241
242    pub(crate) alias: Option<String>,
243
244    /// Metadata information about each column
245    pub(crate) columns_info: Vec<ColumnInfo>,
246
247    /// List of column names (in snake_case)
248    pub(crate) columns: Vec<String>,
249
250    /// Specific columns to select (empty means SELECT *)
251    pub(crate) select_columns: Vec<String>,
252
253    /// Collection of WHERE clause filter functions
254    pub(crate) where_clauses: Vec<FilterFn>,
255
256    /// Collection of ORDER BY clauses
257    pub(crate) order_clauses: Vec<String>,
258
259    /// Collection of JOIN clause to filter entry tables
260    pub(crate) joins_clauses: Vec<FilterFn>,
261
262    /// Map of table names to their aliases used in JOINS
263    pub(crate) join_aliases: std::collections::HashMap<String, String>,
264
265    /// Maximum number of rows to return (LIMIT)
266    pub(crate) limit: Option<usize>,
267
268    /// Number of rows to skip (OFFSET)
269    pub(crate) offset: Option<usize>,
270
271    /// Activate debug mode in query
272    pub(crate) debug_mode: bool,
273
274    /// Clauses for GROUP BY
275    pub(crate) group_by_clauses: Vec<String>,
276
277    /// Clauses for HAVING
278    pub(crate) having_clauses: Vec<FilterFn>,
279
280    /// Distinct flag
281    pub(crate) is_distinct: bool,
282
283    /// Columns to omit from the query results (inverse of select_columns)
284    pub(crate) omit_columns: Vec<String>,
285
286    /// Whether to include soft-deleted records in query results
287    pub(crate) with_deleted: bool,
288
289    /// UNION and UNION ALL clauses
290    pub(crate) union_clauses: Vec<(String, FilterFn)>,
291
292    /// PhantomData to bind the generic type T
293    pub(crate) _marker: PhantomData<T>,
294}
295
296// ============================================================================
297// QueryBuilder Implementation
298// ============================================================================
299
300impl<T, E> QueryBuilder<T, E>
301where
302    T: Model + Send + Sync + Unpin + AnyImpl,
303    E: Connection,
304{
305    // ========================================================================
306    // Constructor
307    // ========================================================================
308
309    /// Creates a new QueryBuilder instance.
310    ///
311    /// This constructor is typically called internally via `db.model::<T>()`.
312    /// You rarely need to call this directly.
313    ///
314    /// # Arguments
315    ///
316    /// * `db` - Reference to the database connection
317    /// * `table_name` - Name of the table to query
318    /// * `columns_info` - Metadata about table columns
319    /// * `columns` - List of column names
320    ///
321    /// # Returns
322    ///
323    /// A new `QueryBuilder` instance ready for query construction
324    ///
325    /// # Example
326    ///
327    /// ```rust,ignore
328    /// // Usually called via db.model::<User>()
329    /// let query = db.model::<User>();
330    /// ```
331    pub fn new(
332        tx: E,
333        driver: Drivers,
334        table_name: &'static str,
335        columns_info: Vec<ColumnInfo>,
336        columns: Vec<String>,
337    ) -> Self {
338        // Pre-populate omit_columns with globally omitted columns (from #[orm(omit)] attribute)
339        let omit_columns: Vec<String> =
340            columns_info.iter().filter(|c| c.omit).map(|c| c.name.to_snake_case()).collect();
341
342        Self {
343            tx,
344            alias: None,
345            driver,
346            table_name,
347            columns_info,
348            columns,
349            debug_mode: false,
350            select_columns: Vec::new(),
351            where_clauses: Vec::new(),
352            order_clauses: Vec::new(),
353            joins_clauses: Vec::new(),
354            join_aliases: std::collections::HashMap::new(),
355            group_by_clauses: Vec::new(),
356            having_clauses: Vec::new(),
357            is_distinct: false,
358            omit_columns,
359            limit: None,
360            offset: None,
361            with_deleted: false,
362            union_clauses: Vec::new(),
363            _marker: PhantomData,
364        }
365    }
366
367    /// Returns the table name or alias if set.
368    pub(crate) fn get_table_identifier(&self) -> String {
369        self.alias.clone().unwrap_or_else(|| self.table_name.to_snake_case())
370    }
371
372    // ========================================================================
373    // Query Building Methods
374    // ========================================================================
375
376    /// Internal helper to add a WHERE clause with a specific join operator.
377    fn filter_internal<V>(mut self, joiner: &str, col: &'static str, op: Op, value: V) -> Self
378    where
379        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
380    {
381        let op_str = op.as_sql();
382        let table_id = self.get_table_identifier();
383        // Check if the column exists in the main table to avoid ambiguous references in JOINS
384        let is_main_col = self.columns.contains(&col.to_snake_case());
385        let joiner_owned = joiner.to_string();
386        let clause: FilterFn = Box::new(move |query, args, driver, arg_counter| {
387            query.push_str(&joiner_owned);
388            if let Some((table, column)) = col.split_once(".") {
389                // If explicit table prefix is provided, use it
390                query.push_str(&format!("\"{}\".\"{}\"", table, column));
391            } else if is_main_col {
392                // If it's a known column of the main table, apply the table name/alias prefix
393                query.push_str(&format!("\"{}\".\"{}\"", table_id, col));
394            } else {
395                // Otherwise leave it unqualified so the DB can resolve it (or fail if ambiguous)
396                query.push_str(&format!("\"{}\"", col));
397            }
398            query.push(' ');
399            query.push_str(op_str);
400            query.push(' ');
401
402            // Handle different placeholder syntaxes based on database driver
403            match driver {
404                // PostgreSQL uses numbered placeholders: $1, $2, $3, ...
405                Drivers::Postgres => {
406                    query.push_str(&format!("${}", arg_counter));
407                    *arg_counter += 1;
408                }
409                // MySQL and SQLite use question mark placeholders: ?
410                _ => query.push('?'),
411            }
412
413            // Bind the value to the query
414            let _ = args.add(value.clone());
415        });
416
417        self.where_clauses.push(clause);
418        self
419    }
420
421    /// Adds a WHERE IN (SUBQUERY) clause to the query.
422    ///
423    /// This allows for filtering a column based on the results of another query.
424    ///
425    /// # Example
426    /// ```rust,ignore
427    /// let subquery = db.model::<Post>().select("user_id").filter("views", ">", 1000);
428    /// db.model::<User>().filter_subquery("id", Op::In, subquery).scan().await?;
429    /// ```
430    pub fn filter_subquery<S, SE>(mut self, col: &'static str, op: Op, mut subquery: QueryBuilder<S, SE>) -> Self
431    where
432        S: Model + Send + Sync + Unpin + AnyImpl + 'static,
433        SE: Connection + 'static,
434    {
435        subquery.apply_soft_delete_filter();
436        let table_id = self.get_table_identifier();
437        let is_main_col = self.columns.contains(&col.to_snake_case());
438        let op_str = op.as_sql();
439
440        let clause: FilterFn = Box::new(move |query, args, _driver, arg_counter| {
441            query.push_str(" AND ");
442            if let Some((table, column)) = col.split_once(".") {
443                query.push_str(&format!("\"{}\".\"{}\"", table, column));
444            } else if is_main_col {
445                query.push_str(&format!("\"{}\".\"{}\"", table_id, col));
446            } else {
447                query.push_str(&format!("\"{}\"", col));
448            }
449            query.push_str(&format!(" {} (", op_str));
450
451            subquery.write_select_sql::<S>(query, args, arg_counter);
452            query.push_str(")");
453        });
454
455        self.where_clauses.push(clause);
456        self
457    }
458
459    /// Truncates the table associated with this Model.
460    ///
461    /// This method removes all records from the table. It uses `TRUNCATE TABLE`
462    /// for Postgres and MySQL, and `DELETE FROM` with sequence reset for SQLite.
463    ///
464    /// # Returns
465    ///
466    /// * `Ok(())` - Table truncated successfully
467    /// * `Err(sqlx::Error)` - Database error occurred
468    ///
469    /// # Example
470    ///
471    /// ```rust,ignore
472    /// db.model::<Log>().truncate().await?;
473    /// ```
474    pub async fn truncate(self) -> Result<(), sqlx::Error> {
475        let table_name = self.table_name.to_snake_case();
476        let query = match self.driver {
477            Drivers::Postgres | Drivers::MySQL => format!("TRUNCATE TABLE \"{}\"", table_name),
478            Drivers::SQLite => format!("DELETE FROM \"{}\"", table_name),
479        };
480
481        if self.debug_mode {
482            log::debug!("SQL: {}", query);
483        }
484
485        self.tx.execute(&query, AnyArguments::default()).await?;
486        
487        // For SQLite, reset auto-increment if exists
488        if matches!(self.driver, Drivers::SQLite) {
489            let _ = self.tx.execute(&format!("DELETE FROM sqlite_sequence WHERE name='{}'", table_name), AnyArguments::default()).await;
490        }
491
492        Ok(())
493    }
494
495    /// Combines the results of this query with another query using UNION.
496    ///
497    /// This method allows you to combine the result sets of two queries into a single
498    /// result set. Duplicate rows are removed by default.
499    ///
500    /// # Arguments
501    ///
502    /// * `other` - Another QueryBuilder instance to combine with.
503    ///
504    /// # Example
505    ///
506    /// ```rust,ignore
507    /// let q1 = db.model::<User>().filter("age", ">", 18);
508    /// let q2 = db.model::<User>().filter("status", "=", "premium");
509    /// let results = q1.union(q2).scan().await?;
510    /// ```
511    pub fn union(self, other: QueryBuilder<T, E>) -> Self where T: AnyImpl + 'static, E: 'static {
512        self.union_internal("UNION", other)
513    }
514
515    /// Combines the results of this query with another query using UNION ALL.
516    ///
517    /// This method allows you to combine the result sets of two queries into a single
518    /// result set, including all duplicates.
519    ///
520    /// # Arguments
521    ///
522    /// * `other` - Another QueryBuilder instance to combine with.
523    ///
524    /// # Example
525    ///
526    /// ```rust,ignore
527    /// let q1 = db.model::<User>().filter("age", ">", 18);
528    /// let q2 = db.model::<User>().filter("status", "=", "premium");
529    /// let results = q1.union_all(q2).scan().await?;
530    /// ```
531    pub fn union_all(self, other: QueryBuilder<T, E>) -> Self where T: AnyImpl + 'static, E: 'static {
532        self.union_internal("UNION ALL", other)
533    }
534
535    fn union_internal(mut self, op: &str, mut other: QueryBuilder<T, E>) -> Self where T: AnyImpl + 'static, E: 'static {
536        other.apply_soft_delete_filter();
537        let op_owned = op.to_string();
538        
539        self.union_clauses.push((op_owned.clone(), Box::new(move |query: &mut String, args: &mut AnyArguments<'_>, _driver: &Drivers, arg_counter: &mut usize| {
540            query.push_str(" ");
541            query.push_str(&op_owned);
542            query.push_str(" ");
543            other.write_select_sql::<T>(query, args, arg_counter);
544        })));
545        self
546    }
547
548    /// Internal helper to write the SELECT SQL to a string buffer.
549    pub(crate) fn write_select_sql<R: AnyImpl>(
550        &self,
551        query: &mut String,
552        args: &mut AnyArguments,
553        arg_counter: &mut usize,
554    ) {
555        query.push_str("SELECT ");
556
557        if self.is_distinct {
558            query.push_str("DISTINCT ");
559        }
560
561        query.push_str(&self.select_args_sql::<R>().join(", "));
562
563        // Build FROM clause
564        query.push_str(" FROM \"");
565        query.push_str(&self.table_name.to_snake_case());
566        query.push_str("\" ");
567        if let Some(alias) = &self.alias {
568            query.push_str(&format!("\"{}\" ", alias));
569        }
570
571        if !self.joins_clauses.is_empty() {
572            for join_clause in &self.joins_clauses {
573                query.push(' ');
574                join_clause(query, args, &self.driver, arg_counter);
575            }
576        }
577
578        query.push_str(" WHERE 1=1");
579
580        // Apply WHERE clauses
581        for clause in &self.where_clauses {
582            clause(query, args, &self.driver, arg_counter);
583        }
584
585        // Apply GROUP BY
586        if !self.group_by_clauses.is_empty() {
587            query.push_str(&format!(" GROUP BY {}", self.group_by_clauses.join(", ")));
588        }
589
590        // Apply HAVING
591        if !self.having_clauses.is_empty() {
592            query.push_str(" HAVING 1=1");
593            for clause in &self.having_clauses {
594                clause(query, args, &self.driver, arg_counter);
595            }
596        }
597
598        // Apply ORDER BY clauses
599        if !self.order_clauses.is_empty() {
600            query.push_str(&format!(" ORDER BY {}", self.order_clauses.join(", ")));
601        }
602
603        // Apply LIMIT clause
604        if let Some(limit) = self.limit {
605            query.push_str(" LIMIT ");
606            match self.driver {
607                Drivers::Postgres => {
608                    query.push_str(&format!("${}", arg_counter));
609                    *arg_counter += 1;
610                }
611                _ => query.push('?'),
612            }
613            let _ = args.add(limit as i64);
614        }
615
616        // Apply OFFSET clause
617        if let Some(offset) = self.offset {
618            query.push_str(" OFFSET ");
619            match self.driver {
620                Drivers::Postgres => {
621                    query.push_str(&format!("${}", arg_counter));
622                    *arg_counter += 1;
623                }
624                _ => query.push('?'),
625            }
626            let _ = args.add(offset as i64);
627        }
628
629        // Apply UNION clauses
630        for (_op, clause) in &self.union_clauses {
631            clause(query, args, &self.driver, arg_counter);
632        }
633    }
634
635    /// Adds a WHERE clause to the query.
636    ///
637    /// This method adds a filter condition to the query. Multiple filters can be chained
638    /// and will be combined with AND operators. The value is bound as a parameter to
639    /// prevent SQL injection.
640    ///
641    /// # Type Parameters
642    ///
643    /// * `V` - The type of the value to filter by. Must be encodable for SQL queries.
644    ///
645    /// # Arguments
646    ///
647    /// * `col` - The column name to filter on
648    /// * `op` - The comparison operator (e.g., "=", ">", "LIKE", "IN")
649    /// * `value` - The value to compare against
650    ///
651    /// # Example
652    ///
653    /// ```rust,ignore
654    /// query.filter("age", Op::Gte, 18)
655    /// // SQL: AND "age" >= 18
656    /// ```
657    pub fn filter<V>(self, col: &'static str, op: Op, value: V) -> Self
658    where
659        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
660    {
661        self.filter_internal(" AND ", col, op, value)
662    }
663
664    /// Adds an OR WHERE clause to the query.
665    ///
666    /// # Arguments
667    ///
668    /// * `col` - The column name to filter on
669    /// * `op` - The comparison operator
670    /// * `value` - The value to compare against
671    ///
672    /// # Example
673    ///
674    /// ```rust,ignore
675    /// query.filter("age", Op::Lt, 18).or_filter("active", Op::Eq, false)
676    /// // SQL: AND "age" < 18 OR "active" = false
677    /// ```
678    pub fn or_filter<V>(self, col: &'static str, op: Op, value: V) -> Self
679    where
680        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
681    {
682        self.filter_internal(" OR ", col, op, value)
683    }
684
685    /// Adds an AND NOT WHERE clause to the query.
686    ///
687    /// # Arguments
688    ///
689    /// * `col` - The column name to filter on
690    /// * `op` - The comparison operator
691    /// * `value` - The value to compare against
692    ///
693    /// # Example
694    ///
695    /// ```rust,ignore
696    /// query.not_filter("status", Op::Eq, "banned")
697    /// // SQL: AND NOT "status" = 'banned'
698    /// ```
699    pub fn not_filter<V>(self, col: &'static str, op: Op, value: V) -> Self
700    where
701        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
702    {
703        self.filter_internal(" AND NOT ", col, op, value)
704    }
705
706    /// Adds an OR NOT WHERE clause to the query.
707    ///
708    /// # Arguments
709    ///
710    /// * `col` - The column name to filter on
711    /// * `op` - The comparison operator
712    /// * `value` - The value to compare against
713    ///
714    /// # Example
715    ///
716    /// ```rust,ignore
717    /// query.filter("age", Op::Gt, 18).or_not_filter("status", Op::Eq, "inactive")
718    /// // SQL: AND "age" > 18 OR NOT "status" = 'inactive'
719    /// ```
720    pub fn or_not_filter<V>(self, col: &'static str, op: Op, value: V) -> Self
721    where
722        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
723    {
724        self.filter_internal(" OR NOT ", col, op, value)
725    }
726
727    /// Adds a BETWEEN clause to the query.
728    ///
729    /// # Arguments
730    ///
731    /// * `col` - The column name
732    /// * `start` - The start value of the range
733    /// * `end` - The end value of the range
734    ///
735    /// # Example
736    ///
737    /// ```rust,ignore
738    /// query.between("age", 18, 30)
739    /// // SQL: AND "age" BETWEEN 18 AND 30
740    /// ```
741    pub fn between<V>(mut self, col: &'static str, start: V, end: V) -> Self
742    where
743        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
744    {
745        let table_id = self.get_table_identifier();
746        let is_main_col = self.columns.contains(&col.to_snake_case());
747        let clause: FilterFn = Box::new(move |query, args, driver, arg_counter| {
748            query.push_str(" AND ");
749            if let Some((table, column)) = col.split_once(".") {
750                query.push_str(&format!("\"{}\".\"{}\"", table, column));
751            } else if is_main_col {
752                query.push_str(&format!("\"{}\".\"{}\"", table_id, col));
753            } else {
754                query.push_str(&format!("\"{}\"", col));
755            }
756            query.push_str(" BETWEEN ");
757
758            match driver {
759                Drivers::Postgres => {
760                    query.push_str(&format!("${} AND ${}", arg_counter, *arg_counter + 1));
761                    *arg_counter += 2;
762                }
763                _ => query.push_str("? AND ?"),
764            }
765
766            let _ = args.add(start.clone());
767            let _ = args.add(end.clone());
768        });
769        self.where_clauses.push(clause);
770        self
771    }
772
773    /// Adds an OR BETWEEN clause to the query.
774    ///
775    /// # Arguments
776    ///
777    /// * `col` - The column name
778    /// * `start` - The start value of the range
779    /// * `end` - The end value of the range
780    ///
781    /// # Example
782    ///
783    /// ```rust,ignore
784    /// query.between("age", 18, 30).or_between("salary", 5000, 10000)
785    /// // SQL: AND "age" BETWEEN 18 AND 30 OR "salary" BETWEEN 5000 AND 10000
786    /// ```
787    pub fn or_between<V>(mut self, col: &'static str, start: V, end: V) -> Self
788    where
789        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
790    {
791        let table_id = self.get_table_identifier();
792        let is_main_col = self.columns.contains(&col.to_snake_case());
793        let clause: FilterFn = Box::new(move |query, args, driver, arg_counter| {
794            query.push_str(" OR ");
795            if let Some((table, column)) = col.split_once(".") {
796                query.push_str(&format!("\"{}\".\"{}\"", table, column));
797            } else if is_main_col {
798                query.push_str(&format!("\"{}\".\"{}\"", table_id, col));
799            } else {
800                query.push_str(&format!("\"{}\"", col));
801            }
802            query.push_str(" BETWEEN ");
803
804            match driver {
805                Drivers::Postgres => {
806                    query.push_str(&format!("${} AND ${}", arg_counter, *arg_counter + 1));
807                    *arg_counter += 2;
808                }
809                _ => query.push_str("? AND ?"),
810            }
811
812            let _ = args.add(start.clone());
813            let _ = args.add(end.clone());
814        });
815        self.where_clauses.push(clause);
816        self
817    }
818
819    /// Adds an IN list clause to the query.
820    ///
821    /// # Arguments
822    ///
823    /// * `col` - The column name
824    /// * `values` - A vector of values
825    ///
826    /// # Example
827    ///
828    /// ```rust,ignore
829    /// query.in_list("status", vec!["active", "pending"])
830    /// // SQL: AND "status" IN ('active', 'pending')
831    /// ```
832    pub fn in_list<V>(mut self, col: &'static str, values: Vec<V>) -> Self
833    where
834        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
835    {
836        if values.is_empty() {
837            // WHERE 1=0 to ensure empty result
838            let clause: FilterFn = Box::new(|query, _, _, _| {
839                query.push_str(" AND 1=0");
840            });
841            self.where_clauses.push(clause);
842            return self;
843        }
844
845        let table_id = self.get_table_identifier();
846        let is_main_col = self.columns.contains(&col.to_snake_case());
847        let clause: FilterFn = Box::new(move |query, args, driver, arg_counter| {
848            query.push_str(" AND ");
849            if let Some((table, column)) = col.split_once(".") {
850                query.push_str(&format!("\"{}\".\"{}\"", table, column));
851            } else if is_main_col {
852                query.push_str(&format!("\"{}\".\"{}\"", table_id, col));
853            } else {
854                query.push_str(&format!("\"{}\"", col));
855            }
856            query.push_str(" IN (");
857
858            let mut placeholders = Vec::new();
859            for _ in &values {
860                match driver {
861                    Drivers::Postgres => {
862                        placeholders.push(format!("${}", arg_counter));
863                        *arg_counter += 1;
864                    }
865                    _ => placeholders.push("?".to_string()),
866                }
867            }
868            query.push_str(&placeholders.join(", "));
869            query.push(')');
870
871            for val in &values {
872                let _ = args.add(val.clone());
873            }
874        });
875        self.where_clauses.push(clause);
876        self
877    }
878
879    /// Adds an OR IN list clause to the query.
880    pub fn or_in_list<V>(mut self, col: &'static str, values: Vec<V>) -> Self
881    where
882        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
883    {
884        if values.is_empty() {
885            return self;
886        }
887
888        let table_id = self.get_table_identifier();
889        let is_main_col = self.columns.contains(&col.to_snake_case());
890        let clause: FilterFn = Box::new(move |query, args, driver, arg_counter| {
891            query.push_str(" OR ");
892            if let Some((table, column)) = col.split_once(".") {
893                query.push_str(&format!("\"{}\".\"{}\"", table, column));
894            } else if is_main_col {
895                query.push_str(&format!("\"{}\".\"{}\"", table_id, col));
896            } else {
897                query.push_str(&format!("\"{}\"", col));
898            }
899            query.push_str(" IN (");
900
901            let mut placeholders = Vec::new();
902            for _ in &values {
903                match driver {
904                    Drivers::Postgres => {
905                        placeholders.push(format!("${}", arg_counter));
906                        *arg_counter += 1;
907                    }
908                    _ => placeholders.push("?".to_string()),
909                }
910            }
911            query.push_str(&placeholders.join(", "));
912            query.push(')');
913
914            for val in &values {
915                let _ = args.add(val.clone());
916            }
917        });
918        self.where_clauses.push(clause);
919        self
920    }
921
922    /// Groups filters inside parentheses with an AND operator.
923    ///
924    /// This allows for constructing complex WHERE clauses with nested logic.
925    ///
926    /// # Arguments
927    ///
928    /// * `f` - A closure that receives a `QueryBuilder` and returns it with more filters
929    ///
930    /// # Example
931    ///
932    /// ```rust,ignore
933    /// db.model::<User>()
934    ///     .filter("active", Op::Eq, true)
935    ///     .group(|q| q.filter("age", Op::Gt, 18).or_filter("role", Op::Eq, "admin"))
936    ///     .scan()
937    ///     .await?;
938    /// // SQL: AND "active" = true AND (1=1 AND ("age" > 18 OR "role" = 'admin'))
939    /// ```
940    pub fn group<F>(mut self, f: F) -> Self
941    where
942        F: FnOnce(Self) -> Self,
943    {
944        let old_clauses = std::mem::take(&mut self.where_clauses);
945        self = f(self);
946        let group_clauses = std::mem::take(&mut self.where_clauses);
947        self.where_clauses = old_clauses;
948
949        if !group_clauses.is_empty() {
950            let clause: FilterFn = Box::new(move |query, args, driver, arg_counter| {
951                query.push_str(" AND (1=1");
952                for c in &group_clauses {
953                    c(query, args, driver, arg_counter);
954                }
955                query.push_str(")");
956            });
957            self.where_clauses.push(clause);
958        }
959        self
960    }
961
962    /// Groups filters inside parentheses with an OR operator.
963    ///
964    /// # Arguments
965    ///
966    /// * `f` - A closure that receives a `QueryBuilder` and returns it with more filters
967    ///
968    /// # Example
969    ///
970    /// ```rust,ignore
971    /// db.model::<User>()
972    ///     .filter("active", Op::Eq, true)
973    ///     .or_group(|q| q.filter("role", Op::Eq, "admin").filter("age", Op::Gt, 18))
974    ///     .scan()
975    ///     .await?;
976    /// // SQL: AND "active" = true OR (1=1 AND ("role" = 'admin' AND "age" > 18))
977    /// ```
978    pub fn or_group<F>(mut self, f: F) -> Self
979    where
980        F: FnOnce(Self) -> Self,
981    {
982        let old_clauses = std::mem::take(&mut self.where_clauses);
983        self = f(self);
984        let group_clauses = std::mem::take(&mut self.where_clauses);
985        self.where_clauses = old_clauses;
986
987        if !group_clauses.is_empty() {
988            let clause: FilterFn = Box::new(move |query, args, driver, arg_counter| {
989                query.push_str(" OR (1=1");
990                for c in &group_clauses {
991                    c(query, args, driver, arg_counter);
992                }
993                query.push_str(")");
994            });
995            self.where_clauses.push(clause);
996        }
997        self
998    }
999
1000    /// Adds a raw WHERE clause with a placeholder and a single value.
1001    ///
1002    /// This allows writing raw SQL conditions with a `?` placeholder.
1003    /// To use multiple placeholders with different types, chain multiple `where_raw` calls.
1004    ///
1005    /// # Arguments
1006    ///
1007    /// * `sql` - Raw SQL string with one `?` placeholder (e.g., "age > ?")
1008    /// * `value` - Value to bind
1009    ///
1010    /// # Example
1011    ///
1012    /// ```rust,ignore
1013    /// db.model::<User>()
1014    ///     .where_raw("name = ?", "Alice".to_string())
1015    ///     .where_raw("age >= ?", 18)
1016    ///     .scan()
1017    ///     .await?;
1018    /// // SQL: AND name = 'Alice' AND age >= 18
1019    /// ```
1020    pub fn where_raw<V>(mut self, sql: &str, value: V) -> Self
1021    where
1022        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
1023    {
1024        self.where_clauses.push(self.create_raw_clause(" AND ", sql, value));
1025        self
1026    }
1027
1028    /// Adds a raw OR WHERE clause with a placeholder.
1029    pub fn or_where_raw<V>(mut self, sql: &str, value: V) -> Self
1030    where
1031        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
1032    {
1033        self.where_clauses.push(self.create_raw_clause(" OR ", sql, value));
1034        self
1035    }
1036
1037    /// Internal helper to create a raw SQL clause with a single value.
1038    fn create_raw_clause<V>(&self, joiner: &'static str, sql: &str, value: V) -> FilterFn
1039    where
1040        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
1041    {
1042        let sql_owned = sql.to_string();
1043        Box::new(move |query, args, driver, arg_counter| {
1044            query.push_str(joiner);
1045            
1046            let mut processed_sql = sql_owned.clone();
1047            
1048            // If no placeholder is found, try to be helpful
1049            if !processed_sql.contains('?') {
1050                let trimmed = processed_sql.trim();
1051                if trimmed.ends_with('=') || trimmed.ends_with('>') || trimmed.ends_with('<') || trimmed.to_uppercase().ends_with(" LIKE") {
1052                    processed_sql.push_str(" ?");
1053                } else if !trimmed.contains(' ') && !trimmed.contains('(') {
1054                    // It looks like just a column name
1055                    processed_sql.push_str(" = ?");
1056                }
1057            }
1058
1059            // Replace '?' with driver-specific placeholders only if needed
1060            if matches!(driver, Drivers::Postgres) {
1061                while let Some(pos) = processed_sql.find('?') {
1062                    let placeholder = format!("${}", arg_counter);
1063                    *arg_counter += 1;
1064                    processed_sql.replace_range(pos..pos + 1, &placeholder);
1065                }
1066            }
1067            
1068            query.push_str(&processed_sql);
1069            let _ = args.add(value.clone());
1070        })
1071    }
1072
1073    /// Adds an equality filter to the query.
1074    ///
1075    /// This is a convenience wrapper around `filter()` for simple equality checks.
1076    /// It is equivalent to calling `filter(col, "=", value)`.
1077    ///
1078    /// # Type Parameters
1079    ///
1080    /// * `V` - The type of the value to compare against.
1081    ///
1082    /// # Arguments
1083    ///
1084    /// * `col` - The column name to filter on.
1085    /// * `value` - The value to match.
1086    ///
1087    /// # Example
1088    ///
1089    /// ```rust,ignore
1090    /// // Equivalent to filter("age", Op::Eq, 18)
1091    /// query.equals("age", 18)
1092    /// ```
1093    pub fn equals<V>(self, col: &'static str, value: V) -> Self
1094    where
1095        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
1096    {
1097        self.filter(col, Op::Eq, value)
1098    }
1099
1100    /// Adds an ORDER BY clause to the query.
1101    ///
1102    /// Specifies the sort order for the query results. Multiple order clauses
1103    /// can be added and will be applied in the order they were added.
1104    ///
1105    /// # Arguments
1106    ///
1107    /// * `order` - The ORDER BY expression (e.g., "created_at DESC", "age ASC, name DESC")
1108    ///
1109    /// # Example
1110    ///
1111    /// ```rust,ignore
1112    /// // Single column ascending (ASC is default)
1113    /// query.order("age")
1114    ///
1115    /// // Single column descending
1116    /// query.order("created_at DESC")
1117    ///
1118    /// // Multiple columns
1119    /// query.order("age DESC, username ASC")
1120    ///
1121    /// // Chain multiple order clauses
1122    /// query
1123    ///     .order("priority DESC")
1124    ///     .order("created_at ASC")
1125    /// ```
1126    pub fn order(mut self, order: &str) -> Self {
1127        self.order_clauses.push(order.to_string());
1128        self
1129    }
1130
1131    /// Defines a SQL alias for the primary table in the query.
1132    ///
1133    /// This method allows you to set a short alias for the model's underlying table.
1134    /// It is highly recommended when writing complex queries with multiple `JOIN` clauses,
1135    /// preventing the need to repeat the full table name in `.filter()`, `.equals()`, or `.select()`.
1136    ///
1137    /// # Arguments
1138    ///
1139    /// * `alias` - A string slice representing the alias to be used (e.g., "u", "rp").
1140    ///
1141    /// # Example
1142    ///
1143    /// ```rust,ignore
1144    /// // Using 'u' as an alias for the User table
1145    /// let results = db.model::<User>()
1146    ///     .alias("u")
1147    ///     .join("role_permissions rp", "rp.role_id = u.role")
1148    ///     .equals("u.id", user_id)
1149    ///     .select("u.username, rp.permission_id")
1150    ///     .scan_as::<UserPermissionDTO>()
1151    ///     .await?;
1152    /// ```
1153    pub fn alias(mut self, alias: &str) -> Self {
1154        self.alias = Some(alias.to_string());
1155        self
1156    }
1157
1158    /// Placeholder for eager loading relationships (preload).
1159    ///
1160    /// This method is reserved for future implementation of relationship preloading.
1161    /// Currently, it returns `self` unchanged to maintain the fluent interface.
1162    ///
1163    /// # Future Implementation
1164    ///
1165    /// Will support eager loading of related models to avoid N+1 query problems:
1166    ///
1167    /// ```rust,ignore
1168    /// // Future usage example
1169    /// query.preload("posts").preload("comments")
1170    /// ```
1171    // pub fn preload(self) -> Self {
1172    //     // TODO: Implement relationship preloading
1173    //     self
1174    // }
1175
1176    /// Activates debug mode for this query.
1177    ///
1178    /// When enabled, the generated SQL query will be logged using the `log` crate
1179    /// at the `DEBUG` level before execution.
1180    ///
1181    /// # Note
1182    ///
1183    /// To see the output, you must initialize a logger in your application (e.g., using `env_logger`)
1184    /// and configure it to display `debug` logs for `bottle_orm`.
1185    ///
1186    /// # Example
1187    ///
1188    /// ```rust,ignore
1189    /// db.model::<User>()
1190    ///     .filter("active", "=", true)
1191    ///     .debug() // Logs SQL: SELECT * FROM "user" WHERE "active" = $1
1192    ///     .scan()
1193    ///     .await?;
1194    /// ```
1195    pub fn debug(mut self) -> Self {
1196        self.debug_mode = true;
1197        self
1198    }
1199
1200    /// Adds an IS NULL filter for the specified column.
1201    ///
1202    /// # Arguments
1203    ///
1204    /// * `col` - The column name to check for NULL
1205    ///
1206    /// # Example
1207    ///
1208    /// ```rust,ignore
1209    /// db.model::<User>()
1210    ///     .is_null("deleted_at")
1211    ///     .scan()
1212    ///     .await?;
1213    /// // SQL: SELECT * FROM "user" WHERE "deleted_at" IS NULL
1214    /// ```
1215    pub fn is_null(mut self, col: &str) -> Self {
1216        let col_owned = col.to_string();
1217        let table_id = self.get_table_identifier();
1218        let is_main_col = self.columns.contains(&col_owned.to_snake_case());
1219        let clause: FilterFn = Box::new(move |query, _args, _driver, _arg_counter| {
1220            query.push_str(" AND ");
1221            if let Some((table, column)) = col_owned.split_once(".") {
1222                query.push_str(&format!("\"{}\".\"{}\"", table, column));
1223            } else if is_main_col {
1224                query.push_str(&format!("\"{}\".\"{}\"", table_id, col_owned));
1225            } else {
1226                query.push_str(&format!("\"{}\"", col_owned));
1227            }
1228            query.push_str(" IS NULL");
1229        });
1230        self.where_clauses.push(clause);
1231        self
1232    }
1233
1234    /// Adds an IS NOT NULL filter for the specified column.
1235    ///
1236    /// # Arguments
1237    ///
1238    /// * `col` - The column name to check for NOT NULL
1239    ///
1240    /// # Example
1241    ///
1242    /// ```rust,ignore
1243    /// db.model::<User>()
1244    ///     .is_not_null("email")
1245    ///     .scan()
1246    ///     .await?;
1247    /// // SQL: SELECT * FROM "user" WHERE "email" IS NOT NULL
1248    /// ```
1249    pub fn is_not_null(mut self, col: &str) -> Self {
1250        let col_owned = col.to_string();
1251        let table_id = self.get_table_identifier();
1252        let is_main_col = self.columns.contains(&col_owned.to_snake_case());
1253        let clause: FilterFn = Box::new(move |query, _args, _driver, _arg_counter| {
1254            query.push_str(" AND ");
1255            if let Some((table, column)) = col_owned.split_once(".") {
1256                query.push_str(&format!("\"{}\".\"{}\"", table, column));
1257            } else if is_main_col {
1258                query.push_str(&format!("\"{}\".\"{}\"", table_id, col_owned));
1259            } else {
1260                query.push_str(&format!("\"{}\"", col_owned));
1261            }
1262            query.push_str(" IS NOT NULL");
1263        });
1264        self.where_clauses.push(clause);
1265        self
1266    }
1267
1268    /// Includes soft-deleted records in query results.
1269    ///
1270    /// By default, queries on models with a `#[orm(soft_delete)]` column exclude
1271    /// records where that column is not NULL. This method disables that filter.
1272    ///
1273    /// # Example
1274    ///
1275    /// ```rust,ignore
1276    /// // Get all users including deleted ones
1277    /// db.model::<User>()
1278    ///     .with_deleted()
1279    ///     .scan()
1280    ///     .await?;
1281    /// ```
1282    pub fn with_deleted(mut self) -> Self {
1283        self.with_deleted = true;
1284        self
1285    }
1286
1287    /// Adds an INNER JOIN clause to the query.
1288    ///
1289    /// # Arguments
1290    ///
1291    /// * `table` - The name of the table to join (with optional alias)
1292    /// * `on` - The join condition (e.g., "users.id = posts.user_id")
1293    ///
1294    /// # Example
1295    ///
1296    /// ```rust,ignore
1297    /// db.model::<User>()
1298    ///     .join("posts p", "u.id = p.user_id")
1299    ///     .scan()
1300    ///     .await?;
1301    /// // SQL: INNER JOIN "posts" p ON u.id = p.user_id
1302    /// ```
1303    pub fn join(self, table: &str, s_query: &str) -> Self {
1304        self.join_generic("", table, s_query)
1305    }
1306
1307    /// Internal helper for specific join types
1308    fn join_generic(mut self, join_type: &str, table: &str, s_query: &str) -> Self {
1309        let table_owned = table.to_string();
1310        let join_type_owned = join_type.to_string();
1311        
1312        let trimmed_value = s_query.replace(" ", "");
1313        let values = trimmed_value.split_once("=");
1314        let mut parsed_query = s_query.to_string();
1315        
1316        if let Some((first, second)) = values {
1317            // Try to parse table.column = table.column
1318            if let Some((t1, c1)) = first.split_once('.') {
1319                if let Some((t2, c2)) = second.split_once('.') {
1320                    parsed_query = format!("\"{}\".\"{}\" = \"{}\".\"{}\"", t1, c1, t2, c2);
1321                }
1322            }
1323        }
1324
1325        if let Some((table_name, alias)) = table.split_once(" ") {
1326            self.join_aliases.insert(table_name.to_snake_case(), alias.to_string());
1327        } else {
1328            self.join_aliases.insert(table.to_snake_case(), table.to_string());
1329        }
1330
1331        self.joins_clauses.push(Box::new(move |query, _args, _driver, _arg_counter| {
1332            if let Some((table_name, alias)) = table_owned.split_once(" ") {
1333                query.push_str(&format!("{} JOIN \"{}\" \"{}\" ON {}", join_type_owned, table_name, alias, parsed_query));
1334            } else {
1335                query.push_str(&format!("{} JOIN \"{}\" ON {}", join_type_owned, table_owned, parsed_query));
1336            }
1337        }));
1338        self
1339    }
1340
1341    /// Adds a JOIN clause with a placeholder and a bound value.
1342    ///
1343    /// # Arguments
1344    ///
1345    /// * `table` - The name of the table to join
1346    /// * `on` - The join condition with a `?` placeholder
1347    /// * `value` - The value to bind
1348    ///
1349    /// # Example
1350    ///
1351    /// ```rust,ignore
1352    /// db.model::<User>()
1353    ///     .join_raw("posts p", "p.user_id = u.id AND p.status = ?", "published")
1354    ///     .scan()
1355    ///     .await?;
1356    /// // SQL: JOIN "posts" p ON p.user_id = u.id AND p.status = 'published'
1357    /// ```
1358    pub fn join_raw<V>(self, table: &str, on: &str, value: V) -> Self
1359    where
1360        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
1361    {
1362        self.join_generic_raw("", table, on, value)
1363    }
1364
1365    /// Adds a raw LEFT JOIN clause with a placeholder and a bound value.
1366    ///
1367    /// # Example
1368    ///
1369    /// ```rust,ignore
1370    /// query.left_join_raw("posts", "posts.user_id = ?", user_id)
1371    /// ```
1372    pub fn left_join_raw<V>(self, table: &str, on: &str, value: V) -> Self
1373    where
1374        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
1375    {
1376        self.join_generic_raw("LEFT", table, on, value)
1377    }
1378
1379    /// Adds a raw RIGHT JOIN clause with a placeholder and a bound value.
1380    ///
1381    /// # Example
1382    ///
1383    /// ```rust,ignore
1384    /// query.right_join_raw("users", "users.id = ?", user_id)
1385    /// ```
1386    pub fn right_join_raw<V>(self, table: &str, on: &str, value: V) -> Self
1387    where
1388        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
1389    {
1390        self.join_generic_raw("RIGHT", table, on, value)
1391    }
1392
1393    /// Adds a raw INNER JOIN clause with a placeholder and a bound value.
1394    ///
1395    /// # Example
1396    ///
1397    /// ```rust,ignore
1398    /// query.inner_join_raw("accounts", "accounts.user_id = ?", user_id)
1399    /// ```
1400    pub fn inner_join_raw<V>(self, table: &str, on: &str, value: V) -> Self
1401    where
1402        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
1403    {
1404        self.join_generic_raw("INNER", table, on, value)
1405    }
1406
1407    /// Adds a raw FULL JOIN clause with a placeholder and a bound value.
1408    ///
1409    /// # Example
1410    ///
1411    /// ```rust,ignore
1412    /// query.full_join_raw("profiles", "profiles.user_id = ?", user_id)
1413    /// ```
1414    pub fn full_join_raw<V>(self, table: &str, on: &str, value: V) -> Self
1415    where
1416        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
1417    {
1418        self.join_generic_raw("FULL", table, on, value)
1419    }
1420
1421    /// Internal helper for raw join types
1422    fn join_generic_raw<V>(mut self, join_type: &str, table: &str, on: &str, value: V) -> Self
1423    where
1424        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
1425    {
1426        let table_owned = table.to_string();
1427        let on_owned = on.to_string();
1428        let join_type_owned = join_type.to_string();
1429        
1430        if let Some((table_name, alias)) = table.split_once(" ") {
1431            self.join_aliases.insert(table_name.to_snake_case(), alias.to_string());
1432        } else {
1433            self.join_aliases.insert(table.to_snake_case(), table.to_string());
1434        }
1435
1436        self.joins_clauses.push(Box::new(move |query, args, driver, arg_counter| {
1437            if let Some((table_name, alias)) = table_owned.split_once(" ") {
1438                query.push_str(&format!("{} JOIN \"{}\" {} ON ", join_type_owned, table_name, alias));
1439            } else {
1440                query.push_str(&format!("{} JOIN \"{}\" ON ", join_type_owned, table_owned));
1441            }
1442
1443            let mut processed_on = on_owned.clone();
1444            if let Some(pos) = processed_on.find('?') {
1445                let placeholder = match driver {
1446                    Drivers::Postgres => {
1447                        let p = format!("${}", arg_counter);
1448                        *arg_counter += 1;
1449                        p
1450                    }
1451                    _ => "?".to_string(),
1452                };
1453                processed_on.replace_range(pos..pos + 1, &placeholder);
1454            }
1455            
1456            query.push_str(&processed_on);
1457            let _ = args.add(value.clone());
1458        }));
1459        self
1460    }
1461
1462    /// Adds a LEFT JOIN clause.
1463    ///
1464    /// # Arguments
1465    ///
1466    /// * `table` - The name of the table to join with
1467    /// * `on` - The join condition (e.g., "users.id = posts.user_id")
1468    ///
1469    /// # Example
1470    ///
1471    /// ```rust,ignore
1472    /// // Get all users and their posts (if any)
1473    /// let users_with_posts = db.model::<User>()
1474    ///     .left_join("posts p", "u.id = p.user_id")
1475    ///     .scan()
1476    ///     .await?;
1477    /// // SQL: LEFT JOIN "posts" p ON u.id = p.user_id
1478    /// ```
1479    pub fn left_join(self, table: &str, on: &str) -> Self {
1480        self.join_generic("LEFT", table, on)
1481    }
1482
1483    /// Adds a RIGHT JOIN clause.
1484    ///
1485    /// # Arguments
1486    ///
1487    /// * `table` - The name of the table to join with
1488    /// * `on` - The join condition
1489    ///
1490    /// # Example
1491    ///
1492    /// ```rust,ignore
1493    /// db.model::<Post>()
1494    ///     .right_join("users u", "p.user_id = u.id")
1495    ///     .scan()
1496    ///     .await?;
1497    /// // SQL: RIGHT JOIN "users" u ON p.user_id = u.id
1498    /// ```
1499    pub fn right_join(self, table: &str, on: &str) -> Self {
1500        self.join_generic("RIGHT", table, on)
1501    }
1502
1503    /// Adds an INNER JOIN clause.
1504    ///
1505    /// # Arguments
1506    ///
1507    /// * `table` - The name of the table to join with
1508    /// * `on` - The join condition
1509    ///
1510    /// # Example
1511    ///
1512    /// ```rust,ignore
1513    /// // Get only users who have posts
1514    /// let active_users = db.model::<User>()
1515    ///     .inner_join("posts p", "u.id = p.user_id")
1516    ///     .scan()
1517    ///     .await?;
1518    /// // SQL: INNER JOIN "posts" p ON u.id = p.user_id
1519    /// ```
1520    pub fn inner_join(self, table: &str, on: &str) -> Self {
1521        self.join_generic("INNER", table, on)
1522    }
1523
1524    /// Adds a FULL JOIN clause.
1525    ///
1526    /// # Arguments
1527    ///
1528    /// * `table` - The name of the table to join with
1529    /// * `on` - The join condition
1530    ///
1531    /// # Example
1532    ///
1533    /// ```rust,ignore
1534    /// query.full_join("profiles pr", "u.id = pr.user_id")
1535    /// // SQL: FULL JOIN "profiles" pr ON u.id = pr.user_id
1536    /// ```
1537    pub fn full_join(self, table: &str, on: &str) -> Self {
1538        self.join_generic("FULL", table, on)
1539    }
1540
1541    /// Marks the query to return DISTINCT results.
1542    ///
1543    /// Adds the `DISTINCT` keyword to the SELECT statement, ensuring that unique
1544    /// rows are returned.
1545    ///
1546    /// # Example
1547    ///
1548    /// ```rust,ignore
1549    /// // Get unique ages of users
1550    /// let unique_ages: Vec<i32> = db.model::<User>()
1551    ///     .select("age")
1552    ///     .distinct()
1553    ///     .scan()
1554    ///     .await?;
1555    /// ```
1556    pub fn distinct(mut self) -> Self {
1557        self.is_distinct = true;
1558        self
1559    }
1560
1561    /// Adds a GROUP BY clause to the query.
1562    ///
1563    /// Groups rows that have the same values into summary rows. Often used with
1564    /// aggregate functions (COUNT, MAX, MIN, SUM, AVG).
1565    ///
1566    /// # Arguments
1567    ///
1568    /// * `columns` - Comma-separated list of columns to group by
1569    ///
1570    /// # Example
1571    ///
1572    /// ```rust,ignore
1573    /// // Count users by age group
1574    /// let stats: Vec<(i32, i64)> = db.model::<User>()
1575    ///     .select("age, COUNT(*)")
1576    ///     .group_by("age")
1577    ///     .scan()
1578    ///     .await?;
1579    /// ```
1580    pub fn group_by(mut self, columns: &str) -> Self {
1581        self.group_by_clauses.push(columns.to_string());
1582        self
1583    }
1584
1585    /// Adds a HAVING clause to the query.
1586    ///
1587    /// Used to filter groups created by `group_by`. Similar to `filter` (WHERE),
1588    /// but operates on grouped records and aggregate functions.
1589    ///
1590    /// # Arguments
1591    ///
1592    /// * `col` - The column or aggregate function to filter on
1593    /// * `op` - Comparison operator
1594    /// * `value` - Value to compare against
1595    ///
1596    /// # Example
1597    ///
1598    /// ```rust,ignore
1599    /// // Get ages with more than 5 users
1600    /// let popular_ages = db.model::<User>()
1601    ///     .select("age, COUNT(*)")
1602    ///     .group_by("age")
1603    ///     .having("COUNT(*)", Op::Gt, 5)
1604    ///     .scan()
1605    ///     .await?;
1606    /// ```
1607    pub fn having<V>(mut self, col: &'static str, op: Op, value: V) -> Self
1608    where
1609        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
1610    {
1611        let op_str = op.as_sql();
1612        let clause: FilterFn = Box::new(move |query, args, driver, arg_counter| {
1613            query.push_str(" AND ");
1614            query.push_str(col);
1615            query.push(' ');
1616            query.push_str(op_str);
1617            query.push(' ');
1618
1619            match driver {
1620                Drivers::Postgres => {
1621                    query.push_str(&format!("${}", arg_counter));
1622                    *arg_counter += 1;
1623                }
1624                _ => query.push('?'),
1625            }
1626            let _ = args.add(value.clone());
1627        });
1628
1629        self.having_clauses.push(clause);
1630        self
1631    }
1632
1633    /// Returns the COUNT of rows matching the query.
1634    ///
1635    /// A convenience method that automatically sets `SELECT COUNT(*)` and returns
1636    /// the result as an `i64`.
1637    ///
1638    /// # Returns
1639    ///
1640    /// * `Ok(i64)` - The count of rows
1641    /// * `Err(sqlx::Error)` - Database error
1642    ///
1643    /// # Example
1644    ///
1645    /// ```rust,ignore
1646    /// let user_count = db.model::<User>().count().await?;
1647    /// ```
1648    pub async fn count(mut self) -> Result<i64, sqlx::Error> {
1649        self.select_columns = vec!["COUNT(*)".to_string()];
1650        self.scalar::<i64>().await
1651    }
1652
1653    /// Returns the SUM of the specified column.
1654    ///
1655    /// Calculates the sum of a numeric column.
1656    ///
1657    /// # Arguments
1658    ///
1659    /// * `column` - The column to sum
1660    ///
1661    /// # Example
1662    ///
1663    /// ```rust,ignore
1664    /// let total_age: i64 = db.model::<User>().sum("age").await?;
1665    /// ```
1666    pub async fn sum<N>(mut self, column: &str) -> Result<N, sqlx::Error>
1667    where
1668        N: FromAnyRow + AnyImpl + for<'r> Decode<'r, Any> + Type<Any> + Send + Unpin,
1669    {
1670        let quoted_col = if column.contains('.') {
1671            let parts: Vec<&str> = column.split('.').collect();
1672            format!("\"{}\".\"{}\"", parts[0].trim_matches('"'), parts[1].trim_matches('"'))
1673        } else {
1674            format!("\"{}\"", column.trim_matches('"'))
1675        };
1676        self.select_columns = vec![format!("SUM({})", quoted_col)];
1677        self.scalar::<N>().await
1678    }
1679
1680    /// Returns the AVG of the specified column.
1681    ///
1682    /// Calculates the average value of a numeric column.
1683    ///
1684    /// # Arguments
1685    ///
1686    /// * `column` - The column to average
1687    ///
1688    /// # Example
1689    ///
1690    /// ```rust,ignore
1691    /// let avg_age: f64 = db.model::<User>().avg("age").await?;
1692    /// ```
1693    pub async fn avg<N>(mut self, column: &str) -> Result<N, sqlx::Error>
1694    where
1695        N: FromAnyRow + AnyImpl + for<'r> Decode<'r, Any> + Type<Any> + Send + Unpin,
1696    {
1697        let quoted_col = if column.contains('.') {
1698            let parts: Vec<&str> = column.split('.').collect();
1699            format!("\"{}\".\"{}\"", parts[0].trim_matches('"'), parts[1].trim_matches('"'))
1700        } else {
1701            format!("\"{}\"", column.trim_matches('"'))
1702        };
1703        self.select_columns = vec![format!("AVG({})", quoted_col)];
1704        self.scalar::<N>().await
1705    }
1706
1707    /// Returns the MIN of the specified column.
1708    ///
1709    /// Finds the minimum value in a column.
1710    ///
1711    /// # Arguments
1712    ///
1713    /// * `column` - The column to check
1714    ///
1715    /// # Example
1716    ///
1717    /// ```rust,ignore
1718    /// let min_age: i32 = db.model::<User>().min("age").await?;
1719    /// ```
1720    pub async fn min<N>(mut self, column: &str) -> Result<N, sqlx::Error>
1721    where
1722        N: FromAnyRow + AnyImpl + for<'r> Decode<'r, Any> + Type<Any> + Send + Unpin,
1723    {
1724        let quoted_col = if column.contains('.') {
1725            let parts: Vec<&str> = column.split('.').collect();
1726            format!("\"{}\".\"{}\"", parts[0].trim_matches('"'), parts[1].trim_matches('"'))
1727        } else {
1728            format!("\"{}\"", column.trim_matches('"'))
1729        };
1730        self.select_columns = vec![format!("MIN({})", quoted_col)];
1731        self.scalar::<N>().await
1732    }
1733
1734    /// Returns the MAX of the specified column.
1735    ///
1736    /// Finds the maximum value in a column.
1737    ///
1738    /// # Arguments
1739    ///
1740    /// * `column` - The column to check
1741    ///
1742    /// # Example
1743    ///
1744    /// ```rust,ignore
1745    /// let max_age: i32 = db.model::<User>().max("age").await?;
1746    /// ```
1747    pub async fn max<N>(mut self, column: &str) -> Result<N, sqlx::Error>
1748    where
1749        N: FromAnyRow + AnyImpl + for<'r> Decode<'r, Any> + Type<Any> + Send + Unpin,
1750    {
1751        let quoted_col = if column.contains('.') {
1752            let parts: Vec<&str> = column.split('.').collect();
1753            format!("\"{}\".\"{}\"", parts[0].trim_matches('"'), parts[1].trim_matches('"'))
1754        } else {
1755            format!("\"{}\"", column.trim_matches('"'))
1756        };
1757        self.select_columns = vec![format!("MAX({})", quoted_col)];
1758        self.scalar::<N>().await
1759    }
1760
1761    /// Applies pagination with validation and limits.
1762    ///
1763    /// This is a convenience method that combines `limit()` and `offset()` with
1764    /// built-in validation and maximum value enforcement for safer pagination.
1765    ///
1766    /// # Arguments
1767    ///
1768    /// * `max_value` - Maximum allowed items per page
1769    /// * `default` - Default value if `value` exceeds `max_value`
1770    /// * `page` - Zero-based page number
1771    /// * `value` - Requested items per page
1772    ///
1773    /// # Returns
1774    ///
1775    /// * `Ok(Self)` - The updated QueryBuilder with pagination applied
1776    /// * `Err(Error)` - If `value` is negative
1777    ///
1778    /// # Pagination Logic
1779    ///
1780    /// 1. Validates that `value` is non-negative
1781    /// 2. If `value` > `max_value`, uses `default` instead
1782    /// 3. Calculates offset as: `value * page`
1783    /// 4. Sets limit to `value`
1784    ///
1785    /// # Example
1786    ///
1787    /// ```rust,ignore
1788    /// // Page 0 with 10 items (page 1 in 1-indexed systems)
1789    /// query.pagination(100, 20, 0, 10)?  // LIMIT 10 OFFSET 0
1790    ///
1791    /// // Page 2 with 25 items (page 3 in 1-indexed systems)
1792    /// query.pagination(100, 20, 2, 25)?  // LIMIT 25 OFFSET 50
1793    ///
1794    /// // Request too many items, falls back to default
1795    /// query.pagination(100, 20, 0, 150)? // LIMIT 20 OFFSET 0 (150 > 100)
1796    ///
1797    /// // Error: negative value
1798    /// query.pagination(100, 20, 0, -10)? // Returns Error
1799    /// ```
1800    pub fn pagination(mut self, max_value: usize, default: usize, page: usize, value: isize) -> Result<Self, Error> {
1801        // Validate that value is non-negative
1802        if value < 0 {
1803            return Err(Error::InvalidArgument("value cannot be negative".into()));
1804        }
1805
1806        let mut f_value = value as usize;
1807
1808        // Enforce maximum value limit
1809        if f_value > max_value {
1810            f_value = default;
1811        }
1812
1813        // Apply offset and limit
1814        self = self.offset(f_value * page);
1815        self = self.limit(f_value);
1816
1817        Ok(self)
1818    }
1819
1820    /// Selects specific columns to return.
1821    ///
1822    /// By default, queries use `SELECT *` to return all columns. This method
1823    /// allows you to specify exactly which columns should be returned.
1824    ///
1825    /// **Note:** Columns are pushed exactly as provided, without automatic
1826    /// snake_case conversion, allowing for aliases and raw SQL fragments.
1827    ///
1828    /// # Arguments
1829    ///
1830    /// * `columns` - Comma-separated list of column names to select
1831    ///
1832    /// # Example
1833    ///
1834    /// ```rust,ignore
1835    /// // Select single column
1836    /// query.select("id")
1837    ///
1838    /// // Select multiple columns
1839    /// query.select("id, username, email")
1840    ///
1841    /// // Select with SQL functions and aliases (now supported)
1842    /// query.select("COUNT(*) as total_count")
1843    /// ```
1844    pub fn select(mut self, columns: &str) -> Self {
1845        self.select_columns.push(columns.to_string());
1846        self
1847    }
1848
1849    /// Excludes specific columns from the query results.
1850    ///
1851    /// This is the inverse of `select()`. Instead of specifying which columns to include,
1852    /// you specify which columns to exclude. All other columns will be returned.
1853    ///
1854    /// # Arguments
1855    ///
1856    /// * `columns` - Comma-separated list of column names to exclude
1857    ///
1858    /// # Priority
1859    ///
1860    /// If both `select()` and `omit()` are used, `select()` takes priority.
1861    ///
1862    /// # Example
1863    ///
1864    /// ```rust,ignore
1865    /// // Exclude password from results
1866    /// let user = db.model::<User>()
1867    ///     .omit("password")
1868    ///     .first()
1869    ///     .await?;
1870    ///
1871    /// // Exclude multiple fields
1872    /// let user = db.model::<User>()
1873    ///     .omit("password, secret_token")
1874    ///     .first()
1875    ///     .await?;
1876    ///
1877    /// // Using with generated field constants (autocomplete support)
1878    /// let user = db.model::<User>()
1879    ///     .omit(user_fields::PASSWORD)
1880    ///     .first()
1881    ///     .await?;
1882    /// ```
1883    pub fn omit(mut self, columns: &str) -> Self {
1884        for col in columns.split(',') {
1885            self.omit_columns.push(col.trim().to_snake_case());
1886        }
1887        self
1888    }
1889
1890    /// Sets the query offset (pagination).
1891    ///
1892    /// Specifies the number of rows to skip before starting to return rows.
1893    /// Commonly used in combination with `limit()` for pagination.
1894    ///
1895    /// # Arguments
1896    ///
1897    /// * `offset` - Number of rows to skip
1898    ///
1899    /// # Example
1900    ///
1901    /// ```rust,ignore
1902    /// // Skip first 20 rows
1903    /// query.offset(20)
1904    ///
1905    /// // Pagination: page 3 with 10 items per page
1906    /// query.limit(10).offset(20)  // Skip 2 pages = 20 items
1907    /// ```
1908    pub fn offset(mut self, offset: usize) -> Self {
1909        self.offset = Some(offset);
1910        self
1911    }
1912
1913    /// Sets the maximum number of records to return.
1914    ///
1915    /// Limits the number of rows returned by the query. Essential for pagination
1916    /// and preventing accidentally fetching large result sets.
1917    ///
1918    /// # Arguments
1919    ///
1920    /// * `limit` - Maximum number of rows to return
1921    ///
1922    /// # Example
1923    ///
1924    /// ```rust,ignore
1925    /// // Return at most 10 rows
1926    /// query.limit(10)
1927    ///
1928    /// // Pagination: 50 items per page
1929    /// query.limit(50).offset(page * 50)
1930    /// ```
1931    pub fn limit(mut self, limit: usize) -> Self {
1932        self.limit = Some(limit);
1933        self
1934    }
1935
1936    // ========================================================================
1937    // Insert Operation
1938    // ========================================================================
1939
1940    /// Inserts a new record into the database based on the model instance.
1941    ///
1942    /// This method serializes the model into a SQL INSERT statement with proper
1943    /// type handling for primitives, dates, UUIDs, and other supported types.
1944    ///
1945    /// # Type Binding Strategy
1946    ///
1947    /// The method uses string parsing as a temporary solution for type binding.
1948    /// Values are converted to strings via the model's `to_map()` method, then
1949    /// parsed back to their original types for proper SQL binding.
1950    ///
1951    /// # Supported Types for Insert
1952    ///
1953    /// - **Integers**: `i32`, `i64` (INTEGER, BIGINT)
1954    /// - **Boolean**: `bool` (BOOLEAN)
1955    /// - **Float**: `f64` (DOUBLE PRECISION)
1956    /// - **Text**: `String` (TEXT, VARCHAR)
1957    /// - **UUID**: `Uuid` (UUID) - All versions 1-7 supported
1958    /// - **DateTime**: `DateTime<Utc>` (TIMESTAMPTZ)
1959    /// - **NaiveDateTime**: (TIMESTAMP)
1960    /// - **NaiveDate**: (DATE)
1961    /// - **NaiveTime**: (TIME)
1962    ///
1963    /// # Arguments
1964    ///
1965    /// * `model` - Reference to the model instance to insert
1966    ///
1967    /// # Returns
1968    ///
1969    /// * `Ok(&Self)` - Reference to self for method chaining
1970    /// * `Err(sqlx::Error)` - Database error during insertion
1971    ///
1972    /// # Example
1973    ///
1974    /// ```rust,ignore
1975    /// 
1976    /// use chrono::Utc;
1977    ///
1978    /// let new_user = User {
1979    ///     id: Uuid::new_v4(),
1980    ///     username: "john_doe".to_string(),
1981    ///     email: "john@example.com".to_string(),
1982    ///     age: 25,
1983    ///     active: true,
1984    ///     created_at: Utc::now(),
1985    /// };
1986    ///
1987    /// db.model::<User>().insert(&new_user).await?;
1988    /// ```
1989    pub fn insert<'b>(&'b mut self, model: &'b T) -> BoxFuture<'b, Result<(), sqlx::Error>> {
1990        Box::pin(async move {
1991            // Serialize model to a HashMap of column_name -> string_value
1992            let data_map = Model::to_map(model);
1993
1994            // Early return if no data to insert
1995            if data_map.is_empty() {
1996                return Ok(());
1997            }
1998
1999            let table_name = self.table_name.to_snake_case();
2000            let columns_info = <T as Model>::columns();
2001
2002            let mut target_columns = Vec::new();
2003            let mut bindings: Vec<(Option<String>, &str)> = Vec::new();
2004
2005            // Build column list and collect values with their SQL types
2006            for (col_name, value) in data_map {
2007                // Strip the "r#" prefix if present (for Rust keywords used as field names)
2008                let col_name_clean = col_name.strip_prefix("r#").unwrap_or(&col_name).to_snake_case();
2009                target_columns.push(format!("\"{}\"", col_name_clean));
2010
2011                // Find the SQL type for this column
2012                let sql_type = columns_info.iter().find(|c| c.name == col_name).map(|c| c.sql_type).unwrap_or("TEXT");
2013
2014                bindings.push((value, sql_type));
2015            }
2016
2017            // Generate placeholders with proper type casting for PostgreSQL
2018            let placeholders: Vec<String> = bindings
2019                .iter()
2020                .enumerate()
2021                .map(|(i, (_, sql_type))| match self.driver {
2022                    Drivers::Postgres => {
2023                        let idx = i + 1;
2024                        // PostgreSQL requires explicit type casting for some types
2025                        if temporal::is_temporal_type(sql_type) {
2026                            // Use temporal module for type casting
2027                            format!("${}{}", idx, temporal::get_postgres_type_cast(sql_type))
2028                        } else {
2029                            match *sql_type {
2030                                "UUID" => format!("${}::UUID", idx),
2031                                "JSONB" | "jsonb" => format!("${}::JSONB", idx),
2032                                s if s.ends_with("[]") => format!("${}::{}", idx, s),
2033                                _ => format!("${}", idx),
2034                            }
2035                        }
2036                    }
2037                    // MySQL and SQLite use simple ? placeholders
2038                    _ => "?".to_string(),
2039                })
2040                .collect();
2041
2042            // Construct the INSERT query
2043            let query_str = format!(
2044                "INSERT INTO \"{}\" ({}) VALUES ({})",
2045                table_name,
2046                target_columns.join(", "),
2047                placeholders.join(", ")
2048            );
2049
2050            if self.debug_mode {
2051                log::debug!("SQL: {}", query_str);
2052            }
2053
2054            let mut args = AnyArguments::default();
2055
2056            // Bind values using the optimized value_binding module
2057            for (val_opt, sql_type) in bindings {
2058                if let Some(val_str) = val_opt {
2059                    if args.bind_value(&val_str, sql_type, &self.driver).is_err() {
2060                        let _ = args.add(val_str);
2061                    }
2062                } else {
2063                    let _ = args.add(None::<String>);
2064                }
2065            }
2066
2067            // Execute the INSERT query
2068            self.tx.execute(&query_str, args).await?;
2069            Ok(())
2070        })
2071    }
2072
2073    /// Inserts multiple records into the database in a single batch operation.
2074    ///
2075    /// This is significantly faster than performing individual inserts in a loop
2076    /// as it generates a single SQL statement with multiple VALUES groups.
2077    ///
2078    /// # Type Binding Strategy
2079    ///
2080    /// Similar to the single record `insert`, this method uses string parsing for
2081    /// type binding. It ensures that all columns defined in the model are included
2082    /// in the insert statement, providing NULL for any missing optional values.
2083    ///
2084    /// # Arguments
2085    ///
2086    /// * `models` - A slice of model instances to insert
2087    ///
2088    /// # Returns
2089    ///
2090    /// * `Ok(())` - Successfully inserted all records
2091    /// * `Err(sqlx::Error)` - Database error during insertion
2092    ///
2093    /// # Example
2094    ///
2095    /// ```rust,ignore
2096    /// let users = vec![
2097    ///     User { username: "alice".to_string(), ... },
2098    ///     User { username: "bob".to_string(), ... },
2099    /// ];
2100    ///
2101    /// db.model::<User>().batch_insert(&users).await?;
2102    /// ```
2103    pub fn batch_insert<'b>(&'b mut self, models: &'b [T]) -> BoxFuture<'b, Result<(), sqlx::Error>> {
2104        Box::pin(async move {
2105            if models.is_empty() {
2106                return Ok(());
2107            }
2108
2109            let table_name = self.table_name.to_snake_case();
2110            let columns_info = <T as Model>::columns();
2111
2112            // Collect all column names for the INSERT statement
2113            // We use all columns defined in the model to ensure consistency across the batch
2114            let target_columns: Vec<String> = columns_info
2115                .iter()
2116                .map(|c| {
2117                    let col_name_clean = c.name.strip_prefix("r#").unwrap_or(c.name).to_snake_case();
2118                    format!("\"{}\"", col_name_clean)
2119                })
2120                .collect();
2121
2122            let mut value_groups = Vec::new();
2123            let mut bind_index = 1;
2124
2125            // Generate placeholders for all models
2126            for _ in models {
2127                let mut placeholders = Vec::new();
2128                for col in &columns_info {
2129                    match self.driver {
2130                        Drivers::Postgres => {
2131                            let p = if temporal::is_temporal_type(col.sql_type) {
2132                                format!("${}{}", bind_index, temporal::get_postgres_type_cast(col.sql_type))
2133                            } else {
2134                                match col.sql_type {
2135                                    "UUID" => format!("${}::UUID", bind_index),
2136                                    "JSONB" | "jsonb" => format!("${}::JSONB", bind_index),
2137                                    _ => format!("${}", bind_index),
2138                                }
2139                            };
2140                            placeholders.push(p);
2141                            bind_index += 1;
2142                        }
2143                        _ => {
2144                            placeholders.push("?".to_string());
2145                        }
2146                    }
2147                }
2148                value_groups.push(format!("({})", placeholders.join(", ")));
2149            }
2150
2151            let query_str = format!(
2152                "INSERT INTO \"{}\" ({}) VALUES {}",
2153                table_name,
2154                target_columns.join(", "),
2155                value_groups.join(", ")
2156            );
2157
2158            if self.debug_mode {
2159                log::debug!("SQL Batch: {}", query_str);
2160            }
2161
2162            let mut args = AnyArguments::default();
2163
2164            for model in models {
2165                let data_map = Model::to_map(model);
2166                for col in &columns_info {
2167                    let val_opt = data_map.get(col.name);
2168                    let sql_type = col.sql_type;
2169
2170                    if let Some(Some(val_str)) = val_opt {
2171                        if args.bind_value(val_str, sql_type, &self.driver).is_err() {
2172                            let _ = args.add(val_str.clone());
2173                        }
2174                    } else {
2175                        // Bind NULL for missing or None values
2176                        let _ = args.add(None::<String>);
2177                    }
2178                }
2179            }
2180
2181            // Execute the batch INSERT query
2182            self.tx.execute(&query_str, args).await?;
2183            Ok(())
2184        })
2185    }
2186
2187    /// Inserts a record or updates it if a conflict occurs (UPSERT).
2188    ///
2189    /// This method provides a cross-database way to perform "Insert or Update" operations.
2190    /// It uses `ON CONFLICT` for PostgreSQL and SQLite, and `ON DUPLICATE KEY UPDATE` for MySQL.
2191    ///
2192    /// # Arguments
2193    ///
2194    /// * `model` - The model instance to insert or update
2195    /// * `conflict_columns` - Columns that trigger the conflict (e.g., primary key or unique columns)
2196    /// * `update_columns` - Columns to update when a conflict occurs
2197    ///
2198    /// # Returns
2199    ///
2200    /// * `Ok(u64)` - The number of rows affected
2201    /// * `Err(sqlx::Error)` - Database error
2202    ///
2203    /// # Example
2204    ///
2205    /// ```rust,ignore
2206    /// let user = User { id: 1, username: "alice".to_string(), age: 25 };
2207    ///
2208    /// // If id 1 exists, update username and age
2209    /// db.model::<User>().upsert(&user, &["id"], &["username", "age"]).await?;
2210    /// ```
2211    pub fn upsert<'b>(
2212        &'b mut self,
2213        model: &'b T,
2214        conflict_columns: &'b [&'b str],
2215        update_columns: &'b [&'b str],
2216    ) -> BoxFuture<'b, Result<u64, sqlx::Error>> {
2217        Box::pin(async move {
2218            let data_map = Model::to_map(model);
2219            if data_map.is_empty() {
2220                return Ok(0);
2221            }
2222
2223            let table_name = self.table_name.to_snake_case();
2224            let columns_info = <T as Model>::columns();
2225
2226            let mut target_columns = Vec::new();
2227            let mut bindings: Vec<(Option<String>, &str)> = Vec::new();
2228
2229            // Build INSERT part
2230            for (col_name, value) in &data_map {
2231                let col_name_clean = col_name.strip_prefix("r#").unwrap_or(col_name).to_snake_case();
2232                target_columns.push(format!("\"{}\"", col_name_clean));
2233
2234                let sql_type = columns_info.iter().find(|c| {
2235                    let c_clean = c.name.strip_prefix("r#").unwrap_or(c.name);
2236                    c_clean == *col_name || c_clean.to_snake_case() == col_name_clean
2237                }).map(|c| c.sql_type).unwrap_or("TEXT");
2238                bindings.push((value.clone(), sql_type));
2239            }
2240
2241            let mut arg_counter = 1;
2242            let mut placeholders = Vec::new();
2243            for (_, sql_type) in &bindings {
2244                match self.driver {
2245                    Drivers::Postgres => {
2246                        let p = if temporal::is_temporal_type(sql_type) {
2247                            format!("${}{}", arg_counter, temporal::get_postgres_type_cast(sql_type))
2248                        } else {
2249                            match *sql_type {
2250                                "UUID" => format!("${}::UUID", arg_counter),
2251                                "JSONB" | "jsonb" => format!("${}::JSONB", arg_counter),
2252                                _ => format!("${}", arg_counter),
2253                            }
2254                        };
2255                        placeholders.push(p);
2256                        arg_counter += 1;
2257                    }
2258                    _ => {
2259                        placeholders.push("?".to_string());
2260                    }
2261                }
2262            }
2263
2264            let mut query_str = format!(
2265                "INSERT INTO \"{}\" ({}) VALUES ({})",
2266                table_name,
2267                target_columns.join(", "),
2268                placeholders.join(", ")
2269            );
2270
2271            // Build Conflict/Update part
2272            match self.driver {
2273                Drivers::Postgres | Drivers::SQLite => {
2274                    let conflict_cols_str = conflict_columns
2275                        .iter()
2276                        .map(|c| format!("\"{}\"", c.to_snake_case()))
2277                        .collect::<Vec<_>>()
2278                        .join(", ");
2279                    
2280                    query_str.push_str(&format!(" ON CONFLICT ({}) DO UPDATE SET ", conflict_cols_str));
2281                    
2282                    let mut update_clauses = Vec::new();
2283                    let mut update_bindings = Vec::new();
2284
2285                    for col in update_columns {
2286                        let col_snake = col.to_snake_case();
2287                        if let Some((_key, val_opt)) = data_map.iter().find(|(k, _)| {
2288                            let k_clean = k.strip_prefix("r#").unwrap_or(*k);
2289                            k_clean == *col || k_clean.to_snake_case() == col_snake
2290                        }) {
2291                            let sql_type_opt = columns_info.iter().find(|c| {
2292                                let c_clean = c.name.strip_prefix("r#").unwrap_or(c.name);
2293                                c_clean == *col || c_clean.to_snake_case() == col_snake
2294                            }).map(|c| c.sql_type);
2295                            
2296                            let sql_type = match sql_type_opt {
2297                                Some(t) => t,
2298                                None => continue,
2299                            };
2300                            
2301                            let placeholder = match self.driver {
2302                                Drivers::Postgres => {
2303                                    let p = if temporal::is_temporal_type(sql_type) {
2304                                        format!("${}{}", arg_counter, temporal::get_postgres_type_cast(sql_type))
2305                                    } else {
2306                                        match sql_type {
2307                                            "UUID" => format!("${}::UUID", arg_counter),
2308                                            "JSONB" | "jsonb" => format!("${}::JSONB", arg_counter),
2309                                            _ => format!("${}", arg_counter),
2310                                        }
2311                                    };
2312                                    arg_counter += 1;
2313                                    p
2314                                }
2315                                _ => "?".to_string(),
2316                            };
2317                            update_clauses.push(format!("\"{}\" = {}", col_snake, placeholder));
2318                            update_bindings.push((val_opt.clone(), sql_type));
2319                        }
2320                    }
2321                    if update_clauses.is_empty() {
2322                        query_str.push_str(" NOTHING");
2323                    } else {
2324                        query_str.push_str(&update_clauses.join(", "));
2325                    }
2326                    bindings.extend(update_bindings);
2327                }
2328                Drivers::MySQL => {
2329                    query_str.push_str(" ON DUPLICATE KEY UPDATE ");
2330                    let mut update_clauses = Vec::new();
2331                    for col in update_columns {
2332                        let col_snake = col.to_snake_case();
2333                        update_clauses.push(format!("\"{}\" = VALUES(\"{}\")", col_snake, col_snake));
2334                    }
2335                    query_str.push_str(&update_clauses.join(", "));
2336                }
2337            }
2338
2339            if self.debug_mode {
2340                log::debug!("SQL Upsert: {}", query_str);
2341            }
2342
2343            let mut args = AnyArguments::default();
2344            for (val_opt, sql_type) in bindings {
2345                if let Some(val_str) = val_opt {
2346                    if args.bind_value(&val_str, sql_type, &self.driver).is_err() {
2347                        let _ = args.add(val_str);
2348                    }
2349                } else {
2350                    let _ = args.add(None::<String>);
2351                }
2352            }
2353
2354            let result = self.tx.execute(&query_str, args).await?;
2355            Ok(result.rows_affected())
2356        })
2357    }
2358
2359    // ========================================================================
2360    // Query Execution Methods
2361    // ========================================================================
2362
2363    /// Returns the generated SQL string for debugging purposes.
2364    ///
2365    /// This method constructs the SQL query string without executing it.
2366    /// Useful for debugging and logging query construction. Note that this
2367    /// shows placeholders (?, $1, etc.) rather than actual bound values.
2368    ///
2369    /// # Returns
2370    ///
2371    /// A `String` containing the SQL query that would be executed
2372    ///
2373    /// # Example
2374    ///
2375    /// ```rust,ignore
2376    /// let query = db.model::<User>()
2377    ///     .filter("age", ">=", 18)
2378    ///     .order("created_at DESC")
2379    ///     .limit(10);
2380    ///
2381    /// println!("SQL: {}", query.to_sql());
2382    /// // Output: SELECT * FROM "user" WHERE 1=1 AND "age" >= $1 ORDER BY created_at DESC
2383    /// ```
2384    pub fn to_sql(&self) -> String {
2385        let mut query = String::new();
2386        let mut args = AnyArguments::default();
2387        let mut arg_counter = 1;
2388
2389        self.write_select_sql::<T>(&mut query, &mut args, &mut arg_counter);
2390        query
2391    }
2392
2393    /// Generates the list of column selection SQL arguments.
2394    ///
2395    /// This helper function constructs the column list for the SELECT statement.
2396    /// It handles:
2397    /// 1. Mapping specific columns if `select_columns` is set.
2398    /// 2. Defaulting to all columns from the struct `R` if no columns are specified.
2399    /// 3. applying `to_json(...)` casting for temporal types when using `AnyImpl` structs,
2400    ///    ensuring compatibility with the `FromAnyRow` deserialization logic.
2401    fn select_args_sql<R: AnyImpl>(&self) -> Vec<String> {
2402        let struct_cols = R::columns();
2403        let table_id = self.get_table_identifier();
2404        let main_table_snake = self.table_name.to_snake_case();
2405        
2406        if struct_cols.is_empty() {
2407            if self.select_columns.is_empty() { return vec!["*".to_string()]; }
2408            
2409            // If result type is a tuple or primitive (struct_cols is empty),
2410            // we still need to handle temporal types for Postgres.
2411            if matches!(self.driver, Drivers::Postgres) {
2412                let mut args = Vec::new();
2413                for s in &self.select_columns {
2414                    for sub in s.split(',') {
2415                        let s_trim = sub.trim();
2416                        if s_trim.contains(' ') || s_trim.contains('(') {
2417                            args.push(s_trim.to_string());
2418                            continue;
2419                        }
2420
2421                        let (t, c) = if let Some((t, c)) = s_trim.split_once('.') {
2422                            (t.trim().trim_matches('"'), c.trim().trim_matches('"'))
2423                        } else {
2424                            (table_id.as_str(), s_trim.trim_matches('"'))
2425                        };
2426
2427                        let c_snake = c.to_snake_case();
2428                        let mut is_temporal = false;
2429                        
2430                        // Check if this column is known to be temporal
2431                        if let Some(info) = self.columns_info.iter().find(|info| {
2432                            info.name.to_snake_case() == c_snake
2433                        }) {
2434                            if is_temporal_type(info.sql_type) {
2435                                is_temporal = true;
2436                            }
2437                        }
2438
2439                        if is_temporal {
2440                            args.push(format!("to_json(\"{}\".\"{}\") #>> '{{}}' AS \"{}\"", t, c, c));
2441                        } else {
2442                            args.push(format!("\"{}\".\"{}\"", t, c));
2443                        }
2444                    }
2445                }
2446                return args;
2447            }
2448            
2449            return self.select_columns.clone();
2450        }
2451        let mut flat_selects = Vec::new();
2452        for s in &self.select_columns {
2453            for sub in s.split(',') { flat_selects.push(sub.trim().to_string()); }
2454        }
2455        let mut expanded_tables = HashSet::new();
2456        for s in &flat_selects {
2457            if s == "*" { expanded_tables.insert(table_id.clone()); expanded_tables.insert(main_table_snake.clone()); }
2458            else if let Some(t) = s.strip_suffix(".*") { let t_clean = t.trim().trim_matches('"'); expanded_tables.insert(t_clean.to_string()); expanded_tables.insert(t_clean.to_snake_case()); }
2459        }
2460        let mut col_counts = HashMap::new();
2461        for col_info in &struct_cols {
2462            let col_snake = col_info.column.strip_prefix("r#").unwrap_or(col_info.column).to_snake_case();
2463            *col_counts.entry(col_snake).or_insert(0) += 1;
2464        }
2465        let is_tuple = format!("{:?}", std::any::type_name::<R>()).contains('(');
2466        let mut matched_s_indices = HashSet::new();
2467        let mut manual_field_map = HashMap::new();
2468
2469        for (f_idx, s) in flat_selects.iter().enumerate() {
2470            if s == "*" || s.ends_with(".*") { continue; }
2471            let s_lower = s.to_lowercase();
2472            for (s_idx, col_info) in struct_cols.iter().enumerate() {
2473                if matched_s_indices.contains(&s_idx) { continue; }
2474                let col_snake = col_info.column.strip_prefix("r#").unwrap_or(col_info.column).to_snake_case();
2475                let mut m = false;
2476                if let Some((_, alias)) = s_lower.split_once(" as ") {
2477                    let ca = alias.trim().trim_matches('"').trim_matches('\'');
2478                    if ca == col_info.column || ca == &col_snake { m = true; }
2479                } else if s == col_info.column || s == &col_snake || s.ends_with(&format!(".{}", col_info.column)) || s.ends_with(&format!(".{}", col_snake)) {
2480                    m = true;
2481                }
2482                if m { manual_field_map.insert(f_idx, s_idx); matched_s_indices.insert(s_idx); break; }
2483            }
2484        }
2485
2486        let mut args = Vec::new();
2487        if self.select_columns.is_empty() {
2488            for (s_idx, col_info) in struct_cols.iter().enumerate() {
2489                let mut t_use = table_id.clone();
2490                if !col_info.table.is_empty() {
2491                    let c_snake = col_info.table.to_snake_case();
2492                    if c_snake == main_table_snake { t_use = table_id.clone(); }
2493                    else if let Some(alias) = self.join_aliases.get(&c_snake) { t_use = alias.clone(); }
2494                    else if self.join_aliases.values().any(|a| a == &col_info.table) { t_use = col_info.table.to_string(); }
2495                }
2496                args.push(self.format_select_field::<R>(s_idx, &t_use, &main_table_snake, &col_counts, is_tuple));
2497            }
2498        } else {
2499            for (f_idx, s) in flat_selects.iter().enumerate() {
2500                let s_trim = s.trim();
2501                if s_trim == "*" || s_trim.ends_with(".*") {
2502                    let mut t_exp = if s_trim == "*" { String::new() } else { s_trim.strip_suffix(".*").unwrap().trim().trim_matches('"').to_string() };
2503                    if !t_exp.is_empty() && (t_exp.to_snake_case() == main_table_snake || t_exp == table_id) { t_exp = table_id.clone(); }
2504                    for (s_idx, col_info) in struct_cols.iter().enumerate() {
2505                        if matched_s_indices.contains(&s_idx) { continue; }
2506                        let mut t_col = table_id.clone(); let mut known = false;
2507                        if !col_info.table.is_empty() {
2508                            let c_snake = col_info.table.to_snake_case();
2509                            if c_snake == main_table_snake { t_col = table_id.clone(); known = true; }
2510                            else if let Some(alias) = self.join_aliases.get(&c_snake) { t_col = alias.clone(); known = true; }
2511                            else if self.join_aliases.values().any(|a| a == &col_info.table) { t_col = col_info.table.to_string(); known = true; }
2512                        }
2513                        if !known && !t_exp.is_empty() && flat_selects.iter().filter(|x| x.ends_with(".*") || *x == "*").count() == 1 { t_col = t_exp.clone(); known = true; }
2514                        if (t_exp.is_empty() && known) || (!t_exp.is_empty() && t_col == t_exp) {
2515                            args.push(self.format_select_field::<R>(s_idx, &t_col, &main_table_snake, &col_counts, is_tuple));
2516                            matched_s_indices.insert(s_idx);
2517                        }
2518                    }
2519                } else if let Some(s_idx) = manual_field_map.get(&f_idx) {
2520                    if s.to_lowercase().contains(" as ") { args.push(s_trim.to_string()); }
2521                    else {
2522                        let mut t = table_id.clone();
2523                        if let Some((prefix, _)) = s_trim.split_once('.') { t = prefix.trim().trim_matches('"').to_string(); }
2524                        args.push(self.format_select_field::<R>(*s_idx, &t, &main_table_snake, &col_counts, is_tuple));
2525                    }
2526                } else {
2527                    if !s_trim.contains(' ') && !s_trim.contains('(') {
2528                        if let Some((t, c)) = s_trim.split_once('.') { args.push(format!("\"{}\".\"{}\"", t.trim().trim_matches('"'), c.trim().trim_matches('"'))); }
2529                        else { args.push(format!("\"{}\"", s_trim.trim_matches('"'))); }
2530                    } else { args.push(s_trim.to_string()); }
2531                }
2532            }
2533        }
2534        if args.is_empty() { vec!["*".to_string()] } else { args }
2535    }
2536
2537    fn format_select_field<R: AnyImpl>(&self, s_idx: usize, table_to_use: &str, main_table_snake: &str, col_counts: &HashMap<String, usize>, is_tuple: bool) -> String {
2538        let col_info = &R::columns()[s_idx];
2539        let col_snake = col_info.column.strip_prefix("r#").unwrap_or(col_info.column).to_snake_case();
2540        let has_collision = *col_counts.get(&col_snake).unwrap_or(&0) > 1;
2541        let alias = if is_tuple || has_collision {
2542            let t_alias = if !col_info.table.is_empty() { col_info.table.to_snake_case() } else { main_table_snake.to_string() };
2543            format!("{}__{}", t_alias.to_lowercase(), col_snake.to_lowercase())
2544        } else { col_snake.to_lowercase() };
2545        if is_temporal_type(col_info.sql_type) && matches!(self.driver, Drivers::Postgres) {
2546            format!("to_json(\"{}\".\"{}\") #>> '{{}}' AS \"{}\"", table_to_use, col_snake, alias)
2547        } else {
2548            format!("\"{}\".\"{}\" AS \"{}\"", table_to_use, col_snake, alias)
2549        }
2550    }
2551
2552    /// Executes the query and returns a list of results.
2553    ///
2554    /// This method builds and executes a SELECT query with all accumulated filters,
2555    /// ordering, and pagination settings. It returns all matching rows as a vector.
2556    ///
2557    /// # Type Parameters
2558    ///
2559    /// * `R` - The result type. Must implement `FromAnyRow` and `AnyImpl`.
2560    ///
2561    /// # Returns
2562    ///
2563    /// * `Ok(Vec<R>)` - Vector of results (empty if no matches)
2564    /// * `Err(sqlx::Error)` - Database error during query execution
2565    ///
2566    /// # Example
2567    ///
2568    /// ```rust,ignore
2569    /// let users: Vec<User> = db.model::<User>()
2570    ///     .filter("age", Op::Gte, 18)
2571    ///     .scan()
2572    ///     .await?;
2573    /// // SQL: SELECT * FROM "user" WHERE "age" >= 18
2574    /// ```
2575    pub async fn scan<R>(mut self) -> Result<Vec<R>, sqlx::Error>
2576    where
2577        R: FromAnyRow + AnyImpl + Send + Unpin,
2578    {
2579        self.apply_soft_delete_filter();
2580        let mut query = String::new();
2581        let mut args = AnyArguments::default();
2582        let mut arg_counter = 1;
2583
2584        self.write_select_sql::<R>(&mut query, &mut args, &mut arg_counter);
2585
2586        if self.debug_mode {
2587            log::debug!("SQL: {}", query);
2588        }
2589
2590        let rows = self.tx.fetch_all(&query, args).await?;
2591        let mut result = Vec::with_capacity(rows.len());
2592        for row in rows {
2593            result.push(R::from_any_row(&row)?);
2594        }
2595        Ok(result)
2596    }
2597
2598    /// Executes the query and maps the result to a custom DTO.
2599    ///
2600    /// Useful for queries that return only a subset of columns or join multiple tables.
2601    ///
2602    /// # Type Parameters
2603    ///
2604    /// * `R` - The DTO type. Must implement `FromAnyRow` and `AnyImpl`.
2605    ///
2606    /// # Returns
2607    ///
2608    /// * `Ok(Vec<R>)` - Vector of results
2609    /// * `Err(sqlx::Error)` - Database error
2610    ///
2611    /// # Example
2612    ///
2613    /// ```rust,ignore
2614    /// let dtos: Vec<UserStats> = db.model::<User>()
2615    ///     .select("username, age")
2616    ///     .scan_as::<UserStats>()
2617    ///     .await?;
2618    /// // SQL: SELECT "username", "age" FROM "user"
2619    /// ```
2620    pub async fn scan_as<R>(mut self) -> Result<Vec<R>, sqlx::Error>
2621    where
2622        R: FromAnyRow + AnyImpl + Send + Unpin,
2623    {
2624        self.apply_soft_delete_filter();
2625        let mut query = String::new();
2626        let mut args = AnyArguments::default();
2627        let mut arg_counter = 1;
2628
2629        self.write_select_sql::<R>(&mut query, &mut args, &mut arg_counter);
2630
2631        if self.debug_mode {
2632            log::debug!("SQL: {}", query);
2633        }
2634
2635        let rows = self.tx.fetch_all(&query, args).await?;
2636        let mut result = Vec::with_capacity(rows.len());
2637        for row in rows {
2638            result.push(R::from_any_row(&row)?);
2639        }
2640        Ok(result)
2641    }
2642
2643    /// Executes the query and returns only the first result.
2644    ///
2645    /// Automatically applies `LIMIT 1` if no limit is set.
2646    ///
2647    /// # Type Parameters
2648    ///
2649    /// * `R` - The result type. Must implement `FromAnyRow` and `AnyImpl`.
2650    ///
2651    /// # Returns
2652    ///
2653    /// * `Ok(R)` - The first matching record
2654    /// * `Err(sqlx::Error::RowNotFound)` - If no records match
2655    ///
2656    /// # Example
2657    ///
2658    /// ```rust,ignore
2659    /// let user: User = db.model::<User>()
2660    ///     .filter("id", Op::Eq, 1)
2661    ///     .first()
2662    ///     .await?;
2663    /// // SQL: SELECT * FROM "user" WHERE "id" = 1 LIMIT 1
2664    /// ```
2665    pub async fn first<R>(mut self) -> Result<R, sqlx::Error>
2666    where
2667        R: FromAnyRow + AnyImpl + Send + Unpin,
2668    {
2669        self.apply_soft_delete_filter();
2670        let mut query = String::new();
2671        let mut args = AnyArguments::default();
2672        let mut arg_counter = 1;
2673
2674        // Force limit 1 if not set
2675        if self.limit.is_none() {
2676            self.limit = Some(1);
2677        }
2678
2679        // Apply PK ordering fallback if no order is set
2680        if self.order_clauses.is_empty() {
2681            let table_id = self.get_table_identifier();
2682            let pk_columns: Vec<String> = <T as Model>::columns()
2683                .iter()
2684                .filter(|c| c.is_primary_key)
2685                .map(|c| format!("\"{}\".\"{}\"", table_id, c.name.strip_prefix("r#").unwrap_or(c.name).to_snake_case()))
2686                .collect();
2687            
2688            if !pk_columns.is_empty() {
2689                self.order_clauses.push(pk_columns.iter().map(|col| format!("{} ASC", col)).collect::<Vec<_>>().join(", "));
2690            }
2691        }
2692
2693        self.write_select_sql::<R>(&mut query, &mut args, &mut arg_counter);
2694
2695        if self.debug_mode {
2696            log::debug!("SQL: {}", query);
2697        }
2698
2699        let row = self.tx.fetch_one(&query, args).await?;
2700        R::from_any_row(&row)
2701    }
2702
2703    /// Executes the query and returns a single scalar value.
2704    ///
2705    /// This method is useful for fetching single values like counts, max/min values,
2706    /// or specific columns without mapping to a struct or tuple.
2707    ///
2708    /// # Type Parameters
2709    ///
2710    /// * `O` - The output type. Must implement `FromAnyRow`, `AnyImpl`, `Send` and `Unpin`.
2711    ///
2712    /// # Example
2713    ///
2714    /// ```rust,ignore
2715    /// // Get count of users
2716    /// let count: i64 = db.model::<User>()
2717    ///     .select("count(*)")
2718    ///     .scalar()
2719    ///     .await?;
2720    ///
2721    /// // Get specific field
2722    /// let username: String = db.model::<User>()
2723    ///     .filter("id", "=", 1)
2724    ///     .select("username")
2725    ///     .scalar()
2726    ///     .await?;
2727    /// ```
2728    pub async fn scalar<O>(mut self) -> Result<O, sqlx::Error>
2729    where
2730        O: FromAnyRow + AnyImpl + Send + Unpin,
2731    {
2732        self.apply_soft_delete_filter();
2733        let mut query = String::new();
2734        let mut args = AnyArguments::default();
2735        let mut arg_counter = 1;
2736
2737        // Force limit 1 if not set
2738        if self.limit.is_none() {
2739            self.limit = Some(1);
2740        }
2741
2742        self.write_select_sql::<O>(&mut query, &mut args, &mut arg_counter);
2743
2744        if self.debug_mode {
2745            log::debug!("SQL: {}", query);
2746        }
2747
2748        let row = self.tx.fetch_one(&query, args).await?;
2749        O::from_any_row(&row)
2750    }
2751
2752    /// Updates a single column in the database.
2753    ///
2754    /// # Arguments
2755    ///
2756    /// * `col` - The column name to update
2757    /// * `value` - The new value
2758    ///
2759    /// # Returns
2760    ///
2761    /// * `Ok(u64)` - The number of rows affected
2762    pub fn update<'b, V>(&'b mut self, col: &str, value: V) -> BoxFuture<'b, Result<u64, sqlx::Error>>
2763    where
2764        V: ToUpdateValue + Send + Sync,
2765    {
2766        let mut map = std::collections::HashMap::new();
2767        map.insert(col.to_string(), value.to_update_value());
2768        self.execute_update(map)
2769    }
2770
2771    /// Updates all columns based on the model instance.
2772    ///
2773    /// This method updates all active columns of the table with values from the provided model.
2774    ///
2775    /// # Arguments
2776    ///
2777    /// * `model` - The model instance containing new values
2778    ///
2779    /// # Returns
2780    ///
2781    /// * `Ok(u64)` - The number of rows affected
2782    pub fn updates<'b>(&'b mut self, model: &T) -> BoxFuture<'b, Result<u64, sqlx::Error>> {
2783        self.execute_update(Model::to_map(model))
2784    }
2785
2786    /// Updates columns based on a partial model (struct implementing AnyImpl).
2787    ///
2788    /// This allows updating a subset of columns using a custom struct.
2789    /// The struct must implement `AnyImpl` (usually via `#[derive(FromAnyRow)]`).
2790    ///
2791    /// # Arguments
2792    ///
2793    /// * `partial` - The partial model containing new values
2794    ///
2795    /// # Returns
2796    ///
2797    /// * `Ok(u64)` - The number of rows affected
2798    pub fn update_partial<'b, P: AnyImpl>(&'b mut self, partial: &P) -> BoxFuture<'b, Result<u64, sqlx::Error>> {
2799        self.execute_update(AnyImpl::to_map(partial))
2800    }
2801
2802    /// Updates a column using a raw SQL expression.
2803    ///
2804    /// This allows for complex updates like incrementing values or using database functions.
2805    /// You can use a `?` placeholder in the expression and provide a value to bind.
2806    ///
2807    /// # Arguments
2808    ///
2809    /// * `col` - The column name to update
2810    /// * `expr` - The raw SQL expression (e.g., "age + 1" or "age + ?")
2811    /// * `value` - The value to bind for the placeholder
2812    ///
2813    /// # Example
2814    ///
2815    /// ```rust,ignore
2816    /// // Increment age by 1
2817    /// db.model::<User>()
2818    ///     .filter("id", "=", 1)
2819    ///     .update_raw("age", "age + 1", 0)
2820    ///     .await?;
2821    ///
2822    /// // Increment age by a variable
2823    /// db.model::<User>()
2824    ///     .filter("id", "=", 1)
2825    ///     .update_raw("age", "age + ?", 5)
2826    ///     .await?;
2827    /// ```
2828    pub fn update_raw<'b, V>(
2829        &'b mut self,
2830        col: &str,
2831        expr: &str,
2832        value: V,
2833    ) -> BoxFuture<'b, Result<u64, sqlx::Error>>
2834    where
2835        V: 'static + for<'q> Encode<'q, Any> + Type<Any> + Send + Sync + Clone,
2836    {
2837        self.apply_soft_delete_filter();
2838
2839        let col_name_clean = col.strip_prefix("r#").unwrap_or(col).to_snake_case();
2840        let expr_owned = expr.to_string();
2841        let value_owned = value.clone();
2842
2843        Box::pin(async move {
2844            let table_name = self.table_name.to_snake_case();
2845            let mut query = format!("UPDATE \"{}\" ", table_name);
2846            if let Some(alias) = &self.alias {
2847                query.push_str(&format!("AS {} ", alias));
2848            }
2849            query.push_str("SET ");
2850
2851            let mut arg_counter = 1;
2852            let mut args = AnyArguments::default();
2853
2854            let mut processed_expr = expr_owned.clone();
2855            let mut has_placeholder = false;
2856
2857            if processed_expr.contains('?') {
2858                has_placeholder = true;
2859                if matches!(self.driver, Drivers::Postgres) {
2860                    while let Some(pos) = processed_expr.find('?') {
2861                        let placeholder = format!("${}", arg_counter);
2862                        arg_counter += 1;
2863                        processed_expr.replace_range(pos..pos + 1, &placeholder);
2864                    }
2865                }
2866            }
2867
2868            if has_placeholder {
2869                let _ = args.add(value_owned);
2870            }
2871
2872            query.push_str(&format!("\"{}\" = {}", col_name_clean, processed_expr));
2873            query.push_str(" WHERE 1=1");
2874
2875            for clause in &self.where_clauses {
2876                clause(&mut query, &mut args, &self.driver, &mut arg_counter);
2877            }
2878
2879            if self.debug_mode {
2880                log::debug!("SQL: {}", query);
2881            }
2882
2883            let result = self.tx.execute(&query, args).await?;
2884            Ok(result.rows_affected())
2885        })
2886    }
2887
2888    /// Internal helper to apply soft delete filter to where clauses if necessary.
2889    fn apply_soft_delete_filter(&mut self) {
2890        if !self.with_deleted {
2891            if let Some(soft_delete_col) = self.columns_info.iter().find(|c| c.soft_delete).map(|c| c.name) {
2892                let col_owned = soft_delete_col.to_string();
2893                let clause: FilterFn = Box::new(move |query, _args, _driver, _arg_counter| {
2894                    query.push_str(" AND ");
2895                    query.push_str(&format!("\"{}\"", col_owned));
2896                    query.push_str(" IS NULL");
2897                });
2898                self.where_clauses.push(clause);
2899            }
2900        }
2901    }
2902
2903    /// Internal helper to execute an UPDATE query from a map of values.
2904    fn execute_update<'b>(
2905        &'b mut self,
2906        data_map: std::collections::HashMap<String, Option<String>>,
2907    ) -> BoxFuture<'b, Result<u64, sqlx::Error>> {
2908        self.apply_soft_delete_filter();
2909
2910        Box::pin(async move {
2911            let table_name = self.table_name.to_snake_case();
2912            let mut query = format!("UPDATE \"{}\" ", table_name);
2913            if let Some(alias) = &self.alias {
2914                query.push_str(&format!("{} ", alias));
2915            }
2916            query.push_str("SET ");
2917
2918            let mut bindings: Vec<(Option<String>, &str)> = Vec::new();
2919            let mut set_clauses = Vec::new();
2920
2921            // Maintain argument counter for PostgreSQL ($1, $2, ...)
2922            let mut arg_counter = 1;
2923
2924            // Build SET clause
2925            for (col_name, value) in data_map {
2926                // Strip the "r#" prefix if present
2927                let col_name_clean = col_name.strip_prefix("r#").unwrap_or(&col_name).to_snake_case();
2928
2929                // Find the SQL type for this column from the Model metadata
2930                let sql_type_opt = self
2931                    .columns_info
2932                    .iter()
2933                    .find(|c| c.name == col_name || c.name == col_name_clean)
2934                    .map(|c| c.sql_type);
2935                    
2936                let sql_type = match sql_type_opt {
2937                    Some(t) => t,
2938                    None => continue,
2939                };
2940
2941                // Generate placeholder
2942                let placeholder = match self.driver {
2943                    Drivers::Postgres => {
2944                        let idx = arg_counter;
2945                        arg_counter += 1;
2946
2947                        if temporal::is_temporal_type(sql_type) {
2948                            format!("${}{}", idx, temporal::get_postgres_type_cast(sql_type))
2949                        } else {
2950                            match sql_type {
2951                                "UUID" => format!("${}::UUID", idx),
2952                                "JSONB" | "jsonb" => format!("${}::JSONB", idx),
2953                                s if s.ends_with("[]") => format!("${}::{}", idx, s),
2954                                _ => format!("${}", idx),
2955                            }
2956                        }
2957                    }
2958                    _ => "?".to_string(),
2959                };
2960
2961                set_clauses.push(format!("\"{}\" = {}", col_name_clean, placeholder));
2962                bindings.push((value, sql_type));
2963            }
2964
2965            // If no fields to update, return 0
2966            if set_clauses.is_empty() {
2967                return Ok(0);
2968            }
2969
2970            query.push_str(&set_clauses.join(", "));
2971
2972            // Build WHERE clause
2973            query.push_str(" WHERE 1=1");
2974
2975            let mut args = AnyArguments::default();
2976
2977            // Bind SET values
2978            for (val_opt, sql_type) in bindings {
2979                if let Some(val_str) = val_opt {
2980                    if args.bind_value(&val_str, sql_type, &self.driver).is_err() {
2981                        let _ = args.add(val_str);
2982                    }
2983                } else {
2984                    let _ = args.add(None::<String>);
2985                }
2986            }
2987
2988            // Apply WHERE clauses (appending to args and query)
2989            for clause in &self.where_clauses {
2990                clause(&mut query, &mut args, &self.driver, &mut arg_counter);
2991            }
2992
2993            // Print SQL query to logs if debug mode is active
2994            if self.debug_mode {
2995                log::debug!("SQL: {}", query);
2996            }
2997
2998            // Execute the UPDATE query
2999            let result = self.tx.execute(&query, args).await?;
3000
3001            Ok(result.rows_affected())
3002        })
3003    }
3004
3005    /// Executes a DELETE query based on the current filters.
3006    ///
3007    /// Performs a soft delete if the model has a soft delete column,
3008    /// otherwise performs a permanent hard delete.
3009    ///
3010    /// # Returns
3011    ///
3012    /// * `Ok(u64)` - The number of rows deleted (or soft-deleted)
3013    /// * `Err(sqlx::Error)` - Database error
3014    ///
3015    /// # Example
3016    ///
3017    /// ```rust,ignore
3018    /// db.model::<User>()
3019    ///     .filter("id", Op::Eq, 1)
3020    ///     .delete()
3021    ///     .await?;
3022    /// // SQL (Soft): UPDATE "user" SET "deleted_at" = NOW() WHERE "id" = 1
3023    /// // SQL (Hard): DELETE FROM "user" WHERE "id" = 1
3024    /// ```
3025    pub async fn delete(self) -> Result<u64, sqlx::Error> {
3026        // Check for soft delete column
3027        let soft_delete_col = self.columns_info.iter().find(|c| c.soft_delete).map(|c| c.name);
3028
3029        if let Some(col) = soft_delete_col {
3030            // Soft Delete: Update the column to current timestamp
3031            let table_name = self.table_name.to_snake_case();
3032            let mut query = format!("UPDATE \"{}\" ", table_name);
3033            if let Some(alias) = &self.alias {
3034                query.push_str(&format!("{} ", alias));
3035            }
3036            query.push_str(&format!("SET \"{}\" = ", col));
3037
3038            match self.driver {
3039                Drivers::Postgres => query.push_str("NOW()"),
3040                Drivers::SQLite => query.push_str("strftime('%Y-%m-%dT%H:%M:%SZ', 'now')"),
3041                Drivers::MySQL => query.push_str("NOW()"),
3042            }
3043
3044            query.push_str(" WHERE 1=1");
3045
3046            let mut args = AnyArguments::default();
3047            let mut arg_counter = 1;
3048
3049            // Apply filters
3050            for clause in &self.where_clauses {
3051                clause(&mut query, &mut args, &self.driver, &mut arg_counter);
3052            }
3053
3054            // Print SQL query to logs if debug mode is active
3055            if self.debug_mode {
3056                log::debug!("SQL: {}", query);
3057            }
3058
3059            let result = self.tx.execute(&query, args).await?;
3060            Ok(result.rows_affected())
3061        } else {
3062            // Standard Delete (no soft delete column)
3063            let mut query = String::from("DELETE FROM \"");
3064            query.push_str(&self.table_name.to_snake_case());
3065            query.push_str("\" WHERE 1=1");
3066
3067            let mut args = AnyArguments::default();
3068            let mut arg_counter = 1;
3069
3070            for clause in &self.where_clauses {
3071                clause(&mut query, &mut args, &self.driver, &mut arg_counter);
3072            }
3073
3074            // Print SQL query to logs if debug mode is active
3075            if self.debug_mode {
3076                log::debug!("SQL: {}", query);
3077            }
3078
3079            let result = self.tx.execute(&query, args).await?;
3080            Ok(result.rows_affected())
3081        }
3082    }
3083
3084    /// Permanently removes records from the database.
3085    ///
3086    /// # Returns
3087    ///
3088    /// * `Ok(u64)` - The number of rows deleted
3089    /// * `Err(sqlx::Error)` - Database error
3090    ///
3091    /// # Example
3092    ///
3093    /// ```rust,ignore
3094    /// db.model::<User>()
3095    ///     .filter("id", Op::Eq, 1)
3096    ///     .hard_delete()
3097    ///     .await?;
3098    /// // SQL: DELETE FROM "user" WHERE "id" = 1
3099    /// ```
3100    pub async fn hard_delete(self) -> Result<u64, sqlx::Error> {
3101        let mut query = String::from("DELETE FROM \"");
3102        query.push_str(&self.table_name.to_snake_case());
3103        query.push_str("\" WHERE 1=1");
3104
3105        let mut args = AnyArguments::default();
3106        let mut arg_counter = 1;
3107
3108        for clause in &self.where_clauses {
3109            clause(&mut query, &mut args, &self.driver, &mut arg_counter);
3110        }
3111
3112        // Print SQL query to logs if debug mode is active
3113        if self.debug_mode {
3114            log::debug!("SQL: {}", query);
3115        }
3116
3117        let result = self.tx.execute(&query, args).await?;
3118        Ok(result.rows_affected())
3119    }
3120}