1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//! Sql filtering trait for defining type safe dynamic filters.
use crateDatabase;
use ;
/// Trait for creating SQL filter conditions that can be applied to database queries.
///
/// The `SqlFilter` trait provides a standardized way to define reusable, type-safe
/// SQL filter conditions. Filters can be composed and combined using logical operators
/// to create complex query criteria.
///
/// # Type Parameters
///
/// * `'args`: The lifetime for query arguments
/// * `DB`: The database backend type (defaults to the configured default database)
///
/// # Examples
///
/// Basic implementation using the macro:
/// ```rust
/// # use sqlx_utils::sql_filter;
/// # use sqlx_utils::traits::SqlFilter;
/// # use sqlx_utils::types::Database;
/// # use sqlx::QueryBuilder;
///
/// sql_filter! {
/// pub struct UserFilter {
/// SELECT * FROM users WHERE
/// id = i32 AND
/// ?name LIKE String AND
/// ?email LIKE String
/// }
/// }
///
/// // Usage
/// # fn example() {
/// let filter = UserFilter::new(42)
/// .name("Alice%")
/// .email("alice@example.com");
///
/// let mut builder = QueryBuilder::<Database>::new("SELECT * FROM users WHERE ");
/// filter.apply_filter(&mut builder);
/// # }
/// ```
///
/// Custom implementation:
/// ```rust
/// # use sqlx_utils::traits::SqlFilter;
/// # use sqlx_utils::types::Database;
/// # use sqlx::QueryBuilder;
///
/// struct AgeRangeFilter {
/// min_age: Option<i32>,
/// max_age: Option<i32>,
/// }
///
/// impl<'args> SqlFilter<'args, Database> for AgeRangeFilter {
/// fn apply_filter(self, builder: &mut QueryBuilder<'args, Database>) {
/// if self.min_age.is_some() || self.max_age.is_some() {
/// let mut first = true;
///
/// if let Some(min) = self.min_age {
/// if !first { builder.push(" AND "); }
/// builder.push("age >= ");
/// builder.push_bind(min);
/// first = false;
/// }
///
/// if let Some(max) = self.max_age {
/// if !first { builder.push(" AND "); }
/// builder.push("age <= ");
/// builder.push_bind(max);
/// }
/// }
/// }
///
/// fn should_apply_filter(&self) -> bool {
/// self.min_age.is_some() || self.max_age.is_some()
/// }
/// }
/// ```
///
/// # Implementation Notes
///
/// When implementing this trait:
///
/// 1. The [`apply_filter`](SqlFilter::apply_filter) method should add SQL conditions to the builder
/// 2. The [`should_apply_filter`](SqlFilter::should_apply_filter) method should return `true` if this filter has criteria to apply
/// 3. Consider using the [`sql_filter!`](crate::sql_filter) macro for common filter patterns
/// 4. Ensure proper parameterization to prevent SQL injection