by_loco/model/query/dsl/
mod.rs

1use sea_orm::{
2    sea_query::{IntoCondition, Order},
3    ColumnTrait, Condition, Value,
4};
5use serde::{Deserialize, Serialize};
6
7mod date_range;
8
9// pub mod pagination;
10
11#[derive(Debug)]
12pub struct ConditionBuilder {
13    condition: Condition,
14}
15/// Enum representing sorting directions, with serialization and deserialization
16/// support.
17#[derive(Debug, Deserialize, Serialize)]
18pub enum SortDirection {
19    #[serde(rename = "desc")]
20    Desc,
21    #[serde(rename = "asc")]
22    Asc,
23}
24
25impl SortDirection {
26    /// Returns the corresponding `Order` enum variant based on the current
27    /// `SortDirection`.
28    #[must_use]
29    pub const fn order(&self) -> Order {
30        match self {
31            Self::Desc => Order::Desc,
32            Self::Asc => Order::Asc,
33        }
34    }
35}
36
37#[must_use]
38pub fn condition() -> ConditionBuilder {
39    ConditionBuilder {
40        condition: Condition::all(),
41    }
42}
43
44#[must_use]
45pub const fn with(condition: Condition) -> ConditionBuilder {
46    ConditionBuilder { condition }
47}
48
49/// See [`ConditionBuilder::eq`]
50#[must_use]
51pub fn eq<T: ColumnTrait, V: Into<Value>>(col: T, value: V) -> ConditionBuilder {
52    condition().eq(col, value)
53}
54
55/// See [`ConditionBuilder::ne`]
56#[must_use]
57pub fn not_equal<T: ColumnTrait, V: Into<Value>>(col: T, value: V) -> ConditionBuilder {
58    condition().ne(col, value)
59}
60
61/// See [`ConditionBuilder::gt`]
62#[must_use]
63pub fn gt<T: ColumnTrait, V: Into<Value>>(col: T, value: V) -> ConditionBuilder {
64    condition().gt(col, value)
65}
66
67/// See [`ConditionBuilder::gte`]
68#[must_use]
69pub fn gt_equal<T: ColumnTrait, V: Into<Value>>(col: T, value: V) -> ConditionBuilder {
70    condition().gte(col, value)
71}
72
73/// See [`ConditionBuilder::lt`]
74#[must_use]
75pub fn lt<T: ColumnTrait, V: Into<Value>>(col: T, value: V) -> ConditionBuilder {
76    condition().lt(col, value)
77}
78
79/// See [`ConditionBuilder::lte`]
80#[must_use]
81pub fn lt_equal<T: ColumnTrait, V: Into<Value>>(col: T, value: V) -> ConditionBuilder {
82    condition().lte(col, value)
83}
84
85/// See [`ConditionBuilder::between`]
86#[must_use]
87pub fn between<T: ColumnTrait, V: Into<Value>>(col: T, a: V, b: V) -> ConditionBuilder {
88    condition().between(col, a, b)
89}
90
91/// See [`ConditionBuilder::not_between`]
92#[must_use]
93pub fn not_between<T: ColumnTrait, V: Into<Value>>(col: T, a: V, b: V) -> ConditionBuilder {
94    condition().not_between(col, a, b)
95}
96
97/// See [`ConditionBuilder::like`]
98#[must_use]
99pub fn like<T: ColumnTrait, V: Into<String>>(col: T, a: V) -> ConditionBuilder {
100    condition().like(col, a)
101}
102
103/// See [`ConditionBuilder::not_like`]
104#[must_use]
105pub fn not_like<T: ColumnTrait, V: Into<String>>(col: T, a: V) -> ConditionBuilder {
106    condition().not_like(col, a)
107}
108
109/// See [`ConditionBuilder::starts_with`]
110#[must_use]
111pub fn starts_with<T: ColumnTrait, V: Into<String>>(col: T, a: V) -> ConditionBuilder {
112    condition().starts_with(col, a)
113}
114
115/// See [`ConditionBuilder::ends_with`]
116#[must_use]
117pub fn ends_with<T: ColumnTrait, V: Into<String>>(col: T, a: V) -> ConditionBuilder {
118    condition().ends_with(col, a)
119}
120
121/// See [`ConditionBuilder::contains`]
122#[must_use]
123pub fn contains<T: ColumnTrait, V: Into<String>>(col: T, a: V) -> ConditionBuilder {
124    condition().contains(col, a)
125}
126
127/// See [`ConditionBuilder::is_null`]
128#[must_use]
129#[allow(clippy::wrong_self_convention)]
130pub fn is_null<T: ColumnTrait>(col: T) -> ConditionBuilder {
131    condition().is_null(col)
132}
133
134/// See [`ConditionBuilder::is_not_null`]
135#[must_use]
136#[allow(clippy::wrong_self_convention)]
137pub fn is_not_null<T: ColumnTrait>(col: T) -> ConditionBuilder {
138    condition().is_not_null(col)
139}
140
141/// See [`ConditionBuilder::is_in`]
142#[must_use]
143#[allow(clippy::wrong_self_convention)]
144pub fn is_in<T: ColumnTrait, V: Into<Value>, I: IntoIterator<Item = V>>(
145    col: T,
146    values: I,
147) -> ConditionBuilder {
148    condition().is_in(col, values)
149}
150
151/// See [`ConditionBuilder::is_not_in`]
152#[must_use]
153#[allow(clippy::wrong_self_convention)]
154pub fn is_not_in<T: ColumnTrait, V: Into<Value>, I: IntoIterator<Item = V>>(
155    col: T,
156    values: I,
157) -> ConditionBuilder {
158    condition().is_not_in(col, values)
159}
160
161/// See [`ConditionBuilder::date_range`]
162#[must_use]
163pub fn date_range<T: ColumnTrait>(col: T) -> date_range::DateRangeBuilder<T> {
164    date_range::DateRangeBuilder::new(condition(), col)
165}
166
167impl IntoCondition for ConditionBuilder {
168    fn into_condition(self) -> Condition {
169        self.build()
170    }
171}
172
173/// Builder query condition
174///
175/// # Examples
176/// ```
177/// use loco_rs::tests_cfg::db::test_db;
178/// use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
179/// use loco_rs::prelude::*;
180/// let date = chrono::NaiveDateTime::parse_from_str("2024-03-01 22:10:57", "%Y-%m-%d %H:%M:%S").unwrap();
181///
182/// let query_str = test_db::Entity::find()
183///         .select_only()
184///         .column(test_db::Column::Id)
185///         .filter(query::condition().date_range(test_db::Column::CreatedAt).from(&date).build().like(test_db::Column::Name, "%lo").build())
186///         .build(sea_orm::DatabaseBackend::Postgres)
187///         .to_string();
188///
189///     assert_eq!(
190///         query_str,
191///         "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"created_at\" > '2024-03-01 22:10:57' AND \"loco\".\"name\" LIKE '%lo'"
192///     );
193/// ````
194impl ConditionBuilder {
195    /// where condition the given column equals the given value
196    ///
197    /// # Examples
198    /// ```
199    /// use loco_rs::tests_cfg::db::test_db;
200    /// use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
201    /// use loco_rs::prelude::*;
202    ///
203    /// let query_str = test_db::Entity::find()
204    ///         .select_only()
205    ///         .column(test_db::Column::Id)
206    ///         .filter(query::condition().eq(test_db::Column::Id, 1).build())
207    ///         .build(sea_orm::DatabaseBackend::Postgres)
208    ///         .to_string();
209    ///
210    ///     assert_eq!(
211    ///         query_str,
212    ///         "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" = 1"
213    ///     );
214    /// ````
215    ///
216    /// On string field
217    /// ```
218    /// use loco_rs::tests_cfg::db::test_db;
219    /// use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
220    /// use loco_rs::prelude::*;
221    ///
222    /// let query_str = test_db::Entity::find()
223    ///         .select_only()
224    ///         .column(test_db::Column::Id)
225    ///         .filter(query::condition().eq(test_db::Column::Name, "loco").build())
226    ///         .build(sea_orm::DatabaseBackend::Postgres)
227    ///         .to_string();
228    ///
229    ///     assert_eq!(
230    ///         query_str,
231    ///         "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" = 'loco'"
232    ///     );
233    /// ````
234    #[must_use]
235    pub fn eq<T: ColumnTrait, V: Into<Value>>(self, col: T, value: V) -> Self {
236        with(self.condition.add(col.eq(value)))
237    }
238
239    /// where condition the given column not equals the given value
240    ///
241    /// # Examples
242    /// ```
243    /// use loco_rs::tests_cfg::db::test_db;
244    /// use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
245    /// use loco_rs::prelude::*;
246    ///
247    /// let query_str = test_db::Entity::find()
248    ///         .select_only()
249    ///         .column(test_db::Column::Id)
250    ///         .filter(query::condition().ne(test_db::Column::Id, 1).build())
251    ///         .build(sea_orm::DatabaseBackend::Postgres)
252    ///         .to_string();
253    ///
254    ///     assert_eq!(
255    ///         query_str,
256    ///         "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" <> 1"
257    ///     );
258    /// ````
259    #[must_use]
260    pub fn ne<T: ColumnTrait, V: Into<Value>>(self, col: T, value: V) -> Self {
261        with(self.condition.add(col.ne(value)))
262    }
263
264    /// where condition the given column greater than the given value
265    ///
266    /// # Examples
267    /// ```
268    /// use loco_rs::tests_cfg::db::test_db;
269    /// use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
270    /// use loco_rs::prelude::*;
271    ///
272    /// let query_str = test_db::Entity::find()
273    ///         .select_only()
274    ///         .column(test_db::Column::Id)
275    ///         .filter(query::condition().gt(test_db::Column::Id, 1).build())
276    ///         .build(sea_orm::DatabaseBackend::Postgres)
277    ///         .to_string();
278    ///
279    ///     assert_eq!(
280    ///         query_str,
281    ///         "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" > 1"
282    ///     );
283    /// ````
284    #[must_use]
285    pub fn gt<T: ColumnTrait, V: Into<Value>>(self, col: T, value: V) -> Self {
286        with(self.condition.add(col.gt(value)))
287    }
288
289    /// where condition the given column greater than or equal to the given
290    /// value
291    ///
292    /// # Examples
293    /// ```
294    /// use loco_rs::tests_cfg::db::test_db;
295    /// use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
296    /// use loco_rs::prelude::*;
297    ///
298    /// let query_str = test_db::Entity::find()
299    ///         .select_only()
300    ///         .column(test_db::Column::Id)
301    ///         .filter(query::condition().gte(test_db::Column::Id, 1).build())
302    ///         .build(sea_orm::DatabaseBackend::Postgres)
303    ///         .to_string();
304    ///
305    ///     assert_eq!(
306    ///         query_str,
307    ///         "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" >= 1"
308    ///     );
309    /// ````
310    #[must_use]
311    pub fn gte<T: ColumnTrait, V: Into<Value>>(self, col: T, value: V) -> Self {
312        with(self.condition.add(col.gte(value)))
313    }
314
315    /// where condition the given column smaller than to the given
316    /// value
317    ///
318    /// # Examples
319    /// ```
320    /// use loco_rs::tests_cfg::db::test_db;
321    /// use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
322    /// use loco_rs::prelude::*;
323    ///
324    /// let query_str = test_db::Entity::find()
325    ///         .select_only()
326    ///         .column(test_db::Column::Id)
327    ///         .filter(query::condition().lt(test_db::Column::Id, 1).build())
328    ///         .build(sea_orm::DatabaseBackend::Postgres)
329    ///         .to_string();
330    ///
331    ///     assert_eq!(
332    ///         query_str,
333    ///         "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" < 1"
334    ///     );
335    /// ````
336    #[must_use]
337    pub fn lt<T: ColumnTrait, V: Into<Value>>(self, col: T, value: V) -> Self {
338        with(self.condition.add(col.lt(value)))
339    }
340
341    /// where condition the given column smaller than or equal to the given
342    /// value
343    ///
344    /// # Examples
345    /// ```
346    /// use loco_rs::tests_cfg::db::test_db;
347    /// use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
348    /// use loco_rs::prelude::*;
349    ///
350    /// let query_str = test_db::Entity::find()
351    ///         .select_only()
352    ///         .column(test_db::Column::Id)
353    ///         .filter(query::condition().lte(test_db::Column::Id, 1).build())
354    ///         .build(sea_orm::DatabaseBackend::Postgres)
355    ///         .to_string();
356    ///
357    ///     assert_eq!(
358    ///         query_str,
359    ///         "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" <= 1"
360    ///     );
361    /// ````
362    #[must_use]
363    pub fn lte<T: ColumnTrait, V: Into<Value>>(self, col: T, value: V) -> Self {
364        with(self.condition.add(col.lte(value)))
365    }
366
367    /// where condition the given column between the given values
368    /// value
369    ///
370    /// # Examples
371    /// ```
372    /// use loco_rs::tests_cfg::db::test_db;
373    /// use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
374    /// use loco_rs::prelude::*;
375    ///
376    /// let query_str = test_db::Entity::find()
377    ///         .select_only()
378    ///         .column(test_db::Column::Id)
379    ///         .filter(query::condition().between(test_db::Column::Id, 1, 2).build())
380    ///         .build(sea_orm::DatabaseBackend::Postgres)
381    ///         .to_string();
382    ///
383    ///     assert_eq!(
384    ///         query_str,
385    ///         "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" BETWEEN 1 AND 2"
386    ///     );
387    /// ````
388    #[must_use]
389    pub fn between<T: ColumnTrait, V: Into<Value>>(self, col: T, a: V, b: V) -> Self {
390        with(self.condition.add(col.between(a, b)))
391    }
392
393    /// where condition the given column not between the given values
394    /// value
395    ///
396    /// # Examples
397    /// ```
398    /// use loco_rs::tests_cfg::db::test_db;
399    /// use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
400    /// use loco_rs::prelude::*;
401    ///
402    /// let query_str = test_db::Entity::find()
403    ///         .select_only()
404    ///         .column(test_db::Column::Id)
405    ///         .filter(query::condition().not_between(test_db::Column::Id, 1, 2).build())
406    ///         .build(sea_orm::DatabaseBackend::Postgres)
407    ///         .to_string();
408    ///
409    ///     assert_eq!(
410    ///         query_str,
411    ///         "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" NOT BETWEEN 1 AND 2"
412    ///     );
413    /// ````
414    #[must_use]
415    pub fn not_between<T: ColumnTrait, V: Into<Value>>(self, col: T, a: V, b: V) -> Self {
416        with(self.condition.add(col.not_between(a, b)))
417    }
418
419    /// where condition the given column like given values
420    /// value
421    ///
422    /// # Examples
423    /// ```
424    /// use loco_rs::tests_cfg::db::test_db;
425    /// use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
426    /// use loco_rs::prelude::*;
427    ///
428    /// let query_str = test_db::Entity::find()
429    ///         .select_only()
430    ///         .column(test_db::Column::Id)
431    ///         .filter(query::condition().like(test_db::Column::Name, "%lo").build())
432    ///         .build(sea_orm::DatabaseBackend::Postgres)
433    ///         .to_string();
434    ///
435    ///     assert_eq!(
436    ///         query_str,
437    ///         "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" LIKE '%lo'"
438    ///     );
439    /// ````
440    #[must_use]
441    pub fn like<T: ColumnTrait, V: Into<String>>(self, col: T, a: V) -> Self {
442        with(self.condition.add(col.like(a)))
443    }
444
445    /// where condition the given column not like given values
446    /// value
447    ///
448    /// # Examples
449    /// ```
450    /// use loco_rs::tests_cfg::db::test_db;
451    /// use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
452    /// use loco_rs::prelude::*;
453    ///
454    /// let query_str = test_db::Entity::find()
455    ///         .select_only()
456    ///         .column(test_db::Column::Id)
457    ///         .filter(query::condition().not_like(test_db::Column::Name, "%lo").build())
458    ///         .build(sea_orm::DatabaseBackend::Postgres)
459    ///         .to_string();
460    ///
461    ///     assert_eq!(
462    ///         query_str,
463    ///         "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" NOT LIKE '%lo'"
464    ///     );
465    /// ````
466    #[must_use]
467    pub fn not_like<T: ColumnTrait, V: Into<String>>(self, col: T, a: V) -> Self {
468        with(self.condition.add(col.not_like(a)))
469    }
470
471    /// where condition the given column start with given values
472    /// value
473    ///
474    /// # Examples
475    /// ```
476    /// use loco_rs::tests_cfg::db::test_db;
477    /// use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
478    /// use loco_rs::prelude::*;
479    ///
480    /// let query_str = test_db::Entity::find()
481    ///         .select_only()
482    ///         .column(test_db::Column::Id)
483    ///         .filter(query::condition().starts_with(test_db::Column::Name, "lo").build())
484    ///         .build(sea_orm::DatabaseBackend::Postgres)
485    ///         .to_string();
486    ///
487    ///     assert_eq!(
488    ///         query_str,
489    ///         "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" LIKE 'lo%'"
490    ///     );
491    /// ````
492    #[must_use]
493    pub fn starts_with<T: ColumnTrait, V: Into<String>>(self, col: T, a: V) -> Self {
494        with(self.condition.add(col.starts_with(a)))
495    }
496
497    /// where condition the given column end with given values
498    /// value
499    ///
500    /// # Examples
501    /// ```
502    /// use loco_rs::tests_cfg::db::test_db;
503    /// use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
504    /// use loco_rs::prelude::*;
505    ///
506    /// let query_str = test_db::Entity::find()
507    ///         .select_only()
508    ///         .column(test_db::Column::Id)
509    ///         .filter(query::condition().ends_with(test_db::Column::Name, "lo").build())
510    ///         .build(sea_orm::DatabaseBackend::Postgres)
511    ///         .to_string();
512    ///
513    ///     assert_eq!(
514    ///         query_str,
515    ///         "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" LIKE '%lo'"
516    ///     );
517    /// ````
518    #[must_use]
519    pub fn ends_with<T: ColumnTrait, V: Into<String>>(self, col: T, a: V) -> Self {
520        with(self.condition.add(col.ends_with(a)))
521    }
522
523    /// where condition the given column end with given values
524    /// value
525    ///
526    /// # Examples
527    /// ```
528    /// use loco_rs::tests_cfg::db::test_db;
529    /// use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
530    /// use loco_rs::prelude::*;
531    ///
532    /// let query_str = test_db::Entity::find()
533    ///         .select_only()
534    ///         .column(test_db::Column::Id)
535    ///         .filter(query::condition().contains(test_db::Column::Name, "lo").build())
536    ///         .build(sea_orm::DatabaseBackend::Postgres)
537    ///         .to_string();
538    ///
539    ///     assert_eq!(
540    ///         query_str,
541    ///         "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" LIKE '%lo%'"
542    ///     );
543    /// ````
544    #[must_use]
545    pub fn contains<T: ColumnTrait, V: Into<String>>(self, col: T, a: V) -> Self {
546        with(self.condition.add(col.contains(a)))
547    }
548
549    /// where condition the given column is null
550    /// value
551    ///
552    /// # Examples
553    /// ```
554    /// use loco_rs::tests_cfg::db::test_db;
555    /// use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
556    /// use loco_rs::prelude::*;
557    ///
558    /// let query_str = test_db::Entity::find()
559    ///         .select_only()
560    ///         .column(test_db::Column::Id)
561    ///         .filter(query::condition().is_null(test_db::Column::Name).build())
562    ///         .build(sea_orm::DatabaseBackend::Postgres)
563    ///         .to_string();
564    ///
565    ///     assert_eq!(
566    ///         query_str,
567    ///         "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" IS NULL"
568    ///     );
569    /// ````
570    #[must_use]
571    #[allow(clippy::wrong_self_convention)]
572    pub fn is_null<T: ColumnTrait>(self, col: T) -> Self {
573        with(self.condition.add(col.is_null()))
574    }
575
576    /// where condition the given column is not null
577    /// value
578    ///
579    /// # Examples
580    /// ```
581    /// use loco_rs::tests_cfg::db::test_db;
582    /// use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
583    /// use loco_rs::prelude::*;
584    ///
585    /// let query_str = test_db::Entity::find()
586    ///         .select_only()
587    ///         .column(test_db::Column::Id)
588    ///         .filter(query::condition().is_not_null(test_db::Column::Name).build())
589    ///         .build(sea_orm::DatabaseBackend::Postgres)
590    ///         .to_string();
591    ///
592    ///     assert_eq!(
593    ///         query_str,
594    ///         "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" IS NOT NULL"
595    ///     );
596    /// ````
597    #[must_use]
598    #[allow(clippy::wrong_self_convention)]
599    pub fn is_not_null<T: ColumnTrait>(self, col: T) -> Self {
600        with(self.condition.add(col.is_not_null()))
601    }
602
603    /// where condition the given column is in
604    /// value
605    ///
606    /// # Examples
607    /// ```
608    /// use loco_rs::tests_cfg::db::test_db;
609    /// use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
610    /// use loco_rs::prelude::*;
611    ///
612    /// let query_str = test_db::Entity::find()
613    ///         .select_only()
614    ///         .column(test_db::Column::Id)
615    ///         .filter(query::condition().is_in(test_db::Column::Id, [1]).build())
616    ///         .build(sea_orm::DatabaseBackend::Postgres)
617    ///         .to_string();
618    ///
619    ///     assert_eq!(
620    ///         query_str,
621    ///         "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" IN (1)"
622    ///     );
623    /// ````
624    #[must_use]
625    #[allow(clippy::wrong_self_convention)]
626    pub fn is_in<T: ColumnTrait, V: Into<Value>, I: IntoIterator<Item = V>>(
627        self,
628        col: T,
629        values: I,
630    ) -> Self {
631        with(self.condition.add(col.is_in(values)))
632    }
633
634    /// where condition the given column is not in
635    /// value
636    ///
637    /// # Examples
638    /// ```
639    /// use loco_rs::tests_cfg::db::test_db;
640    /// use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
641    /// use loco_rs::prelude::*;
642    ///
643    /// let query_str = test_db::Entity::find()
644    ///         .select_only()
645    ///         .column(test_db::Column::Id)
646    ///         .filter(query::condition().is_not_in(test_db::Column::Id, [1]).build())
647    ///         .build(sea_orm::DatabaseBackend::Postgres)
648    ///         .to_string();
649    ///
650    ///     assert_eq!(
651    ///         query_str,
652    ///         "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" NOT IN (1)"
653    ///     );
654    /// ````
655    #[must_use]
656    #[allow(clippy::wrong_self_convention)]
657    pub fn is_not_in<T: ColumnTrait, V: Into<Value>, I: IntoIterator<Item = V>>(
658        self,
659        col: T,
660        values: I,
661    ) -> Self {
662        with(self.condition.add(col.is_not_in(values)))
663    }
664
665    /// where condition the given column is not null
666    /// value
667    ///
668    /// # Examples
669    /// ```
670    /// use loco_rs::tests_cfg::db::test_db;
671    /// use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
672    /// use loco_rs::prelude::*;
673    ///
674    /// let from_date = chrono::NaiveDateTime::parse_from_str("2024-03-01
675    /// 22:10:57", "%Y-%m-%d %H:%M:%S").unwrap(); let to_date =
676    /// chrono::NaiveDateTime::parse_from_str("2024-03-25 22:10:57", "%Y-%m-%d
677    /// %H:%M:%S").unwrap();
678    ///
679    /// let condition = query::condition()
680    ///     .date_range(test_db::Column::CreatedAt)
681    ///     .dates(Some(&from_date), Some(&to_date))
682    ///     .build();
683    ///
684    /// let query_str = test_db::Entity::find()
685    ///     .select_only()
686    ///     .column(test_db::Column::Id)
687    ///     .filter(condition.build())
688    ///     .build(sea_orm::DatabaseBackend::Postgres)
689    ///     .to_string();
690    ///
691    /// assert_eq!(
692    ///     query_str,
693    ///     "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"created_at\" BETWEEN '2024-03-01 22:10:57' AND '2024-03-25 22:10:57'" );
694    /// ````
695    #[must_use]
696    pub fn date_range<T: ColumnTrait>(self, col: T) -> date_range::DateRangeBuilder<T> {
697        date_range::DateRangeBuilder::new(self, col)
698    }
699
700    #[must_use]
701    pub fn build(&self) -> Condition {
702        self.condition.clone().into_condition()
703    }
704}
705
706#[cfg(test)]
707mod tests {
708
709    use sea_orm::{EntityTrait, QueryFilter, QuerySelect, QueryTrait};
710
711    use super::*;
712    use crate::tests_cfg::db::*;
713
714    #[test]
715    fn condition_eq() {
716        let query_str = test_db::Entity::find()
717            .select_only()
718            .column(test_db::Column::Id)
719            .filter(condition().eq(test_db::Column::Id, 1).build())
720            .build(sea_orm::DatabaseBackend::Postgres)
721            .to_string();
722
723        assert_eq!(
724            query_str,
725            "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" = 1"
726        );
727    }
728
729    #[test]
730    fn condition_ne() {
731        let query_str = test_db::Entity::find()
732            .select_only()
733            .column(test_db::Column::Id)
734            .filter(condition().ne(test_db::Column::Name, "loco").build())
735            .build(sea_orm::DatabaseBackend::Postgres)
736            .to_string();
737
738        assert_eq!(
739            query_str,
740            "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" <> 'loco'"
741        );
742    }
743
744    #[test]
745    fn condition_gt() {
746        let query_str = test_db::Entity::find()
747            .select_only()
748            .column(test_db::Column::Id)
749            .filter(condition().gt(test_db::Column::Id, 1).build())
750            .build(sea_orm::DatabaseBackend::Postgres)
751            .to_string();
752
753        assert_eq!(
754            query_str,
755            "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" > 1"
756        );
757    }
758
759    #[test]
760    fn condition_gte() {
761        let query_str = test_db::Entity::find()
762            .select_only()
763            .column(test_db::Column::Id)
764            .filter(condition().gte(test_db::Column::Id, 1).build())
765            .build(sea_orm::DatabaseBackend::Postgres)
766            .to_string();
767
768        assert_eq!(
769            query_str,
770            "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" >= 1"
771        );
772    }
773
774    #[test]
775    fn condition_lt() {
776        let query_str = test_db::Entity::find()
777            .select_only()
778            .column(test_db::Column::Id)
779            .filter(condition().lt(test_db::Column::Id, 1).build())
780            .build(sea_orm::DatabaseBackend::Postgres)
781            .to_string();
782
783        assert_eq!(
784            query_str,
785            "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" < 1"
786        );
787    }
788
789    #[test]
790    fn condition_lte() {
791        let query_str = test_db::Entity::find()
792            .select_only()
793            .column(test_db::Column::Id)
794            .filter(condition().lte(test_db::Column::Id, 1).build())
795            .build(sea_orm::DatabaseBackend::Postgres)
796            .to_string();
797
798        assert_eq!(
799            query_str,
800            "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" <= 1"
801        );
802    }
803
804    #[test]
805    fn condition_between() {
806        let query_str = test_db::Entity::find()
807            .select_only()
808            .column(test_db::Column::Id)
809            .filter(condition().between(test_db::Column::Id, 1, 2).build())
810            .build(sea_orm::DatabaseBackend::Postgres)
811            .to_string();
812
813        assert_eq!(
814            query_str,
815            "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" BETWEEN 1 AND 2"
816        );
817    }
818
819    #[test]
820    fn condition_not_between() {
821        let query_str = test_db::Entity::find()
822            .select_only()
823            .column(test_db::Column::Id)
824            .filter(condition().not_between(test_db::Column::Id, 1, 2).build())
825            .build(sea_orm::DatabaseBackend::Postgres)
826            .to_string();
827
828        assert_eq!(
829            query_str,
830            "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" NOT BETWEEN 1 AND 2"
831        );
832    }
833
834    #[test]
835    fn condition_like() {
836        let query_str = test_db::Entity::find()
837            .select_only()
838            .column(test_db::Column::Id)
839            .filter(condition().like(test_db::Column::Name, "%lo").build())
840            .build(sea_orm::DatabaseBackend::Postgres)
841            .to_string();
842
843        assert_eq!(
844            query_str,
845            "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" LIKE '%lo'"
846        );
847    }
848
849    #[test]
850    fn condition_not_like() {
851        let query_str = test_db::Entity::find()
852            .select_only()
853            .column(test_db::Column::Id)
854            .filter(condition().not_like(test_db::Column::Name, "%lo%").build())
855            .build(sea_orm::DatabaseBackend::Postgres)
856            .to_string();
857
858        assert_eq!(
859            query_str,
860            "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" NOT LIKE '%lo%'"
861        );
862    }
863
864    #[test]
865    fn condition_starts_with() {
866        let query_str = test_db::Entity::find()
867            .select_only()
868            .column(test_db::Column::Id)
869            .filter(condition().starts_with(test_db::Column::Name, "lo").build())
870            .build(sea_orm::DatabaseBackend::Postgres)
871            .to_string();
872
873        assert_eq!(
874            query_str,
875            "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" LIKE 'lo%'"
876        );
877    }
878
879    #[test]
880    fn condition_ends_with() {
881        let query_str = test_db::Entity::find()
882            .select_only()
883            .column(test_db::Column::Id)
884            .filter(condition().ends_with(test_db::Column::Name, "lo").build())
885            .build(sea_orm::DatabaseBackend::Postgres)
886            .to_string();
887
888        assert_eq!(
889            query_str,
890            "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" LIKE '%lo'"
891        );
892    }
893
894    #[test]
895    fn condition_contains() {
896        let query_str = test_db::Entity::find()
897            .select_only()
898            .column(test_db::Column::Id)
899            .filter(condition().contains(test_db::Column::Name, "lo").build())
900            .build(sea_orm::DatabaseBackend::Postgres)
901            .to_string();
902
903        assert_eq!(
904            query_str,
905            "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" LIKE '%lo%'"
906        );
907    }
908
909    #[test]
910    fn condition_is_null() {
911        let query_str = test_db::Entity::find()
912            .select_only()
913            .column(test_db::Column::Id)
914            .filter(condition().is_null(test_db::Column::Name).build())
915            .build(sea_orm::DatabaseBackend::Postgres)
916            .to_string();
917
918        assert_eq!(
919            query_str,
920            "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" IS NULL"
921        );
922    }
923
924    #[test]
925    fn condition_is_not_null() {
926        let query_str = test_db::Entity::find()
927            .select_only()
928            .column(test_db::Column::Id)
929            .filter(condition().is_not_null(test_db::Column::Name).build())
930            .build(sea_orm::DatabaseBackend::Postgres)
931            .to_string();
932
933        assert_eq!(
934            query_str,
935            "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"name\" IS NOT NULL"
936        );
937    }
938
939    #[test]
940    fn condition_is_in() {
941        let query_str = test_db::Entity::find()
942            .select_only()
943            .column(test_db::Column::Id)
944            .filter(condition().is_in(test_db::Column::Id, [1]).build())
945            .build(sea_orm::DatabaseBackend::Postgres)
946            .to_string();
947
948        assert_eq!(
949            query_str,
950            "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" IN (1)"
951        );
952    }
953
954    #[test]
955    fn condition_is_not_in() {
956        let query_str = test_db::Entity::find()
957            .select_only()
958            .column(test_db::Column::Id)
959            .filter(condition().is_not_in(test_db::Column::Id, [1]).build())
960            .build(sea_orm::DatabaseBackend::Postgres)
961            .to_string();
962
963        assert_eq!(
964            query_str,
965            "SELECT \"loco\".\"id\" FROM \"loco\" WHERE \"loco\".\"id\" NOT IN (1)"
966        );
967    }
968}