sea_query_spanner/
query_builder.rs1use sea_query::{
2 backend::{
3 EscapeBuilder, OperLeftAssocDecider, PrecedenceDecider, QueryBuilder, QuotedBuilder,
4 TableRefBuilder,
5 },
6 BinOper, Oper, Quote, SelectInto, SimpleExpr, SqlWriter, SubQueryStatement, Value,
7};
8
9pub struct SpannerQueryBuilder;
10
11impl SpannerQueryBuilder {
12 pub fn new() -> Self {
13 Self
14 }
15}
16
17impl Default for SpannerQueryBuilder {
18 fn default() -> Self {
19 Self::new()
20 }
21}
22
23impl QuotedBuilder for SpannerQueryBuilder {
24 fn quote(&self) -> Quote {
25 Quote::new(b'`')
26 }
27}
28
29impl EscapeBuilder for SpannerQueryBuilder {
30 fn escape_string(&self, string: &str) -> String {
31 string.replace('\'', "''")
32 }
33
34 fn unescape_string(&self, string: &str) -> String {
35 string.replace("''", "'")
36 }
37}
38
39impl TableRefBuilder for SpannerQueryBuilder {}
40
41impl PrecedenceDecider for SpannerQueryBuilder {
42 fn inner_expr_well_known_greater_precedence(
43 &self,
44 inner: &SimpleExpr,
45 _outer_oper: &Oper,
46 ) -> bool {
47 matches!(
48 inner,
49 SimpleExpr::Column(_)
50 | SimpleExpr::Tuple(_)
51 | SimpleExpr::Constant(_)
52 | SimpleExpr::FunctionCall(_)
53 | SimpleExpr::Value(_)
54 | SimpleExpr::Keyword(_)
55 | SimpleExpr::Case(_)
56 | SimpleExpr::SubQuery(_, _)
57 )
58 }
59}
60
61impl OperLeftAssocDecider for SpannerQueryBuilder {
62 fn well_known_left_associative(&self, op: &BinOper) -> bool {
63 matches!(
64 op,
65 BinOper::And
66 | BinOper::Or
67 | BinOper::Add
68 | BinOper::Sub
69 | BinOper::Mul
70 | BinOper::Div
71 | BinOper::Mod
72 )
73 }
74}
75
76impl QueryBuilder for SpannerQueryBuilder {
77 fn placeholder(&self) -> (&'static str, bool) {
78 ("@p", true)
79 }
80
81 fn prepare_query_statement(&self, query: &SubQueryStatement, sql: &mut impl SqlWriter) {
82 match query {
83 SubQueryStatement::SelectStatement(stmt) => self.prepare_select_statement(stmt, sql),
84 SubQueryStatement::InsertStatement(stmt) => self.prepare_insert_statement(stmt, sql),
85 SubQueryStatement::UpdateStatement(stmt) => self.prepare_update_statement(stmt, sql),
86 SubQueryStatement::DeleteStatement(stmt) => self.prepare_delete_statement(stmt, sql),
87 SubQueryStatement::WithStatement(stmt) => self.prepare_with_query(stmt, sql),
88 }
89 }
90
91 fn prepare_select_into(&self, _: &SelectInto, _: &mut impl SqlWriter) {}
92
93 fn prepare_value(&self, value: Value, sql: &mut impl SqlWriter) {
94 sql.push_param(value, self as _);
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use {
101 super::*,
102 sea_query::{Alias, Expr, Query},
103 };
104
105 #[test]
106 fn test_select_basic() {
107 let query = Query::select()
108 .column(Alias::new("name"))
109 .from(Alias::new("users"))
110 .to_string(SpannerQueryBuilder);
111
112 assert_eq!(query, r#"SELECT `name` FROM `users`"#);
113 }
114
115 #[test]
116 fn test_select_with_where() {
117 let query = Query::select()
118 .column(Alias::new("name"))
119 .from(Alias::new("users"))
120 .and_where(Expr::col(Alias::new("id")).eq(1))
121 .to_string(SpannerQueryBuilder);
122
123 assert_eq!(query, r#"SELECT `name` FROM `users` WHERE `id` = 1"#);
124 }
125
126 #[test]
127 fn test_insert() {
128 let query = Query::insert()
129 .into_table(Alias::new("users"))
130 .columns([Alias::new("name"), Alias::new("email")])
131 .values_panic(["Alice".into(), "alice@example.com".into()])
132 .to_string(SpannerQueryBuilder);
133
134 assert_eq!(
135 query,
136 r#"INSERT INTO `users` (`name`, `email`) VALUES ('Alice', 'alice@example.com')"#
137 );
138 }
139
140 #[test]
141 fn test_update() {
142 let query = Query::update()
143 .table(Alias::new("users"))
144 .value(Alias::new("name"), "Bob")
145 .and_where(Expr::col(Alias::new("id")).eq(1))
146 .to_string(SpannerQueryBuilder);
147
148 assert_eq!(query, r#"UPDATE `users` SET `name` = 'Bob' WHERE `id` = 1"#);
149 }
150
151 #[test]
152 fn test_delete() {
153 let query = Query::delete()
154 .from_table(Alias::new("users"))
155 .and_where(Expr::col(Alias::new("id")).eq(1))
156 .to_string(SpannerQueryBuilder);
157
158 assert_eq!(query, r#"DELETE FROM `users` WHERE `id` = 1"#);
159 }
160
161 #[test]
162 fn test_placeholder() {
163 let builder = SpannerQueryBuilder::new();
164 assert_eq!(builder.placeholder(), ("@p", true));
165 }
166
167 #[test]
168 fn test_select_with_params() {
169 let (sql, values) = Query::select()
170 .column(Alias::new("name"))
171 .from(Alias::new("users"))
172 .and_where(Expr::col(Alias::new("id")).eq(1))
173 .and_where(Expr::col(Alias::new("active")).eq(true))
174 .build(SpannerQueryBuilder);
175
176 assert_eq!(
177 sql,
178 r#"SELECT `name` FROM `users` WHERE (`id` = @p1) AND (`active` = @p2)"#
179 );
180 assert_eq!(values.0.len(), 2);
181 }
182}