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}