1use crate::DeleteBuilder;
3use crate::cond::Cond;
4use crate::flavor::{Flavor, default_flavor};
5use crate::modifiers::{Arg, Builder};
6use crate::select::{JoinOption, SelectBuilder};
7use crate::update::UpdateBuilder;
8use crate::value::SqlValue;
9use crate::where_clause::{WhereClause, WhereClauseRef};
10use std::collections::HashMap;
11use std::sync::Arc;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum Operator {
16 Equal,
17 NotEqual,
18 IsNull,
19 IsNotNull,
20 GreaterThan,
21 LessThan,
22 GreaterEqualThan,
23 LessEqualThan,
24 In,
25 NotIn,
26 Like,
27 NotLike,
28 Limit,
29 Offset,
30 Between,
31 NotBetween,
32 OrderBy,
33 OrderByDesc,
34 OrderByAsc,
35 GroupBy,
36 Join,
37}
38
39#[derive(Debug, Clone)]
41pub enum ConditionValue {
42 Single(Arg),
43 List(Vec<Arg>),
44}
45
46impl ConditionValue {
47 pub fn to_vec(&self) -> Vec<Arg> {
48 match self {
49 Self::Single(v) => vec![v.clone()],
50 Self::List(v) => v.clone(),
51 }
52 }
53
54 pub fn first(&self) -> Option<Arg> {
55 match self {
56 Self::Single(v) => Some(v.clone()),
57 Self::List(v) => v.first().cloned(),
58 }
59 }
60
61 pub fn pair(&self) -> Option<(Arg, Arg)> {
62 match self {
63 Self::Single(_) => None,
64 Self::List(v) if v.len() >= 2 => Some((v[0].clone(), v[1].clone())),
65 _ => None,
66 }
67 }
68
69 pub fn is_empty(&self) -> bool {
70 matches!(self, Self::List(v) if v.is_empty())
71 }
72}
73
74impl Default for ConditionValue {
75 fn default() -> Self {
76 Self::Single(SqlValue::Null.into())
77 }
78}
79
80impl<T: Into<Arg>> From<T> for ConditionValue {
81 fn from(v: T) -> Self {
82 Self::Single(v.into())
83 }
84}
85
86impl<T: Into<Arg>> From<Vec<T>> for ConditionValue {
87 fn from(v: Vec<T>) -> Self {
88 Self::List(v.into_iter().map(Into::into).collect())
89 }
90}
91
92impl<T: Into<Arg>, const N: usize> From<[T; N]> for ConditionValue {
93 fn from(v: [T; N]) -> Self {
94 Self::List(v.into_iter().map(Into::into).collect())
95 }
96}
97
98impl<T: Into<Arg>> From<HashMap<String, T>> for ConditionValue {
99 fn from(v: HashMap<String, T>) -> Self {
100 Self::List(v.into_values().map(Into::into).collect())
101 }
102}
103
104#[derive(Clone, Default)]
106pub struct ChainOptions {
107 pub skip: bool,
108 pub skip_fn: Option<Arc<dyn Fn() -> bool + Send + Sync>>,
109 pub value_fn: Option<Arc<dyn Fn() -> ConditionValue + Send + Sync>>,
110 pub or_values_fn: Option<Arc<dyn Fn() -> Vec<ConditionValue> + Send + Sync>>,
111}
112
113impl ChainOptions {
114 pub fn skip(mut self, skip: bool) -> Self {
115 self.skip = skip;
116 self
117 }
118
119 pub fn skip_fn(mut self, f: impl Fn() -> bool + Send + Sync + 'static) -> Self {
120 self.skip_fn = Some(Arc::new(f));
121 self
122 }
123
124 pub fn value_fn(mut self, f: impl Fn() -> ConditionValue + Send + Sync + 'static) -> Self {
125 self.value_fn = Some(Arc::new(f));
126 self
127 }
128
129 pub fn or_values_fn(
130 mut self,
131 f: impl Fn() -> Vec<ConditionValue> + Send + Sync + 'static,
132 ) -> Self {
133 self.or_values_fn = Some(Arc::new(f));
134 self
135 }
136}
137
138impl std::fmt::Debug for ChainOptions {
139 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
140 f.debug_struct("ChainOptions")
141 .field("skip", &self.skip)
142 .field("has_skip_fn", &self.skip_fn.is_some())
143 .field("has_value_fn", &self.value_fn.is_some())
144 .field("has_or_values_fn", &self.or_values_fn.is_some())
145 .finish()
146 }
147}
148
149#[derive(Debug, Clone)]
151pub struct JoinCondition {
152 pub option: Option<JoinOption>,
153 pub table: String,
154 pub on_expr: Vec<String>,
155}
156
157#[derive(Clone)]
159pub struct Condition {
160 pub skip: bool,
161 pub skip_fn: Option<Arc<dyn Fn() -> bool + Send + Sync>>,
162 pub or: bool,
163 pub or_operators: Vec<Operator>,
164 pub or_fields: Vec<String>,
165 pub or_values: Vec<ConditionValue>,
166 pub or_values_fn: Option<Arc<dyn Fn() -> Vec<ConditionValue> + Send + Sync>>,
167 pub field: String,
168 pub operator: Operator,
169 pub value: ConditionValue,
170 pub value_fn: Option<Arc<dyn Fn() -> ConditionValue + Send + Sync>>,
171 pub join: Option<JoinCondition>,
172 pub where_clause: Option<WhereClauseRef>,
173}
174
175impl Condition {
176 pub fn new(
177 field: impl Into<String>,
178 operator: Operator,
179 value: impl Into<ConditionValue>,
180 ) -> Self {
181 Self {
182 skip: false,
183 skip_fn: None,
184 or: false,
185 or_operators: Vec::new(),
186 or_fields: Vec::new(),
187 or_values: Vec::new(),
188 or_values_fn: None,
189 field: field.into(),
190 operator,
191 value: value.into(),
192 value_fn: None,
193 join: None,
194 where_clause: None,
195 }
196 }
197}
198
199impl std::fmt::Debug for Condition {
200 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
201 f.debug_struct("Condition")
202 .field("skip", &self.skip)
203 .field("or", &self.or)
204 .field("field", &self.field)
205 .field("operator", &self.operator)
206 .field("value", &self.value)
207 .field("or_fields", &self.or_fields)
208 .field("or_operators", &self.or_operators)
209 .field("join", &self.join)
210 .field("has_skip_fn", &self.skip_fn.is_some())
211 .field("has_value_fn", &self.value_fn.is_some())
212 .field("has_or_values_fn", &self.or_values_fn.is_some())
213 .field("has_where_clause", &self.where_clause.is_some())
214 .finish()
215 }
216}
217
218#[derive(Debug, Default, Clone)]
220pub struct Chain {
221 conditions: Vec<Condition>,
222}
223
224impl Chain {
225 pub fn new() -> Self {
226 Self::default()
227 }
228
229 fn map_last(mut self, f: impl FnOnce(&mut Condition)) -> Self {
231 if let Some(last) = self.conditions.last_mut() {
232 f(last);
233 }
234 self
235 }
236
237 pub fn add_condition(mut self, condition: Condition) -> Self {
238 self.conditions.push(condition);
239 self
240 }
241
242 fn add_chain(
243 mut self,
244 field: impl Into<String>,
245 operator: Operator,
246 value: impl Into<ConditionValue>,
247 opts: ChainOptions,
248 ) -> Self {
249 self.conditions.push(Condition {
250 skip: opts.skip,
251 skip_fn: opts.skip_fn,
252 or: false,
253 or_operators: Vec::new(),
254 or_fields: Vec::new(),
255 or_values: Vec::new(),
256 or_values_fn: None,
257 field: field.into(),
258 operator,
259 value: value.into(),
260 value_fn: opts.value_fn,
261 join: None,
262 where_clause: None,
263 });
264 self
265 }
266
267 pub fn equal(self, field: impl Into<String>, value: impl Into<ConditionValue>) -> Self {
268 self.add_chain(field, Operator::Equal, value, ChainOptions::default())
269 }
270
271 pub fn value_fn(self, f: impl Fn() -> ConditionValue + Send + Sync + 'static) -> Self {
273 self.map_last(|c| c.value_fn = Some(Arc::new(f)))
274 }
275
276 pub fn skip(self, skip: bool) -> Self {
278 self.map_last(|c| c.skip = skip)
279 }
280
281 pub fn skip_fn(self, f: impl Fn() -> bool + Send + Sync + 'static) -> Self {
283 self.map_last(|c| c.skip_fn = Some(Arc::new(f)))
284 }
285
286 pub fn equal_opts(
287 self,
288 field: impl Into<String>,
289 value: impl Into<ConditionValue>,
290 opts: ChainOptions,
291 ) -> Self {
292 self.add_chain(field, Operator::Equal, value, opts)
293 }
294
295 pub fn not_equal(self, field: impl Into<String>, value: impl Into<ConditionValue>) -> Self {
296 self.add_chain(field, Operator::NotEqual, value, ChainOptions::default())
297 }
298
299 pub fn is_null(self, field: impl Into<String>) -> Self {
300 self.add_chain(
301 field,
302 Operator::IsNull,
303 ConditionValue::default(),
304 ChainOptions::default(),
305 )
306 }
307
308 pub fn is_not_null(self, field: impl Into<String>) -> Self {
309 self.add_chain(
310 field,
311 Operator::IsNotNull,
312 ConditionValue::default(),
313 ChainOptions::default(),
314 )
315 }
316
317 pub fn greater_than(self, field: impl Into<String>, value: impl Into<ConditionValue>) -> Self {
318 self.add_chain(field, Operator::GreaterThan, value, ChainOptions::default())
319 }
320
321 pub fn less_than(self, field: impl Into<String>, value: impl Into<ConditionValue>) -> Self {
322 self.add_chain(field, Operator::LessThan, value, ChainOptions::default())
323 }
324
325 pub fn greater_equal_than(
326 self,
327 field: impl Into<String>,
328 value: impl Into<ConditionValue>,
329 ) -> Self {
330 self.add_chain(
331 field,
332 Operator::GreaterEqualThan,
333 value,
334 ChainOptions::default(),
335 )
336 }
337
338 pub fn less_equal_than(
339 self,
340 field: impl Into<String>,
341 value: impl Into<ConditionValue>,
342 ) -> Self {
343 self.add_chain(
344 field,
345 Operator::LessEqualThan,
346 value,
347 ChainOptions::default(),
348 )
349 }
350
351 pub fn like(self, field: impl Into<String>, value: impl Into<ConditionValue>) -> Self {
352 self.add_chain(field, Operator::Like, value, ChainOptions::default())
353 }
354
355 pub fn not_like(self, field: impl Into<String>, value: impl Into<ConditionValue>) -> Self {
356 self.add_chain(field, Operator::NotLike, value, ChainOptions::default())
357 }
358
359 pub fn between(self, field: impl Into<String>, value: impl Into<ConditionValue>) -> Self {
360 self.add_chain(field, Operator::Between, value, ChainOptions::default())
361 }
362
363 pub fn in_(self, field: impl Into<String>, value: impl Into<ConditionValue>) -> Self {
364 self.add_chain(field, Operator::In, value, ChainOptions::default())
365 }
366
367 pub fn not_in(self, field: impl Into<String>, value: impl Into<ConditionValue>) -> Self {
368 self.add_chain(field, Operator::NotIn, value, ChainOptions::default())
369 }
370
371 pub fn or(
372 mut self,
373 fields: impl IntoIterator<Item = impl Into<String>>,
374 operators: impl IntoIterator<Item = Operator>,
375 values: impl IntoIterator<Item = impl Into<ConditionValue>>,
376 opts: ChainOptions,
377 ) -> Self {
378 let mut cond = Condition {
379 skip: opts.skip,
380 skip_fn: opts.skip_fn,
381 or: true,
382 or_operators: operators.into_iter().collect(),
383 or_fields: fields.into_iter().map(Into::into).collect(),
384 or_values: values.into_iter().map(Into::into).collect(),
385 or_values_fn: opts.or_values_fn,
386 field: String::new(),
387 operator: Operator::Equal,
388 value: ConditionValue::default(),
389 value_fn: None,
390 join: None,
391 where_clause: None,
392 };
393
394 if let Some(f) = opts.value_fn {
395 cond.value_fn = Some(f);
396 }
397
398 self.conditions.push(cond);
399 self
400 }
401
402 pub fn order_by(self, value: impl Into<ConditionValue>) -> Self {
403 self.add_chain("", Operator::OrderBy, value, ChainOptions::default())
404 }
405
406 pub fn order_by_desc(self, field: impl Into<String>) -> Self {
407 self.add_chain(
408 field,
409 Operator::OrderByDesc,
410 ConditionValue::default(),
411 ChainOptions::default(),
412 )
413 }
414
415 pub fn order_by_asc(self, field: impl Into<String>) -> Self {
416 self.add_chain(
417 field,
418 Operator::OrderByAsc,
419 ConditionValue::default(),
420 ChainOptions::default(),
421 )
422 }
423
424 pub fn limit(self, value: impl Into<ConditionValue>) -> Self {
425 self.add_chain("", Operator::Limit, value, ChainOptions::default())
426 }
427
428 pub fn offset(self, value: impl Into<ConditionValue>) -> Self {
429 self.add_chain("", Operator::Offset, value, ChainOptions::default())
430 }
431
432 pub fn page(self, page: i64, page_size: i64) -> Self {
433 let offset = (page - 1) * page_size;
434 self.offset(offset).limit(page_size)
435 }
436
437 pub fn group_by(self, field: impl Into<String>) -> Self {
438 self.add_chain(
439 field,
440 Operator::GroupBy,
441 ConditionValue::default(),
442 ChainOptions::default(),
443 )
444 }
445
446 pub fn join(
447 mut self,
448 option: JoinOption,
449 table: impl Into<String>,
450 on_expr: impl IntoIterator<Item = impl Into<String>>,
451 ) -> Self {
452 self.conditions.push(Condition {
453 skip: false,
454 skip_fn: None,
455 or: false,
456 or_operators: Vec::new(),
457 or_fields: Vec::new(),
458 or_values: Vec::new(),
459 or_values_fn: None,
460 field: String::new(),
461 operator: Operator::Join,
462 value: ConditionValue::default(),
463 value_fn: None,
464 join: Some(JoinCondition {
465 option: Some(option),
466 table: table.into(),
467 on_expr: on_expr.into_iter().map(Into::into).collect(),
468 }),
469 where_clause: None,
470 });
471 self
472 }
473
474 pub fn where_clause(mut self, wc: WhereClauseRef) -> Self {
475 self.conditions.push(Condition {
476 skip: false,
477 skip_fn: None,
478 or: false,
479 or_operators: Vec::new(),
480 or_fields: Vec::new(),
481 or_values: Vec::new(),
482 or_values_fn: None,
483 field: String::new(),
484 operator: Operator::Equal,
485 value: ConditionValue::default(),
486 value_fn: None,
487 join: None,
488 where_clause: Some(wc),
489 });
490 self
491 }
492
493 pub fn build(self) -> Vec<Condition> {
494 self.conditions
495 }
496}
497
498#[derive(Debug, Clone, Copy, PartialEq, Eq)]
500pub enum UpdateFieldOperator {
501 Incr,
502 Decr,
503 Assign,
504 Add,
505 Sub,
506 Mul,
507 Div,
508}
509
510#[derive(Clone, Default)]
512pub struct UpdateFieldOptions {
513 pub skip: bool,
514 pub skip_fn: Option<Arc<dyn Fn() -> bool + Send + Sync>>,
515 pub value_fn: Option<Arc<dyn Fn() -> Arg + Send + Sync>>,
516}
517
518impl UpdateFieldOptions {
519 pub fn skip(mut self, skip: bool) -> Self {
520 self.skip = skip;
521 self
522 }
523
524 pub fn skip_fn(mut self, f: impl Fn() -> bool + Send + Sync + 'static) -> Self {
525 self.skip_fn = Some(Arc::new(f));
526 self
527 }
528
529 pub fn value_fn(mut self, f: impl Fn() -> Arg + Send + Sync + 'static) -> Self {
530 self.value_fn = Some(Arc::new(f));
531 self
532 }
533}
534
535impl std::fmt::Debug for UpdateFieldOptions {
536 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
537 f.debug_struct("UpdateFieldOptions")
538 .field("skip", &self.skip)
539 .field("has_skip_fn", &self.skip_fn.is_some())
540 .field("has_value_fn", &self.value_fn.is_some())
541 .finish()
542 }
543}
544
545#[derive(Clone)]
547pub struct UpdateField {
548 pub skip: bool,
549 pub skip_fn: Option<Arc<dyn Fn() -> bool + Send + Sync>>,
550 pub field: String,
551 pub operator: UpdateFieldOperator,
552 pub value: Option<Arg>,
553 pub value_fn: Option<Arc<dyn Fn() -> Arg + Send + Sync>>,
554}
555
556impl UpdateField {
557 pub fn new(
558 field: impl Into<String>,
559 operator: UpdateFieldOperator,
560 value: Option<Arg>,
561 opts: UpdateFieldOptions,
562 ) -> Self {
563 Self {
564 skip: opts.skip,
565 skip_fn: opts.skip_fn,
566 field: field.into(),
567 operator,
568 value,
569 value_fn: opts.value_fn,
570 }
571 }
572}
573
574impl std::fmt::Debug for UpdateField {
575 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
576 f.debug_struct("UpdateField")
577 .field("skip", &self.skip)
578 .field("field", &self.field)
579 .field("operator", &self.operator)
580 .field("value", &self.value)
581 .field("has_skip_fn", &self.skip_fn.is_some())
582 .field("has_value_fn", &self.value_fn.is_some())
583 .finish()
584 }
585}
586
587#[derive(Debug, Default, Clone)]
589pub struct UpdateFieldChain {
590 fields: Vec<UpdateField>,
591}
592
593impl UpdateFieldChain {
594 pub fn new() -> Self {
595 Self::default()
596 }
597
598 pub fn assign(
599 mut self,
600 field: impl Into<String>,
601 value: impl Into<Arg>,
602 opts: UpdateFieldOptions,
603 ) -> Self {
604 self.fields.push(UpdateField::new(
605 field,
606 UpdateFieldOperator::Assign,
607 Some(value.into()),
608 opts,
609 ));
610 self
611 }
612
613 pub fn incr(mut self, field: impl Into<String>, opts: UpdateFieldOptions) -> Self {
614 self.fields.push(UpdateField::new(
615 field,
616 UpdateFieldOperator::Incr,
617 None,
618 opts,
619 ));
620 self
621 }
622
623 pub fn decr(mut self, field: impl Into<String>, opts: UpdateFieldOptions) -> Self {
624 self.fields.push(UpdateField::new(
625 field,
626 UpdateFieldOperator::Decr,
627 None,
628 opts,
629 ));
630 self
631 }
632
633 pub fn add(
634 mut self,
635 field: impl Into<String>,
636 value: impl Into<Arg>,
637 opts: UpdateFieldOptions,
638 ) -> Self {
639 self.fields.push(UpdateField::new(
640 field,
641 UpdateFieldOperator::Add,
642 Some(value.into()),
643 opts,
644 ));
645 self
646 }
647
648 pub fn sub(
649 mut self,
650 field: impl Into<String>,
651 value: impl Into<Arg>,
652 opts: UpdateFieldOptions,
653 ) -> Self {
654 self.fields.push(UpdateField::new(
655 field,
656 UpdateFieldOperator::Sub,
657 Some(value.into()),
658 opts,
659 ));
660 self
661 }
662
663 pub fn mul(
664 mut self,
665 field: impl Into<String>,
666 value: impl Into<Arg>,
667 opts: UpdateFieldOptions,
668 ) -> Self {
669 self.fields.push(UpdateField::new(
670 field,
671 UpdateFieldOperator::Mul,
672 Some(value.into()),
673 opts,
674 ));
675 self
676 }
677
678 pub fn div(
679 mut self,
680 field: impl Into<String>,
681 value: impl Into<Arg>,
682 opts: UpdateFieldOptions,
683 ) -> Self {
684 self.fields.push(UpdateField::new(
685 field,
686 UpdateFieldOperator::Div,
687 Some(value.into()),
688 opts,
689 ));
690 self
691 }
692
693 pub fn build(self) -> Vec<(String, UpdateValue)> {
694 let mut out = Vec::new();
695 for mut field in self.fields {
696 if let Some(f) = &field.skip_fn {
697 if f() {
698 continue;
699 }
700 } else if field.skip {
701 continue;
702 }
703 if let Some(f) = &field.value_fn {
704 field.value = Some(f());
705 }
706 out.push((field.field.clone(), UpdateValue::from(field)));
707 }
708 out
709 }
710}
711
712#[derive(Debug, Clone)]
714pub enum UpdateValue {
715 Field(UpdateField),
716 Value(Arg),
717}
718
719impl From<UpdateField> for UpdateValue {
720 fn from(v: UpdateField) -> Self {
721 Self::Field(v)
722 }
723}
724
725impl<T: Into<Arg>> From<T> for UpdateValue {
726 fn from(v: T) -> Self {
727 Self::Value(v.into())
728 }
729}
730
731pub fn to_field_slice(fields: Vec<String>) -> Vec<String> {
733 fields
734}
735
736pub fn unquote(s: &str) -> String {
738 let mut out = s.trim();
739 if out.starts_with('`') || out.starts_with('"') {
740 out = &out[1..];
741 }
742 if out.ends_with('`') || out.ends_with('"') {
743 out = &out[..out.len() - 1];
744 }
745 out.to_string()
746}
747
748pub fn quote_with_flavor(flavor: Flavor, s: &str) -> String {
750 let parts: Vec<String> = s
751 .split('.')
752 .filter(|p| !p.is_empty())
753 .map(|p| flavor.quote(&unquote(p)))
754 .collect();
755 parts.join(".")
756}
757
758fn should_skip(cond: &Condition) -> bool {
759 if let Some(f) = &cond.skip_fn {
760 return f();
761 }
762 cond.skip
763}
764
765fn materialize_value(cond: &Condition) -> ConditionValue {
766 if let Some(f) = &cond.value_fn {
767 f()
768 } else {
769 cond.value.clone()
770 }
771}
772
773fn materialize_or_values(cond: &Condition) -> Vec<ConditionValue> {
774 if let Some(f) = &cond.or_values_fn {
775 f()
776 } else {
777 cond.or_values.clone()
778 }
779}
780
781fn arg_to_string(arg: &Arg) -> Option<String> {
782 match arg {
783 Arg::Value(SqlValue::String(s)) => Some(s.to_string()),
784 Arg::Value(SqlValue::I64(v)) => Some(v.to_string()),
785 Arg::Value(SqlValue::U64(v)) => Some(v.to_string()),
786 Arg::Value(SqlValue::F64(v)) => Some(v.to_string()),
787 Arg::Value(SqlValue::Bool(v)) => Some(v.to_string()),
788 Arg::SqlNamed(v) => Some(format!("@{}", v.name)),
789 Arg::Raw(v) => Some(v.expr.clone()),
790 _ => None,
791 }
792}
793
794fn value_to_strings(value: &ConditionValue) -> Vec<String> {
795 match value {
796 ConditionValue::Single(v) => arg_to_string(v).into_iter().collect(),
797 ConditionValue::List(vs) => vs.iter().filter_map(arg_to_string).collect(),
798 }
799}
800
801fn value_to_i64(value: &ConditionValue) -> Option<i64> {
802 match value {
803 ConditionValue::Single(Arg::Value(SqlValue::I64(v))) => Some(*v),
804 ConditionValue::Single(Arg::Value(SqlValue::U64(v))) => Some(*v as i64),
805 ConditionValue::Single(Arg::Value(SqlValue::F64(v))) => Some(*v as i64),
806 ConditionValue::Single(Arg::Value(SqlValue::Bool(v))) => Some(if *v { 1 } else { 0 }),
807 ConditionValue::Single(Arg::Value(SqlValue::Null)) => Some(0),
808 _ => None,
809 }
810}
811
812fn build_expr(
813 flavor: Flavor,
814 cond: &Cond,
815 field: &str,
816 operator: Operator,
817 value: &ConditionValue,
818) -> Option<String> {
819 let quoted_field = quote_with_flavor(flavor, field);
820 match operator {
821 Operator::Equal => value.first().map(|v| cond.equal("ed_field, v)),
822 Operator::NotEqual => value.first().map(|v| cond.not_equal("ed_field, v)),
823 Operator::GreaterThan => value.first().map(|v| cond.greater_than("ed_field, v)),
824 Operator::LessThan => value.first().map(|v| cond.less_than("ed_field, v)),
825 Operator::GreaterEqualThan => value
826 .first()
827 .map(|v| cond.greater_equal_than("ed_field, v)),
828 Operator::LessEqualThan => value
829 .first()
830 .map(|v| cond.less_equal_than("ed_field, v)),
831 Operator::Like => value.first().map(|v| cond.like("ed_field, v)),
832 Operator::NotLike => value.first().map(|v| cond.not_like("ed_field, v)),
833 Operator::IsNull => Some(cond.is_null("ed_field)),
834 Operator::IsNotNull => Some(cond.is_not_null("ed_field)),
835 Operator::Between => value.pair().map(|(l, r)| cond.between("ed_field, l, r)),
836 Operator::NotBetween => value
837 .pair()
838 .map(|(l, r)| cond.not_between("ed_field, l, r)),
839 Operator::In => {
840 let vals = value.to_vec();
841 if vals.is_empty() {
842 let ph = cond.var(SqlValue::Null);
843 Some(format!("{quoted_field} IN ({ph})"))
844 } else {
845 let phs: Vec<String> = vals.into_iter().map(|v| cond.var(v)).collect();
846 Some(format!("{quoted_field} IN ({})", phs.join(", ")))
847 }
848 }
849 Operator::NotIn => {
850 let vals = value.to_vec();
851 if vals.is_empty() {
852 let ph = cond.var(SqlValue::Null);
853 Some(format!("{quoted_field} NOT IN ({ph})"))
854 } else {
855 let phs: Vec<String> = vals.into_iter().map(|v| cond.var(v)).collect();
856 Some(format!("{quoted_field} NOT IN ({})", phs.join(", ")))
857 }
858 }
859 _ => None,
860 }
861}
862
863fn build_where_clause(flavor: Flavor, conditions: &[Condition]) -> Option<WhereClauseRef> {
864 if conditions.is_empty() {
865 return None;
866 }
867 let wc = WhereClause::new();
868 let cond_builder = Cond::new();
869 let mut has_expr = false;
870
871 for c in conditions {
872 if should_skip(c) {
873 continue;
874 }
875 if let Some(w) = &c.where_clause {
876 wc.borrow_mut().add_where_clause(&w.borrow());
877 has_expr = true;
878 continue;
879 }
880
881 if c.or {
882 let or_values = materialize_or_values(c);
883 let iter_len = c
884 .or_fields
885 .len()
886 .min(c.or_operators.len())
887 .min(or_values.len());
888 let mut exprs = Vec::new();
889 for (i, value) in or_values.iter().enumerate().take(iter_len) {
890 match build_expr(
891 flavor,
892 &cond_builder,
893 &c.or_fields[i],
894 c.or_operators[i],
895 value,
896 ) {
897 Some(expr) if !expr.is_empty() => exprs.push(expr),
898 _ => {}
899 }
900 }
901 if !exprs.is_empty() {
902 let combined = cond_builder.or(exprs);
903 wc.borrow_mut()
904 .add_where_expr(cond_builder.args.clone(), [combined]);
905 has_expr = true;
906 }
907 } else {
908 match build_expr(
909 flavor,
910 &cond_builder,
911 &c.field,
912 c.operator,
913 &materialize_value(c),
914 ) {
915 Some(expr) if !expr.is_empty() => {
916 wc.borrow_mut()
917 .add_where_expr(cond_builder.args.clone(), [expr]);
918 has_expr = true;
919 }
920 _ => {}
921 }
922 }
923 }
924
925 if has_expr { Some(wc) } else { None }
926}
927
928fn apply_select_condition(flavor: Flavor, builder: &mut SelectBuilder, condition: &Condition) {
929 if should_skip(condition) {
930 return;
931 }
932 let value = materialize_value(condition);
933 match condition.operator {
934 Operator::Limit => {
935 if let Some(v) = value_to_i64(&value) {
936 builder.limit(v);
937 }
938 }
939 Operator::Offset => {
940 if let Some(v) = value_to_i64(&value) {
941 builder.offset(v);
942 }
943 }
944 Operator::OrderBy => {
945 let cols = value_to_strings(&value);
946 if !cols.is_empty() {
947 builder.order_by(cols);
948 }
949 }
950 Operator::OrderByDesc => {
951 builder.order_by_desc(quote_with_flavor(flavor, &condition.field));
952 }
953 Operator::OrderByAsc => {
954 builder.order_by_asc(quote_with_flavor(flavor, &condition.field));
955 }
956 Operator::GroupBy => {
957 let cols = value_to_strings(&value);
958 if !cols.is_empty() {
959 builder.group_by(cols);
960 } else if !condition.field.is_empty() {
961 builder.group_by(vec![quote_with_flavor(flavor, &condition.field)]);
962 }
963 }
964 Operator::Join => {
965 if let Some(join) = &condition.join {
966 builder.join_with_option(join.option, join.table.clone(), join.on_expr.clone());
967 }
968 }
969 _ => {}
970 }
971}
972
973fn apply_update_condition(flavor: Flavor, builder: &mut UpdateBuilder, condition: &Condition) {
974 if should_skip(condition) {
975 return;
976 }
977 let value = materialize_value(condition);
978 match condition.operator {
979 Operator::Limit => {
980 if let Some(v) = value_to_i64(&value) {
981 builder.limit(v);
982 }
983 }
984 Operator::OrderBy => {
985 let cols = value_to_strings(&value);
986 if !cols.is_empty() {
987 builder.order_by(cols);
988 }
989 }
990 Operator::OrderByDesc => {
991 builder.order_by_desc(quote_with_flavor(flavor, &condition.field));
992 }
993 Operator::OrderByAsc => {
994 builder.order_by_asc(quote_with_flavor(flavor, &condition.field));
995 }
996 _ => {}
997 }
998}
999
1000fn apply_delete_condition(flavor: Flavor, builder: &mut DeleteBuilder, condition: &Condition) {
1001 if should_skip(condition) {
1002 return;
1003 }
1004 let value = materialize_value(condition);
1005 match condition.operator {
1006 Operator::Limit => {
1007 if let Some(v) = value_to_i64(&value) {
1008 builder.limit(v);
1009 }
1010 }
1011 Operator::OrderBy => {
1012 let cols = value_to_strings(&value);
1013 if !cols.is_empty() {
1014 builder.order_by(cols);
1015 }
1016 }
1017 Operator::OrderByDesc => {
1018 builder.order_by_desc(quote_with_flavor(flavor, &condition.field));
1019 }
1020 Operator::OrderByAsc => {
1021 builder.order_by_asc(quote_with_flavor(flavor, &condition.field));
1022 }
1023 _ => {}
1024 }
1025}
1026
1027pub fn build_select(
1029 builder: SelectBuilder,
1030 conditions: impl IntoIterator<Item = Condition>,
1031) -> (String, Vec<Arg>) {
1032 build_select_with_flavor(default_flavor(), builder, conditions)
1033}
1034
1035pub fn build_select_with_flavor(
1037 flavor: Flavor,
1038 mut builder: SelectBuilder,
1039 conditions: impl IntoIterator<Item = Condition>,
1040) -> (String, Vec<Arg>) {
1041 builder.set_flavor(flavor);
1042 let conditions: Vec<Condition> = conditions.into_iter().collect();
1043 if let Some(wc) = build_where_clause(flavor, &conditions) {
1044 builder.add_where_clause_ref(&wc);
1045 }
1046 for c in &conditions {
1047 apply_select_condition(flavor, &mut builder, c);
1048 }
1049 builder.build_with_flavor(flavor, &[])
1050}
1051
1052pub fn build_update(
1054 builder: UpdateBuilder,
1055 data: impl IntoIterator<Item = (impl Into<String>, impl Into<UpdateValue>)>,
1056 conditions: impl IntoIterator<Item = Condition>,
1057) -> (String, Vec<Arg>) {
1058 build_update_with_flavor(default_flavor(), builder, data, conditions)
1059}
1060
1061pub fn build_update_with_flavor(
1063 flavor: Flavor,
1064 mut builder: UpdateBuilder,
1065 data: impl IntoIterator<Item = (impl Into<String>, impl Into<UpdateValue>)>,
1066 conditions: impl IntoIterator<Item = Condition>,
1067) -> (String, Vec<Arg>) {
1068 builder.set_flavor(flavor);
1069 let conditions: Vec<Condition> = conditions.into_iter().collect();
1070 if let Some(wc) = build_where_clause(flavor, &conditions) {
1071 builder.add_where_clause_ref(&wc);
1072 }
1073 for c in &conditions {
1074 apply_update_condition(flavor, &mut builder, c);
1075 }
1076
1077 for (field, value) in data {
1078 let field = field.into();
1079 match value.into() {
1080 UpdateValue::Value(v) => {
1081 builder.set_more([builder.assign("e_with_flavor(flavor, &field), v)]);
1082 }
1083 UpdateValue::Field(mut f) => {
1084 if let Some(skip_fn) = &f.skip_fn {
1085 if skip_fn() {
1086 continue;
1087 }
1088 } else if f.skip {
1089 continue;
1090 }
1091 if let Some(func) = &f.value_fn {
1092 f.value = Some(func());
1093 }
1094 let quoted = quote_with_flavor(flavor, &f.field);
1095 match f.operator {
1096 UpdateFieldOperator::Assign => {
1097 if let Some(v) = f.value.clone() {
1098 builder.set_more([builder.assign("ed, v)]);
1099 }
1100 }
1101 UpdateFieldOperator::Incr => {
1102 builder.set_more([builder.incr("ed)]);
1103 }
1104 UpdateFieldOperator::Decr => {
1105 builder.set_more([builder.decr("ed)]);
1106 }
1107 UpdateFieldOperator::Add => {
1108 if let Some(v) = f.value.clone() {
1109 builder.set_more([builder.add_("ed, v)]);
1110 }
1111 }
1112 UpdateFieldOperator::Sub => {
1113 if let Some(v) = f.value.clone() {
1114 builder.set_more([builder.sub("ed, v)]);
1115 }
1116 }
1117 UpdateFieldOperator::Mul => {
1118 if let Some(v) = f.value.clone() {
1119 builder.set_more([builder.mul("ed, v)]);
1120 }
1121 }
1122 UpdateFieldOperator::Div => {
1123 if let Some(v) = f.value.clone() {
1124 builder.set_more([builder.div("ed, v)]);
1125 }
1126 }
1127 }
1128 }
1129 }
1130 }
1131
1132 builder.build_with_flavor(flavor, &[])
1133}
1134
1135pub fn build_delete(
1137 builder: DeleteBuilder,
1138 conditions: impl IntoIterator<Item = Condition>,
1139) -> (String, Vec<Arg>) {
1140 build_delete_with_flavor(default_flavor(), builder, conditions)
1141}
1142
1143pub fn build_delete_with_flavor(
1145 flavor: Flavor,
1146 mut builder: DeleteBuilder,
1147 conditions: impl IntoIterator<Item = Condition>,
1148) -> (String, Vec<Arg>) {
1149 builder.set_flavor(flavor);
1150 let conditions: Vec<Condition> = conditions.into_iter().collect();
1151 if let Some(wc) = build_where_clause(flavor, &conditions) {
1152 builder.add_where_clause_ref(&wc);
1153 }
1154 for c in &conditions {
1155 apply_delete_condition(flavor, &mut builder, c);
1156 }
1157 builder.build_with_flavor(flavor, &[])
1158}
1159
1160#[cfg(test)]
1161mod tests {
1162 use super::*;
1163 use crate::select::SelectBuilder;
1164 use crate::update::UpdateBuilder;
1165 use crate::{DeleteBuilder, flavor::set_default_flavor};
1166 use pretty_assertions::assert_eq;
1167
1168 #[test]
1169 fn select_with_condition_like_go() {
1170 set_default_flavor(Flavor::MySQL);
1171 let between = vec![
1172 ConditionValue::from(vec![24_i64, 48]),
1173 ConditionValue::from(vec![170_i64, 175]),
1174 ];
1175 let conditions = vec![
1176 Condition::new("name", Operator::Equal, "jaronnie"),
1177 Condition {
1178 skip: false,
1179 skip_fn: None,
1180 or: true,
1181 or_operators: vec![Operator::Between, Operator::Between],
1182 or_fields: vec!["age".into(), "height".into()],
1183 or_values: between,
1184 or_values_fn: None,
1185 field: String::new(),
1186 operator: Operator::Between,
1187 value: ConditionValue::default(),
1188 value_fn: None,
1189 join: None,
1190 where_clause: None,
1191 },
1192 ];
1193
1194 let mut sb = SelectBuilder::new();
1195 sb.select(vec!["name", "age", "height"]).from(vec!["user"]);
1196 let (sql, args) = build_select(sb, conditions);
1197 assert_eq!(
1198 "SELECT name, age, height FROM user WHERE `name` = ? AND (`age` BETWEEN ? AND ? OR `height` BETWEEN ? AND ?)",
1199 sql
1200 );
1201 assert_eq!(
1202 args,
1203 vec![
1204 Arg::from("jaronnie"),
1205 Arg::from(24_i64),
1206 Arg::from(48_i64),
1207 Arg::from(170_i64),
1208 Arg::from(175_i64)
1209 ]
1210 );
1211 }
1212
1213 #[test]
1214 fn chain_basic_and_order() {
1215 let chain = Chain::new()
1216 .equal_opts("field1", "value1", ChainOptions::default().skip(true))
1217 .equal("field2", "value2")
1218 .order_by_desc("create_time")
1219 .order_by_asc("sort");
1220 let mut sb = SelectBuilder::new();
1221 sb.select(vec!["name", "age"]).from(vec!["user"]);
1222 let (sql, args) = build_select_with_flavor(Flavor::MySQL, sb, chain.build());
1223 assert_eq!(
1224 "SELECT name, age FROM user WHERE `field2` = ? ORDER BY `create_time` DESC, `sort` ASC",
1225 sql
1226 );
1227 assert_eq!(args, vec![Arg::from("value2")]);
1228 }
1229
1230 #[test]
1231 fn chain_join_and_null() {
1232 let chain = Chain::new()
1233 .equal("user.field", "value2")
1234 .join(
1235 JoinOption::InnerJoin,
1236 "user_info",
1237 ["user.id = user_info.user_id"],
1238 )
1239 .is_null("delete_at")
1240 .is_not_null("updated_at");
1241 let mut sb = SelectBuilder::new();
1242 sb.select(vec!["user.name", "user.age"]).from(vec!["user"]);
1243 let (sql, args) = build_select_with_flavor(Flavor::MySQL, sb, chain.build());
1244 assert_eq!(
1245 "SELECT user.name, user.age FROM user INNER JOIN user_info ON user.id = user_info.user_id WHERE `user`.`field` = ? AND `delete_at` IS NULL AND `updated_at` IS NOT NULL",
1246 sql
1247 );
1248 assert_eq!(args, vec![Arg::from("value2")]);
1249 }
1250
1251 #[test]
1252 fn chain_equal_fluent_modifiers() {
1253 let chain = Chain::new()
1254 .equal("name", "placeholder")
1255 .value_fn(|| ConditionValue::from("jzero"))
1256 .skip(false)
1257 .skip_fn(|| false);
1258
1259 let mut sb = SelectBuilder::new();
1260 sb.select(vec!["id", "name"]).from(vec!["user"]);
1261 let (sql, args) = build_select_with_flavor(Flavor::MySQL, sb, chain.build());
1262
1263 assert_eq!("SELECT id, name FROM user WHERE `name` = ?", sql);
1264 assert_eq!(args, vec![Arg::from("jzero")]);
1265 }
1266
1267 #[test]
1268 fn chain_page_and_group_by() {
1269 let chain = Chain::new()
1270 .equal("status", "active")
1271 .group_by("status")
1272 .page(2, 10)
1273 .order_by(vec!["status"]);
1274
1275 let mut sb = SelectBuilder::new();
1276 sb.select(vec!["status", "COUNT(1)"]).from(vec!["users"]);
1277 let (sql, args) = build_select_with_flavor(Flavor::MySQL, sb, chain.build());
1278
1279 assert_eq!(
1280 "SELECT status, COUNT(1) FROM users WHERE `status` = ? GROUP BY `status` ORDER BY status LIMIT ? OFFSET ?",
1281 sql
1282 );
1283 assert_eq!(
1284 args,
1285 vec![Arg::from("active"), Arg::from(10_i64), Arg::from(10_i64)]
1286 );
1287 }
1288
1289 #[test]
1290 fn condition_value_fn_and_skip_fn() {
1291 let conds = vec![
1292 Condition {
1293 skip: false,
1294 skip_fn: Some(Arc::new(|| true)),
1295 or: false,
1296 or_operators: Vec::new(),
1297 or_fields: Vec::new(),
1298 or_values: Vec::new(),
1299 or_values_fn: None,
1300 field: "skip_me".into(),
1301 operator: Operator::Equal,
1302 value: ConditionValue::from("never"),
1303 value_fn: None,
1304 join: None,
1305 where_clause: None,
1306 },
1307 Condition {
1308 skip: false,
1309 skip_fn: None,
1310 or: false,
1311 or_operators: Vec::new(),
1312 or_fields: Vec::new(),
1313 or_values: Vec::new(),
1314 or_values_fn: None,
1315 field: "name".into(),
1316 operator: Operator::Equal,
1317 value: ConditionValue::from("placeholder"),
1318 value_fn: Some(Arc::new(|| ConditionValue::from("dynamic"))),
1319 join: None,
1320 where_clause: None,
1321 },
1322 ];
1323
1324 let mut sb = SelectBuilder::new();
1325 sb.select(vec!["id"]).from(vec!["users"]);
1326 let (sql, args) = build_select_with_flavor(Flavor::MySQL, sb, conds);
1327
1328 assert_eq!("SELECT id FROM users WHERE `name` = ?", sql);
1329 assert_eq!(args, vec![Arg::from("dynamic")]);
1330 }
1331
1332 #[test]
1333 fn condition_delete_skip_and_value_func() {
1334 let conds = vec![
1335 Condition {
1336 skip: false,
1337 skip_fn: Some(Arc::new(|| true)),
1338 or: false,
1339 or_operators: Vec::new(),
1340 or_fields: Vec::new(),
1341 or_values: Vec::new(),
1342 or_values_fn: None,
1343 field: "name".into(),
1344 operator: Operator::Equal,
1345 value: ConditionValue::from("jaronnie"),
1346 value_fn: Some(Arc::new(|| ConditionValue::from("jaronnie2"))),
1347 join: None,
1348 where_clause: None,
1349 },
1350 Condition {
1351 skip: false,
1352 skip_fn: None,
1353 or: true,
1354 or_operators: vec![Operator::Between, Operator::Between],
1355 or_fields: vec!["age".into(), "height".into()],
1356 or_values: vec![
1357 ConditionValue::from(vec![24_i64, 48]),
1358 ConditionValue::from(vec![170_i64, 175]),
1359 ],
1360 or_values_fn: Some(Arc::new(|| {
1361 vec![
1362 ConditionValue::from(vec![24_i64, 49]),
1363 ConditionValue::from(vec![170_i64, 176]),
1364 ]
1365 })),
1366 field: String::new(),
1367 operator: Operator::Between,
1368 value: ConditionValue::default(),
1369 value_fn: None,
1370 join: None,
1371 where_clause: None,
1372 },
1373 ];
1374 let mut db = DeleteBuilder::new();
1375 db.delete_from(vec!["user"]);
1376 let (sql, args) = build_delete(db, conds);
1377 assert_eq!(
1378 "DELETE FROM user WHERE (`age` BETWEEN ? AND ? OR `height` BETWEEN ? AND ?)",
1379 sql
1380 );
1381 assert_eq!(
1382 args,
1383 vec![
1384 Arg::from(24_i64),
1385 Arg::from(49_i64),
1386 Arg::from(170_i64),
1387 Arg::from(176_i64)
1388 ]
1389 );
1390 }
1391
1392 #[test]
1393 fn update_with_update_field_chain() {
1394 let data = UpdateFieldChain::new()
1395 .assign("name", "jaronnie", UpdateFieldOptions::default().skip(true))
1396 .incr("version", UpdateFieldOptions::default())
1397 .add(
1398 "age",
1399 12_i64,
1400 UpdateFieldOptions::default().value_fn(|| Arg::from(15_i64)),
1401 )
1402 .build();
1403
1404 let chain = Chain::new().equal("id", 1_i64);
1405 let mut ub = UpdateBuilder::new();
1406 ub.update(vec!["users"]);
1407 let (sql, args) = build_update_with_flavor(Flavor::MySQL, ub, data, chain.build());
1408 assert_eq!(
1409 "UPDATE users SET `version` = `version` + 1, `age` = `age` + ? WHERE `id` = ?",
1410 sql
1411 );
1412 assert_eq!(args, vec![Arg::from(15_i64), Arg::from(1_i64)]);
1413 }
1414
1415 #[test]
1416 fn condition_in_allows_empty_slice() {
1417 let mut sb = SelectBuilder::new();
1418 sb.select(vec!["id"]).from(vec!["users"]);
1419 let (sql, args) = build_select(
1420 sb,
1421 [Condition::new(
1422 "id",
1423 Operator::In,
1424 ConditionValue::from(Vec::<i64>::new()),
1425 )],
1426 );
1427 assert_eq!("SELECT id FROM users WHERE `id` IN (?)", sql);
1428 assert_eq!(args, vec![Arg::from(SqlValue::Null)]);
1429 }
1430}