@@ -239,9 +239,21 @@ mod tests {
239
239
(
240
240
"t" ,
241
241
ProductType :: from( [
242
- ( "int" , AlgebraicType :: U32 ) ,
242
+ ( "i8" , AlgebraicType :: I8 ) ,
243
+ ( "u8" , AlgebraicType :: U8 ) ,
244
+ ( "i16" , AlgebraicType :: I16 ) ,
245
+ ( "u16" , AlgebraicType :: U16 ) ,
246
+ ( "i32" , AlgebraicType :: I32 ) ,
243
247
( "u32" , AlgebraicType :: U32 ) ,
248
+ ( "i64" , AlgebraicType :: I64 ) ,
249
+ ( "u64" , AlgebraicType :: U64 ) ,
250
+ ( "int" , AlgebraicType :: U32 ) ,
244
251
( "f32" , AlgebraicType :: F32 ) ,
252
+ ( "f64" , AlgebraicType :: F64 ) ,
253
+ ( "i128" , AlgebraicType :: I128 ) ,
254
+ ( "u128" , AlgebraicType :: U128 ) ,
255
+ ( "i256" , AlgebraicType :: I256 ) ,
256
+ ( "u256" , AlgebraicType :: U256 ) ,
245
257
( "str" , AlgebraicType :: String ) ,
246
258
( "arr" , AlgebraicType :: array( AlgebraicType :: String ) ) ,
247
259
] ) ,
@@ -258,57 +270,224 @@ mod tests {
258
270
] )
259
271
}
260
272
273
+ #[ test]
274
+ fn valid_literals ( ) {
275
+ let tx = SchemaViewer ( module_def ( ) ) ;
276
+
277
+ struct TestCase {
278
+ sql : & ' static str ,
279
+ msg : & ' static str ,
280
+ }
281
+
282
+ for TestCase { sql, msg } in [
283
+ TestCase {
284
+ sql : "select * from t where i32 = -1" ,
285
+ msg : "Leading `-`" ,
286
+ } ,
287
+ TestCase {
288
+ sql : "select * from t where u32 = +1" ,
289
+ msg : "Leading `+`" ,
290
+ } ,
291
+ TestCase {
292
+ sql : "select * from t where u32 = 1e3" ,
293
+ msg : "Scientific notation" ,
294
+ } ,
295
+ TestCase {
296
+ sql : "select * from t where u32 = 1E3" ,
297
+ msg : "Case insensitive scientific notation" ,
298
+ } ,
299
+ TestCase {
300
+ sql : "select * from t where f32 = 1e3" ,
301
+ msg : "Integers can parse as floats" ,
302
+ } ,
303
+ TestCase {
304
+ sql : "select * from t where f32 = 1e-3" ,
305
+ msg : "Negative exponent" ,
306
+ } ,
307
+ TestCase {
308
+ sql : "select * from t where f32 = 0.1" ,
309
+ msg : "Standard decimal notation" ,
310
+ } ,
311
+ TestCase {
312
+ sql : "select * from t where f32 = .1" ,
313
+ msg : "Leading `.`" ,
314
+ } ,
315
+ TestCase {
316
+ sql : "select * from t where f32 = 1e40" ,
317
+ msg : "Infinity" ,
318
+ } ,
319
+ TestCase {
320
+ sql : "select * from t where u256 = 1e40" ,
321
+ msg : "u256" ,
322
+ } ,
323
+ ] {
324
+ let result = parse_and_type_sub ( sql, & tx) ;
325
+ assert ! ( result. is_ok( ) , "{msg}" ) ;
326
+ }
327
+ }
328
+
329
+ #[ test]
330
+ fn valid_literals_for_type ( ) {
331
+ let tx = SchemaViewer ( module_def ( ) ) ;
332
+
333
+ for ty in [
334
+ "i8" , "u8" , "i16" , "u16" , "i32" , "u32" , "i64" , "u64" , "f32" , "f64" , "i128" , "u128" , "i256" , "u256" ,
335
+ ] {
336
+ let sql = format ! ( "select * from t where {ty} = 127" ) ;
337
+ let result = parse_and_type_sub ( & sql, & tx) ;
338
+ assert ! ( result. is_ok( ) , "Faild to parse {ty}: {}" , result. unwrap_err( ) ) ;
339
+ }
340
+ }
341
+
342
+ #[ test]
343
+ fn invalid_literals ( ) {
344
+ let tx = SchemaViewer ( module_def ( ) ) ;
345
+
346
+ struct TestCase {
347
+ sql : & ' static str ,
348
+ msg : & ' static str ,
349
+ }
350
+
351
+ for TestCase { sql, msg } in [
352
+ TestCase {
353
+ sql : "select * from t where u8 = -1" ,
354
+ msg : "Negative integer for unsigned column" ,
355
+ } ,
356
+ TestCase {
357
+ sql : "select * from t where u8 = 1e3" ,
358
+ msg : "Out of bounds" ,
359
+ } ,
360
+ TestCase {
361
+ sql : "select * from t where u8 = 0.1" ,
362
+ msg : "Float as integer" ,
363
+ } ,
364
+ TestCase {
365
+ sql : "select * from t where u32 = 1e-3" ,
366
+ msg : "Float as integer" ,
367
+ } ,
368
+ TestCase {
369
+ sql : "select * from t where i32 = 1e-3" ,
370
+ msg : "Float as integer" ,
371
+ } ,
372
+ ] {
373
+ let result = parse_and_type_sub ( sql, & tx) ;
374
+ assert ! ( result. is_err( ) , "{msg}" ) ;
375
+ }
376
+ }
377
+
261
378
#[ test]
262
379
fn valid ( ) {
263
380
let tx = SchemaViewer ( module_def ( ) ) ;
264
381
265
- for sql in [
266
- "select * from t" ,
267
- "select * from t where true" ,
268
- "select * from t where t.u32 = 1" ,
269
- "select * from t where u32 = 1" ,
270
- "select * from t where t.u32 = 1 or t.str = ''" ,
271
- "select * from s where s.bytes = 0xABCD or bytes = X'ABCD'" ,
272
- "select * from s as r where r.bytes = 0xABCD or bytes = X'ABCD'" ,
273
- "select t.* from t join s" ,
274
- "select t.* from t join s join s as r where t.u32 = s.u32 and s.u32 = r.u32" ,
275
- "select t.* from t join s on t.u32 = s.u32 where t.f32 = 0.1" ,
382
+ struct TestCase {
383
+ sql : & ' static str ,
384
+ msg : & ' static str ,
385
+ }
386
+
387
+ for TestCase { sql, msg } in [
388
+ TestCase {
389
+ sql : "select * from t" ,
390
+ msg : "Can select * on any table" ,
391
+ } ,
392
+ TestCase {
393
+ sql : "select * from t where true" ,
394
+ msg : "Boolean literals are valid in WHERE clause" ,
395
+ } ,
396
+ TestCase {
397
+ sql : "select * from t where t.u32 = 1" ,
398
+ msg : "Can qualify column references with table name" ,
399
+ } ,
400
+ TestCase {
401
+ sql : "select * from t where u32 = 1" ,
402
+ msg : "Can leave columns unqualified when unambiguous" ,
403
+ } ,
404
+ TestCase {
405
+ sql : "select * from t where t.u32 = 1 or t.str = ''" ,
406
+ msg : "Type OR with qualified column references" ,
407
+ } ,
408
+ TestCase {
409
+ sql : "select * from s where s.bytes = 0xABCD or bytes = X'ABCD'" ,
410
+ msg : "Type OR with mixed qualified and unqualified column references" ,
411
+ } ,
412
+ TestCase {
413
+ sql : "select * from s as r where r.bytes = 0xABCD or bytes = X'ABCD'" ,
414
+ msg : "Type OR with table alias" ,
415
+ } ,
416
+ TestCase {
417
+ sql : "select t.* from t join s" ,
418
+ msg : "Type cross join + projection" ,
419
+ } ,
420
+ TestCase {
421
+ sql : "select t.* from t join s join s as r where t.u32 = s.u32 and s.u32 = r.u32" ,
422
+ msg : "Type self join + projection" ,
423
+ } ,
424
+ TestCase {
425
+ sql : "select t.* from t join s on t.u32 = s.u32 where t.f32 = 0.1" ,
426
+ msg : "Type inner join + projection" ,
427
+ } ,
276
428
] {
277
429
let result = parse_and_type_sub ( sql, & tx) ;
278
- assert ! ( result. is_ok( ) ) ;
430
+ assert ! ( result. is_ok( ) , "{msg}" ) ;
279
431
}
280
432
}
281
433
282
434
#[ test]
283
435
fn invalid ( ) {
284
436
let tx = SchemaViewer ( module_def ( ) ) ;
285
437
286
- for sql in [
287
- // Table r does not exist
288
- "select * from r" ,
289
- // Field a does not exist on table t
290
- "select * from t where t.a = 1" ,
291
- // Field a does not exist on table t
292
- "select * from t as r where r.a = 1" ,
293
- // Field u32 is not a string
294
- "select * from t where u32 = 'str'" ,
295
- // Field u32 is not a float
296
- "select * from t where t.u32 = 1.3" ,
297
- // t is not in scope after alias
298
- "select * from t as r where t.u32 = 5" ,
299
- // Subscriptions must be typed to a single table
300
- "select u32 from t" ,
301
- // Subscriptions must be typed to a single table
302
- "select * from t join s" ,
303
- // Self join requires aliases
304
- "select t.* from t join t" ,
305
- // Product values are not comparable
306
- "select t.* from t join s on t.arr = s.arr" ,
307
- // Alias r is not in scope when it is referenced
308
- "select t.* from t join s on t.u32 = r.u32 join s as r" ,
438
+ struct TestCase {
439
+ sql : & ' static str ,
440
+ msg : & ' static str ,
441
+ }
442
+
443
+ for TestCase { sql, msg } in [
444
+ TestCase {
445
+ sql : "select * from r" ,
446
+ msg : "Table r does not exist" ,
447
+ } ,
448
+ TestCase {
449
+ sql : "select * from t where t.a = 1" ,
450
+ msg : "Field a does not exist on table t" ,
451
+ } ,
452
+ TestCase {
453
+ sql : "select * from t as r where r.a = 1" ,
454
+ msg : "Field a does not exist on table t" ,
455
+ } ,
456
+ TestCase {
457
+ sql : "select * from t where u32 = 'str'" ,
458
+ msg : "Field u32 is not a string" ,
459
+ } ,
460
+ TestCase {
461
+ sql : "select * from t where t.u32 = 1.3" ,
462
+ msg : "Field u32 is not a float" ,
463
+ } ,
464
+ TestCase {
465
+ sql : "select * from t as r where t.u32 = 5" ,
466
+ msg : "t is not in scope after alias" ,
467
+ } ,
468
+ TestCase {
469
+ sql : "select u32 from t" ,
470
+ msg : "Subscriptions must be typed to a single table" ,
471
+ } ,
472
+ TestCase {
473
+ sql : "select * from t join s" ,
474
+ msg : "Subscriptions must be typed to a single table" ,
475
+ } ,
476
+ TestCase {
477
+ sql : "select t.* from t join t" ,
478
+ msg : "Self join requires aliases" ,
479
+ } ,
480
+ TestCase {
481
+ sql : "select t.* from t join s on t.arr = s.arr" ,
482
+ msg : "Product values are not comparable" ,
483
+ } ,
484
+ TestCase {
485
+ sql : "select t.* from t join s on t.u32 = r.u32 join s as r" ,
486
+ msg : "Alias r is not in scope when it is referenced" ,
487
+ } ,
309
488
] {
310
489
let result = parse_and_type_sub ( sql, & tx) ;
311
- assert ! ( result. is_err( ) ) ;
490
+ assert ! ( result. is_err( ) , "{msg}" ) ;
312
491
}
313
492
}
314
493
}
0 commit comments