1
1
extern crate log;
2
2
extern crate sqlparser;
3
3
4
- use sqlparser:: dialect:: GenericSqlDialect ;
4
+ use sqlparser:: dialect:: * ;
5
5
use sqlparser:: sqlast:: * ;
6
6
use sqlparser:: sqlparser:: * ;
7
7
use sqlparser:: sqltokenizer:: * ;
@@ -10,7 +10,7 @@ use sqlparser::sqltokenizer::*;
10
10
fn parse_delete_statement ( ) {
11
11
let sql: & str = "DELETE FROM 'table'" ;
12
12
13
- match parse_sql ( & sql) {
13
+ match verified ( & sql) {
14
14
ASTNode :: SQLDelete { relation, .. } => {
15
15
assert_eq ! (
16
16
Some ( Box :: new( ASTNode :: SQLValue ( Value :: SingleQuotedString (
@@ -31,7 +31,7 @@ fn parse_where_delete_statement() {
31
31
use self :: ASTNode :: * ;
32
32
use self :: SQLOperator :: * ;
33
33
34
- match parse_sql ( & sql) {
34
+ match verified ( & sql) {
35
35
ASTNode :: SQLDelete {
36
36
relation,
37
37
selection,
@@ -61,8 +61,7 @@ fn parse_where_delete_statement() {
61
61
#[ test]
62
62
fn parse_simple_select ( ) {
63
63
let sql = String :: from ( "SELECT id, fname, lname FROM customer WHERE id = 1 LIMIT 5" ) ;
64
- let ast = parse_sql ( & sql) ;
65
- match ast {
64
+ match verified ( & sql) {
66
65
ASTNode :: SQLSelect {
67
66
projection, limit, ..
68
67
} => {
@@ -76,8 +75,7 @@ fn parse_simple_select() {
76
75
#[ test]
77
76
fn parse_select_wildcard ( ) {
78
77
let sql = String :: from ( "SELECT * FROM customer" ) ;
79
- let ast = parse_sql ( & sql) ;
80
- match ast {
78
+ match verified ( & sql) {
81
79
ASTNode :: SQLSelect { projection, .. } => {
82
80
assert_eq ! ( 1 , projection. len( ) ) ;
83
81
assert_eq ! ( ASTNode :: SQLWildcard , projection[ 0 ] ) ;
@@ -89,8 +87,7 @@ fn parse_select_wildcard() {
89
87
#[ test]
90
88
fn parse_select_count_wildcard ( ) {
91
89
let sql = String :: from ( "SELECT COUNT(*) FROM customer" ) ;
92
- let ast = parse_sql ( & sql) ;
93
- match ast {
90
+ match verified ( & sql) {
94
91
ASTNode :: SQLSelect { projection, .. } => {
95
92
assert_eq ! ( 1 , projection. len( ) ) ;
96
93
assert_eq ! (
@@ -111,7 +108,7 @@ fn parse_not() {
111
108
"SELECT id FROM customer \
112
109
WHERE NOT salary = ''",
113
110
) ;
114
- let _ast = parse_sql ( & sql) ;
111
+ let _ast = verified ( & sql) ;
115
112
//TODO: add assertions
116
113
}
117
114
@@ -121,14 +118,14 @@ fn parse_select_string_predicate() {
121
118
"SELECT id, fname, lname FROM customer \
122
119
WHERE salary != 'Not Provided' AND salary != ''",
123
120
) ;
124
- let _ast = parse_sql ( & sql) ;
121
+ let _ast = verified ( & sql) ;
125
122
//TODO: add assertions
126
123
}
127
124
128
125
#[ test]
129
126
fn parse_projection_nested_type ( ) {
130
127
let sql = String :: from ( "SELECT customer.address.state FROM foo" ) ;
131
- let _ast = parse_sql ( & sql) ;
128
+ let _ast = verified ( & sql) ;
132
129
//TODO: add assertions
133
130
}
134
131
@@ -137,7 +134,6 @@ fn parse_compound_expr_1() {
137
134
use self :: ASTNode :: * ;
138
135
use self :: SQLOperator :: * ;
139
136
let sql = String :: from ( "a + b * c" ) ;
140
- let ast = parse_sql ( & sql) ;
141
137
assert_eq ! (
142
138
SQLBinaryExpr {
143
139
left: Box :: new( SQLIdentifier ( "a" . to_string( ) ) ) ,
@@ -148,7 +144,7 @@ fn parse_compound_expr_1() {
148
144
right: Box :: new( SQLIdentifier ( "c" . to_string( ) ) )
149
145
} )
150
146
} ,
151
- ast
147
+ verified ( & sql )
152
148
) ;
153
149
}
154
150
@@ -157,7 +153,6 @@ fn parse_compound_expr_2() {
157
153
use self :: ASTNode :: * ;
158
154
use self :: SQLOperator :: * ;
159
155
let sql = String :: from ( "a * b + c" ) ;
160
- let ast = parse_sql ( & sql) ;
161
156
assert_eq ! (
162
157
SQLBinaryExpr {
163
158
left: Box :: new( SQLBinaryExpr {
@@ -168,33 +163,76 @@ fn parse_compound_expr_2() {
168
163
op: Plus ,
169
164
right: Box :: new( SQLIdentifier ( "c" . to_string( ) ) )
170
165
} ,
171
- ast
166
+ verified ( & sql )
172
167
) ;
173
168
}
174
169
175
170
#[ test]
176
171
fn parse_is_null ( ) {
177
172
use self :: ASTNode :: * ;
178
173
let sql = String :: from ( "a IS NULL" ) ;
179
- let ast = parse_sql ( & sql) ;
180
- assert_eq ! ( SQLIsNull ( Box :: new( SQLIdentifier ( "a" . to_string( ) ) ) ) , ast) ;
174
+ assert_eq ! (
175
+ SQLIsNull ( Box :: new( SQLIdentifier ( "a" . to_string( ) ) ) ) ,
176
+ verified( & sql)
177
+ ) ;
181
178
}
182
179
183
180
#[ test]
184
181
fn parse_is_not_null ( ) {
185
182
use self :: ASTNode :: * ;
186
183
let sql = String :: from ( "a IS NOT NULL" ) ;
187
- let ast = parse_sql ( & sql) ;
188
- assert_eq ! ( SQLIsNotNull ( Box :: new( SQLIdentifier ( "a" . to_string( ) ) ) ) , ast) ;
184
+ assert_eq ! (
185
+ SQLIsNotNull ( Box :: new( SQLIdentifier ( "a" . to_string( ) ) ) ) ,
186
+ verified( & sql)
187
+ ) ;
188
+ }
189
+
190
+ #[ test]
191
+ fn parse_like ( ) {
192
+ let sql = String :: from ( "SELECT * FROM customers WHERE name LIKE '%a'" ) ;
193
+ match verified ( & sql) {
194
+ ASTNode :: SQLSelect { selection, .. } => {
195
+ assert_eq ! (
196
+ ASTNode :: SQLBinaryExpr {
197
+ left: Box :: new( ASTNode :: SQLIdentifier ( "name" . to_string( ) ) ) ,
198
+ op: SQLOperator :: Like ,
199
+ right: Box :: new( ASTNode :: SQLValue ( Value :: SingleQuotedString (
200
+ "%a" . to_string( )
201
+ ) ) ) ,
202
+ } ,
203
+ * selection. unwrap( )
204
+ ) ;
205
+ }
206
+ _ => assert ! ( false ) ,
207
+ }
208
+ }
209
+
210
+ #[ test]
211
+ fn parse_not_like ( ) {
212
+ let sql = String :: from ( "SELECT * FROM customers WHERE name NOT LIKE '%a'" ) ;
213
+ match verified ( & sql) {
214
+ ASTNode :: SQLSelect { selection, .. } => {
215
+ assert_eq ! (
216
+ ASTNode :: SQLBinaryExpr {
217
+ left: Box :: new( ASTNode :: SQLIdentifier ( "name" . to_string( ) ) ) ,
218
+ op: SQLOperator :: NotLike ,
219
+ right: Box :: new( ASTNode :: SQLValue ( Value :: SingleQuotedString (
220
+ "%a" . to_string( )
221
+ ) ) ) ,
222
+ } ,
223
+ * selection. unwrap( )
224
+ ) ;
225
+ }
226
+ _ => assert ! ( false ) ,
227
+ }
189
228
}
190
229
191
230
#[ test]
192
231
fn parse_select_order_by ( ) {
193
232
let sql = String :: from (
194
233
"SELECT id, fname, lname FROM customer WHERE id < 5 ORDER BY lname ASC, fname DESC" ,
195
234
) ;
196
- let ast = parse_sql ( & sql) ;
197
- match ast {
235
+ match verified ( & sql) {
198
236
ASTNode :: SQLSelect { order_by, .. } => {
199
237
assert_eq ! (
200
238
Some ( vec![
@@ -246,8 +284,7 @@ fn parse_select_order_by_limit() {
246
284
#[ test]
247
285
fn parse_select_group_by ( ) {
248
286
let sql = String :: from ( "SELECT id, fname, lname FROM customer GROUP BY lname, fname" ) ;
249
- let ast = parse_sql ( & sql) ;
250
- match ast {
287
+ match verified ( & sql) {
251
288
ASTNode :: SQLSelect { group_by, .. } => {
252
289
assert_eq ! (
253
290
Some ( vec![
@@ -263,24 +300,16 @@ fn parse_select_group_by() {
263
300
264
301
#[ test]
265
302
fn parse_limit_accepts_all ( ) {
266
- let sql = String :: from ( "SELECT id, fname, lname FROM customer WHERE id = 1 LIMIT ALL" ) ;
267
- let ast = parse_sql ( & sql) ;
268
- match ast {
269
- ASTNode :: SQLSelect {
270
- projection, limit, ..
271
- } => {
272
- assert_eq ! ( 3 , projection. len( ) ) ;
273
- assert_eq ! ( None , limit) ;
274
- }
275
- _ => assert ! ( false ) ,
276
- }
303
+ parses_to (
304
+ "SELECT id, fname, lname FROM customer WHERE id = 1 LIMIT ALL" ,
305
+ "SELECT id, fname, lname FROM customer WHERE id = 1" ,
306
+ ) ;
277
307
}
278
308
279
309
#[ test]
280
310
fn parse_cast ( ) {
281
- let sql = String :: from ( "SELECT CAST(id AS BIGINT) FROM customer" ) ;
282
- let ast = parse_sql ( & sql) ;
283
- match ast {
311
+ let sql = String :: from ( "SELECT CAST(id AS bigint) FROM customer" ) ;
312
+ match verified ( & sql) {
284
313
ASTNode :: SQLSelect { projection, .. } => {
285
314
assert_eq ! ( 1 , projection. len( ) ) ;
286
315
assert_eq ! (
@@ -293,6 +322,10 @@ fn parse_cast() {
293
322
}
294
323
_ => assert ! ( false ) ,
295
324
}
325
+ parses_to (
326
+ "SELECT CAST(id AS BIGINT) FROM customer" ,
327
+ "SELECT CAST(id AS bigint) FROM customer" ,
328
+ ) ;
296
329
}
297
330
298
331
#[ test]
@@ -303,8 +336,14 @@ fn parse_create_table() {
303
336
lat DOUBLE NULL,\
304
337
lng DOUBLE NULL)",
305
338
) ;
306
- let ast = parse_sql ( & sql) ;
307
- match ast {
339
+ parses_to (
340
+ & sql,
341
+ "CREATE TABLE uk_cities (\
342
+ name character varying(100) NOT NULL, \
343
+ lat double, \
344
+ lng double)",
345
+ ) ;
346
+ match parse_sql ( & sql) {
308
347
ASTNode :: SQLCreateTable { name, columns } => {
309
348
assert_eq ! ( "uk_cities" , name) ;
310
349
assert_eq ! ( 3 , columns. len( ) ) ;
@@ -331,31 +370,31 @@ fn parse_create_table() {
331
370
#[ test]
332
371
fn parse_scalar_function_in_projection ( ) {
333
372
let sql = String :: from ( "SELECT sqrt(id) FROM foo" ) ;
334
- let ast = parse_sql ( & sql) ;
335
- if let ASTNode :: SQLSelect { projection, .. } = ast {
336
- assert_eq ! (
337
- vec![ ASTNode :: SQLFunction {
338
- id: String :: from( "sqrt" ) ,
339
- args: vec![ ASTNode :: SQLIdentifier ( String :: from( "id" ) ) ] ,
340
- } ] ,
341
- projection
342
- ) ;
343
- } else {
344
- assert ! ( false ) ;
373
+ match verified ( & sql) {
374
+ ASTNode :: SQLSelect { projection, .. } => {
375
+ assert_eq ! (
376
+ vec![ ASTNode :: SQLFunction {
377
+ id: String :: from( "sqrt" ) ,
378
+ args: vec![ ASTNode :: SQLIdentifier ( String :: from( "id" ) ) ] ,
379
+ } ] ,
380
+ projection
381
+ ) ;
382
+ }
383
+ _ => assert ! ( false ) ,
345
384
}
346
385
}
347
386
348
387
#[ test]
349
388
fn parse_aggregate_with_group_by ( ) {
350
389
let sql = String :: from ( "SELECT a, COUNT(1), MIN(b), MAX(b) FROM foo GROUP BY a" ) ;
351
- let _ast = parse_sql ( & sql) ;
390
+ let _ast = verified ( & sql) ;
352
391
//TODO: assertions
353
392
}
354
393
355
394
#[ test]
356
395
fn parse_literal_string ( ) {
357
396
let sql = "SELECT 'one'" ;
358
- match parse_sql ( & sql) {
397
+ match verified ( & sql) {
359
398
ASTNode :: SQLSelect { ref projection, .. } => {
360
399
assert_eq ! (
361
400
projection[ 0 ] ,
@@ -381,7 +420,7 @@ fn parse_simple_math_expr_minus() {
381
420
#[ test]
382
421
fn parse_select_version ( ) {
383
422
let sql = "SELECT @@version" ;
384
- match parse_sql ( & sql) {
423
+ match verified ( & sql) {
385
424
ASTNode :: SQLSelect { ref projection, .. } => {
386
425
assert_eq ! (
387
426
projection[ 0 ] ,
@@ -488,9 +527,9 @@ fn parse_delete_with_semi_colon() {
488
527
489
528
#[ test]
490
529
fn parse_implicit_join ( ) {
491
- let sql = "SELECT * FROM t1,t2" ;
530
+ let sql = "SELECT * FROM t1, t2" ;
492
531
493
- match parse_sql ( sql) {
532
+ match verified ( sql) {
494
533
ASTNode :: SQLSelect { joins, .. } => {
495
534
assert_eq ! ( joins. len( ) , 1 ) ;
496
535
assert_eq ! (
@@ -509,7 +548,7 @@ fn parse_implicit_join() {
509
548
fn parse_cross_join ( ) {
510
549
let sql = "SELECT * FROM t1 CROSS JOIN t2" ;
511
550
512
- match parse_sql ( sql) {
551
+ match verified ( sql) {
513
552
ASTNode :: SQLSelect { joins, .. } => {
514
553
assert_eq ! ( joins. len( ) , 1 ) ;
515
554
assert_eq ! (
@@ -595,10 +634,6 @@ fn parse_complex_join() {
595
634
596
635
#[ test]
597
636
fn parse_join_syntax_variants ( ) {
598
- fn parses_to ( from : & str , to : & str ) {
599
- assert_eq ! ( to, & parse_sql( from) . to_string( ) )
600
- }
601
-
602
637
parses_to (
603
638
"SELECT c1 FROM t1 INNER JOIN t2 USING(c1)" ,
604
639
"SELECT c1 FROM t1 JOIN t2 USING(c1)" ,
@@ -623,6 +658,10 @@ fn verified(query: &str) -> ASTNode {
623
658
ast
624
659
}
625
660
661
+ fn parses_to ( from : & str , to : & str ) {
662
+ assert_eq ! ( to, & parse_sql( from) . to_string( ) )
663
+ }
664
+
626
665
fn joins_from ( ast : ASTNode ) -> Vec < Join > {
627
666
match ast {
628
667
ASTNode :: SQLSelect { joins, .. } => joins,
@@ -631,8 +670,14 @@ fn joins_from(ast: ASTNode) -> Vec<Join> {
631
670
}
632
671
633
672
fn parse_sql ( sql : & str ) -> ASTNode {
634
- let dialect = GenericSqlDialect { } ;
635
- let mut tokenizer = Tokenizer :: new ( & dialect, & sql) ;
673
+ let generic_ast = parse_sql_with ( sql, & GenericSqlDialect { } ) ;
674
+ let pg_ast = parse_sql_with ( sql, & PostgreSqlDialect { } ) ;
675
+ assert_eq ! ( generic_ast, pg_ast) ;
676
+ generic_ast
677
+ }
678
+
679
+ fn parse_sql_with ( sql : & str , dialect : & Dialect ) -> ASTNode {
680
+ let mut tokenizer = Tokenizer :: new ( dialect, & sql) ;
636
681
let tokens = tokenizer. tokenize ( ) . unwrap ( ) ;
637
682
let mut parser = Parser :: new ( tokens) ;
638
683
let ast = parser. parse ( ) . unwrap ( ) ;
0 commit comments