1pub mod seaql;
2
3use crate::{QueryBuilder, write_int};
4
5#[derive(Debug)]
6pub struct RawSqlQueryBuilder {
7 sql: String,
8 parameter_index: usize,
9 placeholder: &'static str,
10 numbered: bool,
11}
12
13impl RawSqlQueryBuilder {
14 pub fn new<T: QueryBuilder>(backend: T) -> Self {
15 let (placeholder, numbered) = backend.placeholder();
16 Self {
17 sql: Default::default(),
18 parameter_index: 1,
19 placeholder,
20 numbered,
21 }
22 }
23
24 pub fn push_fragment(&mut self, sql: &str) -> &mut Self {
25 self.sql.push_str(sql);
26 self
27 }
28
29 pub fn push_parameters(&mut self, n: usize) -> &mut Self {
30 for i in 0..n {
31 if i > 0 {
32 self.sql.push_str(", ");
33 }
34 self.sql.push_str(self.placeholder);
35 if self.numbered {
36 write_int(&mut self.sql, self.parameter_index);
37 self.parameter_index += 1;
38 }
39 }
40 self
41 }
42
43 pub fn push_tuple_parameter_groups(&mut self, len: usize, tuple_arity: usize) -> &mut Self {
44 for i in 0..len {
45 if i > 0 {
46 self.sql.push_str(", ");
47 }
48 self.sql.push('(');
49 self.push_parameters(tuple_arity);
50 self.sql.push(')');
51 }
52 self
53 }
54
55 pub fn finish(self) -> String {
56 self.sql
57 }
58}
59
60#[cfg(test)]
61mod test {
62 use super::*;
63 use crate::PostgresQueryBuilder;
64
65 #[derive(Default)]
66 struct Values(Vec<String>);
67
68 impl Values {
69 fn bind<V: std::fmt::Debug>(&mut self, v: V) {
70 self.0.push(format!("{v:?}"));
71 }
72 }
73
74 #[test]
75 fn test_raw_sql_0() {
76 let mut builder = RawSqlQueryBuilder::new(PostgresQueryBuilder);
77 builder.push_fragment("SELECT");
78 assert_eq!(builder.finish(), "SELECT");
79 }
80
81 #[test]
82 fn test_raw_sql_1() {
83 let a = 1;
84 let b = vec![2i32, 3];
85 let c = [4i32, 5, 6];
86
87 let mut builder = RawSqlQueryBuilder::new(PostgresQueryBuilder);
88 builder
89 .push_fragment("SELECT")
90 .push_fragment(" ")
91 .push_parameters(1)
92 .push_fragment(", ")
93 .push_parameters((&b).len())
94 .push_fragment(", ")
95 .push_parameters((&c).len());
96
97 assert_eq!(builder.finish(), "SELECT $1, $2, $3, $4, $5, $6");
98
99 let mut values = Values::default();
100 values.bind(a);
101 for v in (&b).iter() {
102 values.bind(v);
103 }
104 for v in (&c).iter() {
105 values.bind(v);
106 }
107
108 assert_eq!(values.0, ["1", "2", "3", "4", "5", "6"]);
109 }
110}