Skip to main content

sea_query_spanner/
query_builder.rs

1use 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}