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}