1use crate::ast::{Expr, Statement};
2
3pub fn format_statement(statement: &Statement) -> String {
4 crate::ast::statement_to_sql(statement)
5}
6
7pub fn format_expr(expr: &Expr) -> String {
8 expr.to_sql()
9}
10
11#[cfg(test)]
12mod tests {
13 use super::format_statement;
14 use crate::ast::{InsertSource, SelectItem, SelectStatement, Statement, TableFactor, TableRef};
15
16 #[test]
17 fn format_simple_select() {
18 let stmt = Statement::Select(SelectStatement {
19 distinct: false,
20 distinct_on: Vec::new(),
21 projection: vec![SelectItem {
22 expr: crate::ast::Expr::Identifier("id".to_string()),
23 alias: None,
24 }],
25 from: Some(TableRef {
26 factor: TableFactor::Table {
27 name: "users".to_string(),
28 },
29 alias: None,
30 column_aliases: Vec::new(),
31 joins: Vec::new(),
32 }),
33 selection: None,
34 group_by: Vec::new(),
35 having: None,
36 qualify: None,
37 order_by: Vec::new(),
38 limit: None,
39 offset: None,
40 });
41 let output = format_statement(&stmt);
42 assert_eq!(output, "select id from users");
43 }
44
45 #[test]
46 fn format_update_statement() {
47 let stmt = Statement::Update(crate::ast::UpdateStatement {
48 table: "users".to_string(),
49 assignments: vec![crate::ast::Assignment {
50 column: "name".to_string(),
51 value: crate::ast::Expr::Literal(crate::ast::Literal::String("bob".to_string())),
52 }],
53 selection: Some(crate::ast::Expr::BinaryOp {
54 left: Box::new(crate::ast::Expr::Identifier("id".to_string())),
55 op: crate::ast::BinaryOperator::Eq,
56 right: Box::new(crate::ast::Expr::Literal(crate::ast::Literal::Number(1.0))),
57 }),
58 returning: Vec::new(),
59 });
60 let output = format_statement(&stmt);
61 assert_eq!(output, "update users set name = 'bob' where id = 1");
62 }
63
64 #[test]
65 fn format_insert_multi_values() {
66 let stmt = Statement::Insert(crate::ast::InsertStatement {
67 table: "users".to_string(),
68 columns: vec!["id".to_string(), "name".to_string()],
69 source: InsertSource::Values(vec![
70 vec![
71 crate::ast::Expr::Literal(crate::ast::Literal::Number(1.0)),
72 crate::ast::Expr::Literal(crate::ast::Literal::String("alice".to_string())),
73 ],
74 vec![
75 crate::ast::Expr::Literal(crate::ast::Literal::Number(2.0)),
76 crate::ast::Expr::Literal(crate::ast::Literal::String("bob".to_string())),
77 ],
78 ]),
79 returning: Vec::new(),
80 });
81 let output = format_statement(&stmt);
82 assert_eq!(
83 output,
84 "insert into users (id, name) values (1, 'alice'), (2, 'bob')"
85 );
86 }
87
88 #[test]
89 fn format_insert_default_values() {
90 let stmt = Statement::Insert(crate::ast::InsertStatement {
91 table: "users".to_string(),
92 columns: Vec::new(),
93 source: InsertSource::DefaultValues,
94 returning: Vec::new(),
95 });
96 let output = format_statement(&stmt);
97 assert_eq!(output, "insert into users default values");
98 }
99
100 #[test]
101 fn format_insert_select() {
102 let select = Statement::Select(SelectStatement {
103 distinct: false,
104 distinct_on: Vec::new(),
105 projection: vec![SelectItem {
106 expr: crate::ast::Expr::Identifier("id".to_string()),
107 alias: None,
108 }],
109 from: Some(TableRef {
110 factor: TableFactor::Table {
111 name: "staging".to_string(),
112 },
113 alias: None,
114 column_aliases: Vec::new(),
115 joins: Vec::new(),
116 }),
117 selection: None,
118 group_by: Vec::new(),
119 having: None,
120 qualify: None,
121 order_by: Vec::new(),
122 limit: None,
123 offset: None,
124 });
125 let stmt = Statement::Insert(crate::ast::InsertStatement {
126 table: "users".to_string(),
127 columns: vec!["id".to_string()],
128 source: InsertSource::Query(Box::new(select)),
129 returning: Vec::new(),
130 });
131 let output = format_statement(&stmt);
132 assert_eq!(output, "insert into users (id) select id from staging");
133 }
134
135 #[test]
136 fn format_select_without_from() {
137 let stmt = Statement::Select(SelectStatement {
138 distinct: false,
139 distinct_on: Vec::new(),
140 projection: vec![SelectItem {
141 expr: crate::ast::Expr::Literal(crate::ast::Literal::Number(1.0)),
142 alias: None,
143 }],
144 from: None,
145 selection: None,
146 group_by: Vec::new(),
147 having: None,
148 qualify: None,
149 order_by: Vec::new(),
150 limit: None,
151 offset: None,
152 });
153 let output = format_statement(&stmt);
154 assert_eq!(output, "select 1");
155 }
156
157 #[test]
158 fn format_select_without_from_with_order_limit() {
159 let stmt = Statement::Select(SelectStatement {
160 distinct: false,
161 distinct_on: Vec::new(),
162 projection: vec![SelectItem {
163 expr: crate::ast::Expr::Literal(crate::ast::Literal::Number(1.0)),
164 alias: None,
165 }],
166 from: None,
167 selection: None,
168 group_by: Vec::new(),
169 having: None,
170 qualify: None,
171 order_by: vec![crate::ast::OrderByExpr {
172 expr: crate::ast::Expr::Literal(crate::ast::Literal::Number(1.0)),
173 asc: true,
174 nulls_first: None,
175 }],
176 limit: Some(2),
177 offset: Some(1),
178 });
179 let output = format_statement(&stmt);
180 assert_eq!(output, "select 1 order by 1 asc limit 2 offset 1");
181 }
182
183 #[test]
184 fn format_create_table_if_not_exists() {
185 let stmt = Statement::CreateTable(crate::ast::CreateTableStatement {
186 name: "users".to_string(),
187 if_not_exists: true,
188 columns: Vec::new(),
189 });
190 let output = format_statement(&stmt);
191 assert_eq!(output, "create table if not exists users");
192 }
193
194 #[test]
195 fn format_create_table_with_columns() {
196 let stmt = Statement::CreateTable(crate::ast::CreateTableStatement {
197 name: "users".to_string(),
198 if_not_exists: false,
199 columns: vec![
200 crate::ast::ColumnDef {
201 name: "id".to_string(),
202 data_type: "integer".to_string(),
203 },
204 crate::ast::ColumnDef {
205 name: "name".to_string(),
206 data_type: "varchar(20)".to_string(),
207 },
208 ],
209 });
210 let output = format_statement(&stmt);
211 assert_eq!(output, "create table users (id integer, name varchar(20))");
212 }
213}