1#[macro_use]
2mod fmt;
3use fmt::ToSql;
4
5mod column;
6use column::ColumnAlias;
7
8mod cte;
9
10mod delim;
11use delim::{Comma, Delimited, Period};
12
13mod flavor;
14use flavor::Flavor;
15
16mod ident;
17use ident::Ident;
18
19mod params;
20pub use params::{Params, Placeholder, TypedValue};
21
22mod column_def;
24mod expr;
25mod name;
26mod statement;
27mod ty;
28mod value;
29
30use crate::stmt::Statement;
31
32use toasty_core::{
33 driver::operation::{IsolationLevel, Transaction},
34 schema::db::{self, Index, Table},
35};
36
37#[derive(Debug, Clone)]
39pub struct InsertContext {
40 pub table_id: db::TableId,
42 pub columns: Vec<db::ColumnId>,
44}
45
46#[derive(Debug)]
48pub struct Serializer<'a> {
49 schema: &'a db::Schema,
51
52 flavor: Flavor,
55}
56
57struct Formatter<'a, T> {
58 serializer: &'a Serializer<'a>,
60
61 dst: &'a mut String,
63
64 params: &'a mut T,
66
67 depth: usize,
70
71 alias: bool,
73
74 insert_context: Option<InsertContext>,
76}
77
78pub type ExprContext<'a> = toasty_core::stmt::ExprContext<'a, db::Schema>;
80
81impl<'a> Serializer<'a> {
82 pub fn serialize(&self, stmt: &Statement, params: &mut impl Params) -> String {
88 let mut ret = String::new();
89
90 let mut fmt = Formatter {
91 serializer: self,
92 dst: &mut ret,
93 params,
94 depth: 0,
95 alias: false,
96 insert_context: None,
97 };
98
99 let cx = ExprContext::new(self.schema);
100
101 stmt.to_sql(&cx, &mut fmt);
102
103 ret.push(';');
104 ret
105 }
106
107 pub fn serialize_transaction(&self, op: &Transaction) -> String {
112 let mut ret = String::new();
113
114 let mut f = Formatter {
115 serializer: self,
116 dst: &mut ret,
117 params: &mut Vec::<TypedValue>::new(),
118 depth: 0,
119 alias: false,
120 insert_context: None,
121 };
122
123 let cx = ExprContext::new(self.schema);
124
125 match op {
126 Transaction::Start {
127 isolation,
128 read_only,
129 } => fmt!(
130 &cx,
131 &mut f,
132 self.serialize_transaction_start(*isolation, *read_only)
133 ),
134 Transaction::Commit => fmt!(&cx, &mut f, "COMMIT"),
135 Transaction::Rollback => fmt!(&cx, &mut f, "ROLLBACK"),
136 Transaction::Savepoint(name) => {
137 fmt!(&cx, &mut f, "SAVEPOINT " Ident(name))
138 }
139 Transaction::ReleaseSavepoint(name) => {
140 fmt!(&cx, &mut f, "RELEASE SAVEPOINT " Ident(name))
141 }
142 Transaction::RollbackToSavepoint(name) => {
143 fmt!(&cx, &mut f, "ROLLBACK TO SAVEPOINT " Ident(name))
144 }
145 };
146
147 ret.push(';');
148 ret
149 }
150
151 fn serialize_transaction_start(
152 &self,
153 isolation: Option<IsolationLevel>,
154 read_only: bool,
155 ) -> String {
156 fn isolation_level_str(level: IsolationLevel) -> &'static str {
157 match level {
158 IsolationLevel::ReadUncommitted => "READ UNCOMMITTED",
159 IsolationLevel::ReadCommitted => "READ COMMITTED",
160 IsolationLevel::RepeatableRead => "REPEATABLE READ",
161 IsolationLevel::Serializable => "SERIALIZABLE",
162 }
163 }
164
165 match self.flavor {
166 Flavor::Mysql => {
167 let mut sql = String::new();
168 if let Some(level) = isolation {
169 sql.push_str("SET TRANSACTION ISOLATION LEVEL ");
170 sql.push_str(isolation_level_str(level));
171 sql.push_str("; ");
172 }
173 sql.push_str("START TRANSACTION");
174 if read_only {
175 sql.push_str(" READ ONLY");
176 }
177 sql
178 }
179 Flavor::Postgresql => {
180 let mut sql = String::from("BEGIN");
181 if let Some(level) = isolation {
182 sql.push_str(" ISOLATION LEVEL ");
183 sql.push_str(isolation_level_str(level));
184 }
185 if read_only {
186 sql.push_str(" READ ONLY");
187 }
188 sql
189 }
190 Flavor::Sqlite => {
191 "BEGIN".to_string()
193 }
194 }
195 }
196
197 fn table(&self, id: impl Into<db::TableId>) -> &'a Table {
198 self.schema.table(id.into())
199 }
200
201 fn index(&self, id: impl Into<db::IndexId>) -> &'a Index {
202 self.schema.index(id.into())
203 }
204
205 fn table_name(&self, id: impl Into<db::TableId>) -> Ident<&str> {
206 let table = self.schema.table(id.into());
207 Ident(&table.name)
208 }
209
210 fn column_name(&self, id: impl Into<db::ColumnId>) -> Ident<&str> {
211 let column = self.schema.column(id.into());
212 Ident(&column.name)
213 }
214}