1use crate::{ParseError, ParseErrors, Parser, Position, Statement};
16
17pub fn parse_sql(sql: &str) -> Result<Vec<Statement>, ParseErrors> {
39 if sql.starts_with('\u{feff}') {
40 return Err(ParseErrors::from_errors_with_sql(
41 vec![ParseError::new(
42 "UTF-8 BOM is not allowed in SQL source".to_string(),
43 Position::new(0, 1, 1),
44 )],
45 sql,
46 ));
47 }
48 if sql.trim().is_empty() {
49 return Err(ParseErrors::from_errors_with_sql(
50 vec![ParseError::new(
51 "No statements found in query".to_string(),
52 Position::new(0, 1, 1),
53 )],
54 sql,
55 ));
56 }
57
58 let mut parser = Parser::new(sql);
59 let program = parser.parse_program()?;
60
61 if program.statements.is_empty() {
62 return Err(ParseErrors::from_errors_with_sql(
63 vec![ParseError::new(
64 "No statements found in query".to_string(),
65 Position::new(0, 1, 1),
66 )],
67 sql,
68 ));
69 }
70
71 Ok(program.statements)
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn test_parse_simple_select() {
80 let result = parse_sql("SELECT 1");
81 assert!(result.is_ok());
82 let statements = result.unwrap();
83 assert_eq!(statements.len(), 1);
84 }
85
86 #[test]
87 fn test_parse_select_from() {
88 let result = parse_sql("SELECT * FROM users");
89 assert!(result.is_ok());
90 let statements = result.unwrap();
91 assert_eq!(statements.len(), 1);
92 match &statements[0] {
93 Statement::Select(s) => {
94 assert!(!s.distinct);
95 assert_eq!(s.columns.len(), 1);
96 }
97 _ => panic!("Expected SELECT statement"),
98 }
99 }
100
101 #[test]
102 fn test_parse_empty_string() {
103 let result = parse_sql("");
104 assert!(result.is_err());
105 }
106
107 #[test]
108 fn test_parse_whitespace_only() {
109 let result = parse_sql(" \n\t ");
110 assert!(result.is_err());
111 }
112
113 #[test]
114 fn test_parse_select_with_where() {
115 let result = parse_sql("SELECT id, name FROM users WHERE id = 1");
116 assert!(result.is_ok());
117 let statements = result.unwrap();
118 assert_eq!(statements.len(), 1);
119 match &statements[0] {
120 Statement::Select(s) => {
121 assert_eq!(s.columns.len(), 2);
122 assert!(s.where_clause.is_some());
123 }
124 _ => panic!("Expected SELECT statement"),
125 }
126 }
127
128 #[test]
129 fn test_parse_insert() {
130 let result = parse_sql("INSERT INTO users (id, name) VALUES (1, 'Alice')");
131 assert!(result.is_ok());
132 let statements = result.unwrap();
133 assert_eq!(statements.len(), 1);
134 match &statements[0] {
135 Statement::Insert(s) => {
136 assert_eq!(s.table_name.value, "users");
137 assert_eq!(s.columns.len(), 2);
138 assert_eq!(s.values.len(), 1);
139 }
140 _ => panic!("Expected INSERT statement"),
141 }
142 }
143
144 #[test]
145 fn test_parse_update() {
146 let result = parse_sql("UPDATE users SET name = 'Bob' WHERE id = 1");
147 assert!(result.is_ok());
148 let statements = result.unwrap();
149 assert_eq!(statements.len(), 1);
150 match &statements[0] {
151 Statement::Update(s) => {
152 assert_eq!(s.table_name.value, "users");
153 assert!(s.where_clause.is_some());
154 }
155 _ => panic!("Expected UPDATE statement"),
156 }
157 }
158
159 #[test]
160 fn test_parse_delete() {
161 let result = parse_sql("DELETE FROM users WHERE id = 1");
162 assert!(result.is_ok());
163 let statements = result.unwrap();
164 assert_eq!(statements.len(), 1);
165 match &statements[0] {
166 Statement::Delete(s) => {
167 assert_eq!(s.table_name.value, "users");
168 assert!(s.where_clause.is_some());
169 }
170 _ => panic!("Expected DELETE statement"),
171 }
172 }
173
174 #[test]
175 fn test_parse_create_table() {
176 let result = parse_sql("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)");
177 assert!(result.is_ok());
178 let statements = result.unwrap();
179 assert_eq!(statements.len(), 1);
180 match &statements[0] {
181 Statement::CreateTable(s) => {
182 assert_eq!(s.table_name.value, "users");
183 assert_eq!(s.columns.len(), 2);
184 }
185 _ => panic!("Expected CREATE TABLE statement"),
186 }
187 }
188
189 #[test]
190 fn test_parse_complex_query() {
191 let result = parse_sql(
192 r#"
193 SELECT u.id, u.name, COUNT(o.id) as order_count
194 FROM users u
195 LEFT JOIN orders o ON u.id = o.user_id
196 WHERE u.active = TRUE
197 GROUP BY u.id, u.name
198 HAVING COUNT(o.id) > 0
199 ORDER BY order_count DESC
200 LIMIT 10
201 "#,
202 );
203 assert!(result.is_ok());
204 }
205
206 #[test]
207 fn test_parse_cte() {
208 let result = parse_sql("WITH temp AS (SELECT * FROM users) SELECT * FROM temp");
209 assert!(result.is_ok());
210 let statements = result.unwrap();
211 match &statements[0] {
212 Statement::Select(s) => {
213 assert!(s.with.is_some());
214 }
215 _ => panic!("Expected SELECT statement"),
216 }
217 }
218
219 #[test]
220 fn test_parse_transaction() {
221 let begin = parse_sql("BEGIN TRANSACTION").unwrap();
222 assert!(matches!(begin[0], Statement::Begin(_)));
223
224 let commit = parse_sql("COMMIT").unwrap();
225 assert!(matches!(commit[0], Statement::Commit(_)));
226
227 let rollback = parse_sql("ROLLBACK").unwrap();
228 assert!(matches!(rollback[0], Statement::Rollback(_)));
229 }
230}