surreal_simple_querybuilder/
querybuilder.rs

1use std::{borrow::Cow, collections::HashMap};
2
3#[cfg(feature = "model")]
4use serde::Serialize;
5
6#[cfg(feature = "model")]
7use crate::prelude::SqlSerializeResult;
8
9pub type CowSegment<'a> = Cow<'a, str>;
10
11#[derive(Debug)]
12enum QueryBuilderInsertExceptions {
13  None,
14  AndOr,
15}
16
17pub struct QueryBuilder<'a> {
18  segments: Vec<CowSegment<'a>>,
19  parameters: HashMap<&'a str, &'a str>,
20
21  /// this private enum is used as a marker for the next segment that will be
22  /// inserted to detect if it should be cancelled/replaced or not.
23  insert_exceptions: QueryBuilderInsertExceptions,
24}
25
26impl<'a> QueryBuilder<'a> {
27  pub fn new() -> Self {
28    QueryBuilder {
29      segments: Vec::new(),
30      parameters: HashMap::new(),
31      insert_exceptions: QueryBuilderInsertExceptions::None,
32    }
33  }
34
35  /// # Example
36  /// ```
37  /// use surreal_simple_querybuilder::prelude::*;
38  ///
39  /// let query = QueryBuilder::new().create("Person:ee").build();
40  ///
41  /// assert_eq!(query, "CREATE Person:ee")
42  /// ```
43  pub fn create<T: Into<CowSegment<'a>>>(mut self, node: T) -> Self {
44    self.add_segment_p("CREATE", node);
45
46    self
47  }
48
49  /// # Example
50  /// ```
51  /// use surreal_simple_querybuilder::prelude::*;
52  ///
53  /// let query = QueryBuilder::new().update("Person:ee").build();
54  ///
55  /// assert_eq!(query, "UPDATE Person:ee")
56  /// ```
57  pub fn update<T: Into<CowSegment<'a>>>(mut self, node: T) -> Self {
58    self.add_segment_p("UPDATE", node);
59
60    self
61  }
62
63  /// # Example
64  /// ```
65  /// use surreal_simple_querybuilder::prelude::*;
66  ///
67  /// let query = QueryBuilder::new().select("ee:Person").build();
68  ///
69  /// assert_eq!(query, "SELECT ee:Person")
70  /// ```
71  pub fn select<T: Into<CowSegment<'a>>>(mut self, node: T) -> Self {
72    self.add_segment_p("SELECT", node);
73
74    self
75  }
76
77  /// Start a `DELETE` statement:
78  /// ```sql
79  /// DELETE user:John
80  /// ```
81  ///
82  /// # Example
83  /// ```
84  /// use surreal_simple_querybuilder::prelude::*;
85  ///
86  /// let query = QueryBuilder::new().delete("ee:Person").build();
87  ///
88  /// assert_eq!(query, "DELETE ee:Person");
89  /// ```
90  pub fn delete<T: Into<CowSegment<'a>>>(mut self, node: T) -> Self {
91    self.add_segment_p("DELETE", node);
92
93    self
94  }
95
96  /// Start a `RELATE` statement:
97  /// ```sql
98  /// RELATE user:tobie->write->article:surreal SET time.written = time::now();
99  /// ```
100  /// _Note: the `SET` or anything after it in the example above should be added
101  /// manually using the [`QueryBuilder::set()`] method._
102  ///
103  /// # Example
104  /// ```
105  /// use surreal_simple_querybuilder::prelude::*;
106  ///
107  /// let query = QueryBuilder::new().relate("user:John->likes->user:Mark").build();
108  ///
109  /// assert_eq!(query, "RELATE user:John->likes->user:Mark");
110  /// ```
111  pub fn relate<T: Into<CowSegment<'a>>>(mut self, node: T) -> Self {
112    self.add_segment_p("RELATE", node);
113
114    self
115  }
116
117  /// Start a `CONTENT` statement. Content statements often follow RELATE statements:
118  /// ```sql
119  /// RELATE user:tobie->write->article:surreal CONTENT {
120  ///   source: 'Apple notes',
121  ///   tags: ['notes', 'markdown'],
122  ///   time: {
123  ///     written: time::now(),
124  ///   },
125  /// };
126  /// ```
127  /// _Note: Anything before the `CONTENT` in the example above should be added
128  /// manually using the [`QueryBuilder::relate()`] method._
129  ///
130  /// # Example
131  /// ```
132  /// use surreal_simple_querybuilder::prelude::*;
133  ///
134  /// let query = QueryBuilder::new().content("{ creation_time: time::now() }").build();
135  ///
136  /// assert_eq!(query, "CONTENT { creation_time: time::now() }");
137  /// ```
138  pub fn content<T: Into<CowSegment<'a>>>(mut self, json_content: T) -> Self {
139    self.add_segment_p("CONTENT", json_content);
140
141    self
142  }
143
144  /// # Example
145  /// ```
146  /// use surreal_simple_querybuilder::prelude::*;
147  ///
148  /// let query = QueryBuilder::new().from("Person").build();
149  ///
150  /// assert_eq!(query, "FROM Person")
151  pub fn from<T: Into<CowSegment<'a>>>(mut self, node: T) -> Self {
152    self.add_segment_p("FROM", node);
153
154    self
155  }
156
157  /// # Example
158  /// ```
159  /// use surreal_simple_querybuilder::prelude::*;
160  ///
161  /// let query = QueryBuilder::new().select_many(&["ee:Person", "o:Order"]).build();
162  ///
163  /// assert_eq!(query, "SELECT ee:Person , o:Order")
164  /// ```
165  pub fn select_many<T: Into<CowSegment<'a>>>(mut self, nodes: &[T]) -> Self
166  where
167    T: Copy,
168  {
169    self.add_segment("SELECT");
170    self.join_segments(",", "", nodes, "");
171
172    self
173  }
174
175  /// Adds the supplied query with a comma in front of it
176  ///
177  /// # Example
178  /// ```
179  /// use surreal_simple_querybuilder::prelude::*;
180  ///
181  /// let query = QueryBuilder::new().also("ee").build();
182  ///
183  /// assert_eq!(query, ", ee")
184  /// ```
185  pub fn also<T: Into<CowSegment<'a>>>(mut self, query: T) -> Self {
186    self.add_segment_p(",", query);
187
188    self
189  }
190
191  /// Adds the given segments, separated by the given `separator` and with a `prefix`
192  /// and a `suffix` added to them too.
193  ///
194  /// # Example
195  /// ```rs
196  /// use surreal_simple_querybuilder::prelude::*;
197  ///
198  /// let query = QueryBuilder::new()
199  ///   .join_segments(",", "set", &["handle", "id"], "")
200  ///   .build();
201  ///
202  /// assert_eq!(query, "set handle , set id");
203  /// ```
204  #[allow(dead_code)]
205  fn join_segments<T: Into<CowSegment<'a>>>(
206    &mut self, seperator: &'a str, prefix: &'a str, segments: &[T], suffix: &'a str,
207  ) -> &mut Self
208  where
209    T: Copy,
210  {
211    let segments_count = segments.len();
212
213    if segments_count <= 1 {
214      for segment in segments {
215        self.add_segment_ps(prefix, *segment, suffix);
216      }
217
218      return self;
219    }
220
221    for i in 0..segments_count - 1 {
222      self.add_segment_ps(prefix, segments[i], suffix);
223      self.add_segment(seperator);
224    }
225
226    self.add_segment_ps(prefix, segments[segments_count - 1], suffix);
227
228    self
229  }
230
231  /// Starts a WHERE clause.
232  ///
233  /// # Example
234  /// ```
235  /// use surreal_simple_querybuilder::prelude::*;
236  ///
237  /// let query = QueryBuilder::new()
238  ///   .filter("handle = ?1")
239  ///   .build();
240  ///
241  /// assert_eq!(query, "WHERE handle = ?1");
242  /// ```
243  pub fn filter<T: Into<CowSegment<'a>>>(mut self, condition: T) -> Self {
244    self.add_segment_p("WHERE", condition);
245
246    self
247  }
248
249  /// An alias for `QueryBuilder::filter`
250  pub fn and_where<T: Into<CowSegment<'a>>>(self, condition: T) -> Self {
251    self.filter(condition)
252  }
253
254  /// Writes a OR followed by the supplied `condition`
255  ///
256  /// # Example
257  /// ```
258  /// use surreal_simple_querybuilder::prelude::*;
259  ///
260  /// let query = QueryBuilder::new()
261  ///   .or("handle = ?1")
262  ///   .build();
263  ///
264  /// assert_eq!(query, "OR handle = ?1");
265  /// ```
266  pub fn or<T: Into<CowSegment<'a>>>(mut self, condition: T) -> Self {
267    match self.insert_exceptions {
268      QueryBuilderInsertExceptions::AndOr => self.add_segment(condition),
269      _ => self.add_segment_p("OR", condition),
270    };
271
272    self
273  }
274
275  /// Starts an AND followed by the supplied `condition`.
276  ///
277  /// # Example
278  /// ```
279  /// use surreal_simple_querybuilder::prelude::*;
280  ///
281  /// let query = QueryBuilder::new()
282  ///   .and("handle = ?1")
283  ///   .build();
284  ///
285  /// assert_eq!(query, "AND handle = ?1");
286  /// ```
287  pub fn and<T: Into<CowSegment<'a>>>(mut self, condition: T) -> Self {
288    match self.insert_exceptions {
289      QueryBuilderInsertExceptions::AndOr => self.add_segment(condition),
290      _ => self.add_segment_p("AND", condition),
291    };
292
293    self
294  }
295
296  /// Starts a SET clause.
297  ///
298  /// # Example
299  /// ```
300  /// use surreal_simple_querybuilder::prelude::*;
301  ///
302  /// let query = QueryBuilder::new()
303  ///   .set("handle = ?1")
304  ///   .build();
305  ///
306  /// assert_eq!(query, "SET handle = ?1");
307  /// ```
308  pub fn set<T: Into<CowSegment<'a>>>(mut self, update: T) -> Self {
309    self.add_segment_p("SET", update);
310
311    self
312  }
313
314  /// Starts a SET clause with many fields.
315  ///
316  /// # Example
317  /// ```
318  /// use surreal_simple_querybuilder::prelude::*;
319  ///
320  /// let query = QueryBuilder::new()
321  ///   .set_many(&["handle = $1", "password = $2"])
322  ///   .build();
323  ///
324  /// assert_eq!(query, "SET handle = $1 , password = $2");
325  /// ```
326  pub fn set_many<T: Into<CowSegment<'a>>>(mut self, updates: &[T]) -> Self
327  where
328    T: Copy,
329  {
330    self.add_segment("SET");
331    self.join_segments(",", "", updates, "");
332
333    self
334  }
335
336  /// Starts a FETCH clause,
337  ///
338  /// # Example
339  /// ```
340  /// use surreal_simple_querybuilder::prelude::*;
341  ///
342  /// let query = QueryBuilder::new()
343  ///   .fetch("author")
344  ///   .build();
345  ///
346  /// assert_eq!(query, "FETCH author");
347  /// ```
348  pub fn fetch<T: Into<CowSegment<'a>>>(mut self, field: T) -> Self {
349    self.add_segment_p("FETCH", field);
350
351    self
352  }
353
354  /// Starts a FETCH clause with zero or more fields,
355  ///
356  /// # Example
357  /// ```
358  /// use surreal_simple_querybuilder::prelude::*;
359  ///
360  /// let query = QueryBuilder::new()
361  ///   .fetch_many(&["author", "projects"])
362  ///   .build();
363  ///
364  /// assert_eq!(query, "FETCH author , projects");
365  /// ```
366  pub fn fetch_many<T: Into<CowSegment<'a>>>(mut self, fields: &[T]) -> Self
367  where
368    T: Copy,
369  {
370    self.add_segment("FETCH");
371    self.join_segments(",", "", fields, "");
372
373    self
374  }
375
376  /// Starts a GROUP BY clause,
377  ///
378  /// # Example
379  /// ```
380  /// use surreal_simple_querybuilder::prelude::*;
381  ///
382  /// let query = QueryBuilder::new()
383  ///   .group_by("author")
384  ///   .build();
385  ///
386  /// assert_eq!(query, "GROUP BY author");
387  /// ```
388  pub fn group_by<T: Into<CowSegment<'a>>>(mut self, field: T) -> Self {
389    self.add_segment_p("GROUP BY", field);
390
391    self
392  }
393
394  /// Starts a GROUP BY clause with zero or more fields,
395  ///
396  /// # Example
397  /// ```
398  /// use surreal_simple_querybuilder::prelude::*;
399  ///
400  /// let query = QueryBuilder::new()
401  ///   .group_by_many(&["author", "projects"])
402  ///   .build();
403  ///
404  /// assert_eq!(query, "GROUP BY author , projects");
405  /// ```
406  pub fn group_by_many<T: Into<CowSegment<'a>>>(mut self, fields: &[T]) -> Self
407  where
408    T: Copy,
409  {
410    self.add_segment("GROUP BY");
411    self.join_segments(",", "", fields, "");
412
413    self
414  }
415
416  /// Starts a ORDER BY ASC clause,
417  ///
418  /// # Example
419  /// ```
420  /// use surreal_simple_querybuilder::prelude::*;
421  ///
422  /// let query = QueryBuilder::new()
423  ///   .order_by_asc("author")
424  ///   .build();
425  ///
426  /// assert_eq!(query, "ORDER BY author ASC");
427  /// ```
428  pub fn order_by_asc<T: Into<CowSegment<'a>>>(mut self, field: T) -> Self {
429    self.add_segment_ps("ORDER BY", field, "ASC");
430
431    self
432  }
433
434  /// Starts a ORDER BY ASC clause with zero or more fields,
435  ///
436  /// # Example
437  /// ```
438  /// use surreal_simple_querybuilder::prelude::*;
439  ///
440  /// let query = QueryBuilder::new()
441  ///   .order_by_asc_many(&["author", "projects"])
442  ///   .build();
443  ///
444  /// assert_eq!(query, "ORDER BY author ASC , projects ASC");
445  /// ```
446  pub fn order_by_asc_many<T: Into<CowSegment<'a>>>(mut self, fields: &[T]) -> Self
447  where
448    T: Copy,
449  {
450    self.add_segment("ORDER BY");
451    self.join_segments(",", "", fields, "ASC");
452
453    self
454  }
455
456  /// Starts a ORDER BY DESC clause,
457  ///
458  /// # Example
459  /// ```
460  /// use surreal_simple_querybuilder::prelude::*;
461  ///
462  /// let query = QueryBuilder::new()
463  ///   .order_by_desc("author")
464  ///   .build();
465  ///
466  /// assert_eq!(query, "ORDER BY author DESC");
467  /// ```
468  pub fn order_by_desc<T: Into<CowSegment<'a>>>(mut self, field: T) -> Self {
469    self.add_segment_ps("ORDER BY", field, "DESC");
470
471    self
472  }
473
474  /// Starts a ORDER BY DESC clause with zero or more fields,
475  ///
476  /// # Example
477  /// ```
478  /// use surreal_simple_querybuilder::prelude::*;
479  ///
480  /// let query = QueryBuilder::new()
481  ///   .order_by_desc_many(&["author", "projects"])
482  ///   .build();
483  ///
484  /// assert_eq!(query, "ORDER BY author DESC , projects DESC");
485  /// ```
486  pub fn order_by_desc_many<T: Into<CowSegment<'a>>>(mut self, fields: &[T]) -> Self
487  where
488    T: Copy,
489  {
490    self.add_segment("ORDER BY");
491    self.join_segments(",", "", fields, "DESC");
492
493    self
494  }
495
496  /// Queues a condition which allows the next statement to be ignored if
497  /// `condition` is `false`.
498  ///
499  /// Conditions can be nested, the queue works as a LIFO queue.
500  ///
501  /// # Example
502  /// ```
503  /// use surreal_simple_querybuilder::prelude::*;
504  ///
505  /// let query = QueryBuilder::new()
506  ///   .select_many(&["1", "2"])
507  ///   .if_then(false, |query| query
508  ///     .select_many(&["3", "4"])
509  ///     // will not run:
510  ///     .if_then(true, |query| query
511  ///       .select_many(&["5", "6"])
512  ///     )
513  ///   )
514  ///   .if_then(true, |query| query
515  ///     .select_many(&["7", "8"])
516  ///   )
517  ///   .build();
518  ///
519  /// assert_eq!(query, "SELECT 1 , 2 SELECT 7 , 8");
520  /// ```
521  pub fn if_then<F>(self, condition: bool, action: F) -> Self
522  where
523    F: Fn(Self) -> Self,
524  {
525    if !condition {
526      return self;
527    }
528
529    action(self)
530  }
531
532  /// Writes an AND followed by the supplied `first_condition` and any other
533  /// statement added to the querybuilder in the `action` closure surrounded by
534  /// parenthesis.
535  ///
536  /// Can be used to compose boolean expressions with grouped OR statements like so:
537  /// ```sql
538  /// WHERE name contains 'John' AND (name contains 'Doe' OR name contains 'Eod')
539  /// ```
540  /// # Example
541  /// ```
542  /// use surreal_simple_querybuilder::prelude::*;
543  ///
544  /// let query = QueryBuilder::new()
545  ///   .select("*")
546  ///   .from("user")
547  ///   .filter("name contains 'John'")
548  ///   .and_group("name contains 'Doe'", |q| {
549  ///     q.or("name contains 'Eod'")
550  ///   })
551  ///   .build();
552  ///
553  /// assert_eq!(query, "SELECT * FROM user WHERE name contains 'John' AND ( name contains 'Doe' OR name contains 'Eod' )");
554  /// ```
555  pub fn and_group<F, T: Into<CowSegment<'a>>>(mut self, first_condition: T, action: F) -> Self
556  where
557    F: Fn(Self) -> Self,
558  {
559    self.add_segment_p("AND", "(");
560    self.add_segment(first_condition);
561    let mut output = action(self);
562    output.add_segment(")");
563
564    output
565  }
566
567  /// Pushes raw text to the buffer
568  ///
569  /// # Example
570  /// ```
571  /// use surreal_simple_querybuilder::prelude::*;
572  ///
573  /// let query = QueryBuilder::new()
574  ///   .raw("foo bar")
575  ///   .build();
576  ///
577  /// assert_eq!(query, "foo bar");
578  /// ```
579  pub fn raw(mut self, text: &'a str) -> Self {
580    self.add_segment(text);
581
582    self
583  }
584
585  /// Start a queue where all of the new pushed actions are separated by commas.
586  ///
587  /// # Example
588  /// ```
589  /// use surreal_simple_querybuilder::prelude::*;
590  ///
591  /// let query = QueryBuilder::new()
592  ///   .commas(|query| query
593  ///     .raw("foo")
594  ///     .raw("bar")
595  ///   ).build();
596  ///
597  /// assert_eq!(query, "foo , bar");
598  /// ```
599  pub fn commas<F>(mut self, action: F) -> Self
600  where
601    F: Fn(Self) -> Self,
602  {
603    let other = action(QueryBuilder::new());
604
605    for (index, segment) in other.segments.into_iter().enumerate() {
606      if index <= 0 {
607        self.segments.push(segment);
608      } else {
609        self.add_segment(",");
610        self.segments.push(segment);
611      }
612    }
613
614    self
615  }
616
617  /// Start a queue where all of the new pushed actions are separated by `AND`s.
618  ///
619  /// # Example
620  /// ```
621  /// use surreal_simple_querybuilder::prelude::*;
622  ///
623  /// let query = QueryBuilder::new()
624  ///   .ands(|query| query
625  ///     .raw("foo")
626  ///     .raw("bar")
627  ///   ).build();
628  ///
629  /// assert_eq!(query, "foo AND bar");
630  /// ```
631  pub fn ands<F>(mut self, action: F) -> Self
632  where
633    F: Fn(Self) -> Self,
634  {
635    let other = action(QueryBuilder::new());
636
637    for (index, segment) in other.segments.into_iter().enumerate() {
638      if index <= 0 {
639        self.segments.push(segment);
640      } else {
641        self = self.and(segment);
642      }
643    }
644
645    self
646  }
647
648  /// Start a queue where all of the new pushed actions are separated by `OR`s.
649  ///
650  /// # Example
651  /// ```
652  /// use surreal_simple_querybuilder::prelude::*;
653  ///
654  /// let query = QueryBuilder::new()
655  ///   .ors(|query| query
656  ///     .raw("foo")
657  ///     .raw("bar")
658  ///   ).build();
659  ///
660  /// assert_eq!(query, "foo OR bar");
661  /// ```
662  pub fn ors<F>(mut self, action: F) -> Self
663  where
664    F: Fn(Self) -> Self,
665  {
666    let other = action(QueryBuilder::new());
667
668    for (index, segment) in other.segments.into_iter().enumerate() {
669      if index <= 0 {
670        self.add_segment(segment);
671      } else {
672        self = self.or(segment);
673      }
674    }
675
676    self
677  }
678
679  /// Start a LIMIT clause.
680  ///
681  /// # Example
682  /// ```
683  /// use surreal_simple_querybuilder::prelude::*;
684  ///
685  ///
686  /// let page_size = 10.to_string();
687  /// let query = QueryBuilder::new()
688  ///   .limit(&page_size)
689  ///   .build();
690  ///
691  /// assert_eq!(query, "LIMIT 10")
692  ///
693  /// ```
694  pub fn limit<T: Into<CowSegment<'a>>>(mut self, limit: T) -> Self {
695    self.add_segment_p("LIMIT", limit);
696
697    self
698  }
699
700  /// Start a START AT clause.
701  ///
702  /// # Example
703  /// ```
704  /// use surreal_simple_querybuilder::prelude::*;
705  ///
706  ///
707  /// let page_size = 10.to_string();
708  /// let query = QueryBuilder::new()
709  ///   .start_at(&page_size)
710  ///   .build();
711  ///
712  /// assert_eq!(query, "START AT 10")
713  ///
714  /// ```
715  pub fn start_at<T: Into<CowSegment<'a>>>(mut self, offset: T) -> Self {
716    self.add_segment_p("START AT", offset);
717
718    self
719  }
720
721  /// Add the given segment to the internal buffer. This is a rather internal
722  /// method that is set public for special cases, you should prefer using the `raw`
723  /// method instead.
724  pub fn add_segment<T: Into<CowSegment<'a>>>(&mut self, segment: T) -> &mut Self {
725    let into = segment.into();
726
727    if into.is_empty() {
728      return self;
729    }
730
731    match (&self.insert_exceptions, into.as_ref()) {
732      // if the previous segment is already a OR or an AND and the new one is
733      // one of the two again, the new one replaces the old one:
734      (QueryBuilderInsertExceptions::AndOr, "AND" | "OR") => {
735        if let Some(last) = self.segments.last_mut() {
736          *last = into;
737        }
738
739        return self;
740      }
741      (_, "AND" | "OR") => {
742        self.insert_exceptions = QueryBuilderInsertExceptions::AndOr;
743      }
744      _ => {
745        self.insert_exceptions = QueryBuilderInsertExceptions::None;
746      }
747    };
748
749    self.segments.push(into);
750
751    self
752  }
753
754  fn add_segment_p<T: Into<CowSegment<'a>>>(&mut self, prefix: &'a str, segment: T) -> &mut Self {
755    self.add_segment(prefix).add_segment(segment)
756  }
757
758  fn add_segment_ps<T: Into<CowSegment<'a>>>(
759    &mut self, prefix: &'a str, segment: T, suffix: &'a str,
760  ) -> &mut Self {
761    self.add_segment_p(prefix, segment).add_segment(suffix)
762  }
763
764  /// Add a parameter and its value to the query that will be used to replace all
765  /// occurences of `key` into `value` when the `build` method is called.
766  ///
767  /// **IMPORTANT** Do not use this for user provided data, the input is not sanitized
768  ///
769  /// # Example
770  /// ```
771  /// use surreal_simple_querybuilder::prelude::*;
772  ///
773  /// let query = QueryBuilder::new()
774  ///   .select("{{field}}")
775  ///   .from("Account")
776  ///   .param("{{field}}", "id")
777  ///   .build();
778  ///
779  /// assert_eq!("SELECT id FROM Account", query);
780  /// ```
781  pub fn param(mut self, key: &'a str, value: &'a str) -> Self {
782    self.parameters.insert(key, value);
783
784    self
785  }
786
787  pub fn build(self) -> String {
788    let mut output = self.segments.join(" ");
789
790    for (key, value) in self.parameters {
791      let key_size = key.len();
792
793      while let Some(index) = output.find(key) {
794        output.replace_range(index..index + key_size, value);
795      }
796    }
797
798    output
799  }
800
801  /// Start a SET statement with all the public fields in the supplied `T` using
802  /// the [SqlFieldSerializer] and Serde to list all the serializable fields in order
803  /// to get a statement like the following:
804  /// ```sql
805  /// SET field_one = $field_one , field_two = $field_two
806  /// ```
807  ///
808  /// The function is meant to be used with the models generated by the [model]
809  /// macro.
810  #[cfg(feature = "model")]
811  pub fn set_model<T: Serialize>(mut self, model: &T) -> SqlSerializeResult<Self> {
812    let parameters = crate::model::to_parameters(model)?;
813
814    self.add_segment_p("SET", parameters);
815
816    Ok(self)
817  }
818
819  /// Start an UPDATE statement with all the public fields in the supplied `T` using
820  /// the [SqlFieldSerializer] and Serde to list all the serializable fields in order
821  /// to get a statement like the following:
822  /// ```sql
823  /// UPDATE field_one = $field_one , field_two = $field_two
824  /// ```
825  ///
826  /// The function is meant to be used with the models generated by the [model]
827  /// macro.
828  #[cfg(feature = "model")]
829  pub fn update_model<T: Serialize>(mut self, model: &T) -> SqlSerializeResult<Self> {
830    let parameters = crate::model::to_parameters(model)?;
831
832    self.add_segment_p("UPDATE", parameters);
833
834    Ok(self)
835  }
836
837  /// Allows passing a custom injecter in a chainable way. The injecter will add
838  /// its related SQL to the querybuilder and then pass out the resulting builder
839  /// so it can be chained again.
840  ///
841  /// Note that injecters often avoid writing the values into the builder to avoid
842  /// SQL injections, and so it is expected you use the [bindings] function to
843  /// extract the variables out of the injecters afterward.
844  ///
845  /// # Example
846  /// ```
847  /// use surreal_simple_querybuilder::prelude::*;
848  ///
849  /// let filter = Where(("name", "john"));
850  /// let query = QueryBuilder::new()
851  ///   .select("*")
852  ///   .from("user")
853  ///   .injecter(&filter) // <-- pass the injecter to the builder
854  ///   .build();
855  ///
856  /// let _params = bindings(filter); // <-- get the variables so you can bind them
857  ///
858  /// assert_eq!(query, "SELECT * FROM user WHERE name = $name");
859  /// ```
860  #[cfg(feature = "queries")]
861  pub fn injecter(self, injecter: &impl crate::queries::QueryBuilderInjecter<'a>) -> Self {
862    injecter.inject(self)
863  }
864}