1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use crate::arg::SqlArg;
pub trait Bind {
fn bind(&self, arg: &dyn SqlArg) -> String;
fn binds(&self, args: &[&dyn SqlArg]) -> String;
}
impl Bind for &str {
fn bind(&self, arg: &dyn SqlArg) -> String {
(*self).to_string().bind(arg)
}
fn binds(&self, args: &[&dyn SqlArg]) -> String {
(*self).to_string().binds(args)
}
}
impl Bind for String {
fn bind(&self, arg: &dyn SqlArg) -> String {
self.replacen('?', &arg.sql_arg(), 1)
}
fn binds(&self, args: &[&dyn SqlArg]) -> String {
let mut offset = 0;
let mut res = String::new();
let len = args.len();
for ch in self.chars() {
if ch == '?' {
res.push_str(&args[offset].sql_arg());
offset = (offset + 1) % len;
} else {
res.push(ch);
}
}
res
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::prelude::*;
use std::error::Error;
#[test]
fn test_bind() -> Result<(), Box<dyn Error + Send + Sync>> {
let foo = "f?o?o";
assert_eq!("'lol'foo?", &"?foo?".bind(&"lol"));
assert_eq!("'lol'foo10", &"?foo?".bind(&"lol").bind(&10));
assert_eq!("'lol'foo?", &"?foo?".bind(&String::from("lol")));
assert_eq!("'lol'foo?", &String::from("?foo?").bind(&"lol"));
assert_eq!("f'lol'o?o", &foo.bind(&"lol"));
assert_eq!("fo'f?o?o'o", &"fo?o".bind(&foo));
assert_eq!("fo10o", &"fo?o".bind(&10_usize));
assert_eq!("fo10o", &"fo?o".bind(&10));
assert_eq!("fo10o", &"fo?o".bind(&10_isize));
assert_eq!("foTRUEo", &"fo?o".bind(&true));
assert_eq!("foFALSEo", &"fo?o".bind(&false));
Ok(())
}
#[test]
fn test_binds() -> Result<(), Box<dyn Error + Send + Sync>> {
assert_eq!("10f20o30o10", &"?f?o?o?".binds(&[&10, &20, &30]));
assert_eq!(
"'abc'f'def'o'ghi'o'abc'",
&"?f?o?o?".binds(&[&"abc", &"def", &"ghi"])
);
assert_eq!(
"10f20o30o10",
&String::from("?f?o?o?").binds(&[&10, &20, &30])
);
assert_eq!(
"10f'AAA'oTRUEo10",
&String::from("?f?o?o?").binds(&[&10, &"AAA", &true])
);
Ok(())
}
#[test]
fn test_bind_doc() -> Result<(), Box<dyn Error + Send + Sync>> {
let sql = SqlBuilder::select_from("books")
.fields(&["title", "price"])
.and_where("price > ? AND title LIKE ?".binds(&[&100, &"Harry Potter%"]))
.sql()?;
assert_eq!(
"SELECT title, price FROM books WHERE price > 100 AND title LIKE 'Harry Potter%';",
&sql
);
Ok(())
}
}