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