SQLite

Check-in [7c989db55c]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add tests for ORDER BY, LIMIT and OFFSET clauses to e_select.test.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 7c989db55cbe87dfb8659dcf534f72cdc2df3bc5
User & Date: dan 2010-09-16 18:51:09.000
Context
2010-09-16
19:49
Updates to the requirements on the sqlite3_create_function() family of interfaces. (check-in: f03c608993 user: drh tags: trunk)
18:51
Add tests for ORDER BY, LIMIT and OFFSET clauses to e_select.test. (check-in: 7c989db55c user: dan tags: trunk)
16:16
Further tweaks related to deleting files from malloc_common.tcl. (check-in: 3e649f80e2 user: dan tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to test/e_select.test.
2293
2294
2295
2296
2297
2298
2299































































































































































































































































































2300
2301

# EVIDENCE-OF: R-49925-55905 Otherwise, the BINARY collation sequence is
# used.
#
do_execsql_test e_select-8.12.1 {
  SELECT x FROM d4 ORDER BY x||''
} {DEF JKL abc ghi}
































































































































































































































































































finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588

# EVIDENCE-OF: R-49925-55905 Otherwise, the BINARY collation sequence is
# used.
#
do_execsql_test e_select-8.12.1 {
  SELECT x FROM d4 ORDER BY x||''
} {DEF JKL abc ghi}

# EVIDENCE-OF: R-44130-32593 If an ORDER BY expression is not an integer
# alias, then SQLite searches the left-most SELECT in the compound for a
# result column that matches either the second or third rules above. If
# a match is found, the search stops and the expression is handled as an
# alias for the result column that it has been matched against.
# Otherwise, the next SELECT to the right is tried, and so on.
#
do_execsql_test e_select-8.13.0 {
  CREATE TABLE d5(a, b);
  CREATE TABLE d6(c, d);
  CREATE TABLE d7(e, f);
 
  INSERT INTO d5 VALUES(1, 'f');
  INSERT INTO d6 VALUES(2, 'e');
  INSERT INTO d7 VALUES(3, 'd');
  INSERT INTO d5 VALUES(4, 'c');
  INSERT INTO d6 VALUES(5, 'b');
  INSERT INTO d7 VALUES(6, 'a');

  CREATE TABLE d8(x COLLATE nocase);
  CREATE TABLE d9(y COLLATE nocase);

  INSERT INTO d8 VALUES('a');
  INSERT INTO d9 VALUES('B');
  INSERT INTO d8 VALUES('c');
  INSERT INTO d9 VALUES('D');
} {}
foreach {tn select res} {
  1   { SELECT a FROM d5 UNION ALL SELECT c FROM d6 UNION ALL SELECT e FROM d7
         ORDER BY a
      } {1 2 3 4 5 6}
  2   { SELECT a FROM d5 UNION ALL SELECT c FROM d6 UNION ALL SELECT e FROM d7
         ORDER BY c
      } {1 2 3 4 5 6}
  3   { SELECT a FROM d5 UNION ALL SELECT c FROM d6 UNION ALL SELECT e FROM d7
         ORDER BY e
      } {1 2 3 4 5 6}
  4   { SELECT a FROM d5 UNION ALL SELECT c FROM d6 UNION ALL SELECT e FROM d7
         ORDER BY 1
      } {1 2 3 4 5 6}

  5   { SELECT a, b FROM d5 UNION ALL SELECT b, a FROM d5 ORDER BY b } 
      {f 1   c 4   4 c   1 f}
  6   { SELECT a, b FROM d5 UNION ALL SELECT b, a FROM d5 ORDER BY 2 } 
      {f 1   c 4   4 c   1 f}

  7   { SELECT a, b FROM d5 UNION ALL SELECT b, a FROM d5 ORDER BY a } 
      {1 f   4 c   c 4   f 1}
  8   { SELECT a, b FROM d5 UNION ALL SELECT b, a FROM d5 ORDER BY 1 } 
      {1 f   4 c   c 4   f 1}

  9   { SELECT a, b FROM d5 UNION ALL SELECT b, a+1 FROM d5 ORDER BY a+1 } 
      {f 2   c 5   4 c   1 f}
  10  { SELECT a, b FROM d5 UNION ALL SELECT b, a+1 FROM d5 ORDER BY 2 } 
      {f 2   c 5   4 c   1 f}

  11  { SELECT a+1, b FROM d5 UNION ALL SELECT b, a+1 FROM d5 ORDER BY a+1 } 
      {2 f   5 c   c 5   f 2}
  12  { SELECT a+1, b FROM d5 UNION ALL SELECT b, a+1 FROM d5 ORDER BY 1 } 
      {2 f   5 c   c 5   f 2}

} {
  do_execsql_test e_select-8.13.$tn $select [list {*}$res]
}

# EVIDENCE-OF: R-39265-04070 If no matching expression can be found in
# the result columns of any constituent SELECT, it is an error.
#
foreach {tn select idx} {
  1   { SELECT a FROM d5 UNION SELECT c FROM d6 ORDER BY a+1 }          1st
  2   { SELECT a FROM d5 UNION SELECT c FROM d6 ORDER BY a, a+1 }       2nd
  3   { SELECT * FROM d5 INTERSECT SELECT * FROM d6 ORDER BY 'hello' }  1st
  4   { SELECT * FROM d5 INTERSECT SELECT * FROM d6 ORDER BY blah    }  1st
  5   { SELECT * FROM d5 INTERSECT SELECT * FROM d6 ORDER BY c,d,c+d }  3rd
  6   { SELECT * FROM d5 EXCEPT SELECT * FROM d7 ORDER BY 1,2,b,a/b  }  4th
} {
  set err "$idx ORDER BY term does not match any column in the result set"
  do_catchsql_test e_select-8.14.$tn $select [list 1 $err]
}

# EVIDENCE-OF: R-03407-11483 Each term of the ORDER BY clause is
# processed separately and may be matched against result columns from
# different SELECT statements in the compound.
# 
foreach {tn select res} {
  1  { SELECT a, b FROM d5 UNION ALL SELECT c-1, d FROM d6 ORDER BY a, d }
     {1 e   1 f   4 b   4 c}
  2  { SELECT a, b FROM d5 UNION ALL SELECT c-1, d FROM d6 ORDER BY c-1, b }
     {1 e   1 f   4 b   4 c}
  3  { SELECT a, b FROM d5 UNION ALL SELECT c-1, d FROM d6 ORDER BY 1, 2 }
     {1 e   1 f   4 b   4 c}
} {
  do_execsql_test e_select-8.15.$tn $select [list {*}$res]
}


#-------------------------------------------------------------------------
# Tests related to statements made about the LIMIT/OFFSET clause.
#
do_execsql_test e_select-9.0 {
  CREATE TABLE f1(a, b);
  INSERT INTO f1 VALUES(26, 'z');
  INSERT INTO f1 VALUES(25, 'y');
  INSERT INTO f1 VALUES(24, 'x');
  INSERT INTO f1 VALUES(23, 'w');
  INSERT INTO f1 VALUES(22, 'v');
  INSERT INTO f1 VALUES(21, 'u');
  INSERT INTO f1 VALUES(20, 't');
  INSERT INTO f1 VALUES(19, 's');
  INSERT INTO f1 VALUES(18, 'r');
  INSERT INTO f1 VALUES(17, 'q');
  INSERT INTO f1 VALUES(16, 'p');
  INSERT INTO f1 VALUES(15, 'o');
  INSERT INTO f1 VALUES(14, 'n');
  INSERT INTO f1 VALUES(13, 'm');
  INSERT INTO f1 VALUES(12, 'l');
  INSERT INTO f1 VALUES(11, 'k');
  INSERT INTO f1 VALUES(10, 'j');
  INSERT INTO f1 VALUES(9, 'i');
  INSERT INTO f1 VALUES(8, 'h');
  INSERT INTO f1 VALUES(7, 'g');
  INSERT INTO f1 VALUES(6, 'f');
  INSERT INTO f1 VALUES(5, 'e');
  INSERT INTO f1 VALUES(4, 'd');
  INSERT INTO f1 VALUES(3, 'c');
  INSERT INTO f1 VALUES(2, 'b');
  INSERT INTO f1 VALUES(1, 'a');
} {}

# EVIDENCE-OF: R-30481-56627 Any scalar expression may be used in the
# LIMIT clause, so long as it evaluates to an integer or a value that
# can be losslessly converted to an integer.
#
foreach {tn select res} {
  1  { SELECT b FROM f1 ORDER BY a LIMIT 5 } {a b c d e}
  2  { SELECT b FROM f1 ORDER BY a LIMIT 2+3 } {a b c d e}
  3  { SELECT b FROM f1 ORDER BY a LIMIT (SELECT a FROM f1 WHERE b = 'e') } 
     {a b c d e}
  4  { SELECT b FROM f1 ORDER BY a LIMIT 5.0 } {a b c d e}
  5  { SELECT b FROM f1 ORDER BY a LIMIT '5' } {a b c d e}
} {
  do_execsql_test e_select-9.1.$tn $select [list {*}$res]
}

# EVIDENCE-OF: R-46155-47219 If the expression evaluates to a NULL value
# or any other value that cannot be losslessly converted to an integer,
# an error is returned.
#
foreach {tn select} {
  1  { SELECT b FROM f1 ORDER BY a LIMIT 'hello' } 
  2  { SELECT b FROM f1 ORDER BY a LIMIT NULL } 
  3  { SELECT b FROM f1 ORDER BY a LIMIT X'ABCD' } 
  4  { SELECT b FROM f1 ORDER BY a LIMIT 5.1 } 
  5  { SELECT b FROM f1 ORDER BY a LIMIT (SELECT group_concat(b) FROM f1) } 
} {
  do_catchsql_test e_select-9.2.$tn $select {1 {datatype mismatch}}
}

# EVIDENCE-OF: R-03014-26414 If the LIMIT expression evaluates to a
# negative value, then there is no upper bound on the number of rows
# returned.
#
foreach {tn select res} {
  1  { SELECT b FROM f1 ORDER BY a LIMIT -1 } 
     {a b c d e f g h i j k l m n o p q r s t u v w x y z}
  2  { SELECT b FROM f1 ORDER BY a LIMIT length('abc')-100 } 
     {a b c d e f g h i j k l m n o p q r s t u v w x y z}
  3  { SELECT b FROM f1 ORDER BY a LIMIT (SELECT count(*) FROM f1)/2 - 14 }
     {a b c d e f g h i j k l m n o p q r s t u v w x y z}
} {
  do_execsql_test e_select-9.4.$tn $select [list {*}$res]
}

# EVIDENCE-OF: R-33750-29536 Otherwise, the SELECT returns the first N
# rows of its result set only, where N is the value that the LIMIT
# expression evaluates to.
#
foreach {tn select res} {
  1  { SELECT b FROM f1 ORDER BY a LIMIT 0 } {}
  2  { SELECT b FROM f1 ORDER BY a DESC LIMIT 4 } {z y x w}
  3  { SELECT b FROM f1 ORDER BY a DESC LIMIT 8 } {z y x w v u t s}
  4  { SELECT b FROM f1 ORDER BY a DESC LIMIT '12.0' } {z y x w v u t s r q p o}
} {
  do_execsql_test e_select-9.5.$tn $select [list {*}$res]
}

# EVIDENCE-OF: R-54935-19057 Or, if the SELECT statement would return
# less than N rows without a LIMIT clause, then the entire result set is
# returned.
#
foreach {tn select res} {
  1  { SELECT b FROM f1 WHERE a>21 ORDER BY a LIMIT 10 } {v w x y z}
  2  { SELECT count(*) FROM f1 GROUP BY a/5 ORDER BY 1 LIMIT 10 } {2 4 5 5 5 5}
} {
  do_execsql_test e_select-9.6.$tn $select [list {*}$res]
}


# EVIDENCE-OF: R-24188-24349 The expression attached to the optional
# OFFSET clause that may follow a LIMIT clause must also evaluate to an
# integer, or a value that can be losslessly converted to an integer.
#
foreach {tn select} {
  1  { SELECT b FROM f1 ORDER BY a LIMIT 2 OFFSET 'hello' } 
  2  { SELECT b FROM f1 ORDER BY a LIMIT 2 OFFSET NULL } 
  3  { SELECT b FROM f1 ORDER BY a LIMIT 2 OFFSET X'ABCD' } 
  4  { SELECT b FROM f1 ORDER BY a LIMIT 2 OFFSET 5.1 } 
  5  { SELECT b FROM f1 ORDER BY a 
       LIMIT 2 OFFSET (SELECT group_concat(b) FROM f1) 
  } 
} {
  do_catchsql_test e_select-9.7.$tn $select {1 {datatype mismatch}}
}

# EVIDENCE-OF: R-20467-43422 If an expression has an OFFSET clause, then
# the first M rows are omitted from the result set returned by the
# SELECT statement and the next N rows are returned, where M and N are
# the values that the OFFSET and LIMIT clauses evaluate to,
# respectively.
#
foreach {tn select res} {
  1  { SELECT b FROM f1 ORDER BY a LIMIT 10 OFFSET 5} {f g h i j k l m n o}
  2  { SELECT b FROM f1 ORDER BY a LIMIT 2+3 OFFSET 10} {k l m n o}
  3  { SELECT b FROM f1 ORDER BY a 
       LIMIT  (SELECT a FROM f1 WHERE b='j') 
       OFFSET (SELECT a FROM f1 WHERE b='b') 
     } {c d e f g h i j k l}
  4  { SELECT b FROM f1 ORDER BY a LIMIT '5' OFFSET 3.0 } {d e f g h}
  5  { SELECT b FROM f1 ORDER BY a LIMIT '5' OFFSET 0 } {a b c d e}
  6  { SELECT b FROM f1 ORDER BY a LIMIT 0 OFFSET 10 } {}
  7  { SELECT b FROM f1 ORDER BY a LIMIT 3 OFFSET '1'||'5' } {p q r}
} {
  do_execsql_test e_select-9.8.$tn $select [list {*}$res]
}

# EVIDENCE-OF: R-34648-44875 Or, if the SELECT would return less than
# M+N rows if it did not have a LIMIT clause, then the first M rows are
# skipped and the remaining rows (if any) are returned.
#
foreach {tn select res} {
  1  { SELECT b FROM f1 ORDER BY a LIMIT 10 OFFSET 20} {u v w x y z}
  2  { SELECT a FROM f1 ORDER BY a DESC LIMIT 100 OFFSET 18+4} {4 3 2 1}
} {
  do_execsql_test e_select-9.9.$tn $select [list {*}$res]
}


# EVIDENCE-OF: R-23293-62447 If the OFFSET clause evaluates to a
# negative value, the results are the same as if it had evaluated to
# zero.
#
foreach {tn select res} {
  1  { SELECT b FROM f1 ORDER BY a LIMIT 5 OFFSET -1 } {a b c d e}
  2  { SELECT b FROM f1 ORDER BY a LIMIT 5 OFFSET -500 } {a b c d e}
  3  { SELECT b FROM f1 ORDER BY a LIMIT 5 OFFSET 0  } {a b c d e}
} {
  do_execsql_test e_select-9.10.$tn $select [list {*}$res]
}

# EVIDENCE-OF: R-19509-40356 Instead of a separate OFFSET clause, the
# LIMIT clause may specify two scalar expressions separated by a comma.
#
# EVIDENCE-OF: R-33788-46243 In this case, the first expression is used
# as the OFFSET expression and the second as the LIMIT expression.
#
foreach {tn select res} {
  1  { SELECT b FROM f1 ORDER BY a LIMIT 5, 10 } {f g h i j k l m n o}
  2  { SELECT b FROM f1 ORDER BY a LIMIT 10, 2+3 } {k l m n o}
  3  { SELECT b FROM f1 ORDER BY a 
       LIMIT (SELECT a FROM f1 WHERE b='b'), (SELECT a FROM f1 WHERE b='j') 
     } {c d e f g h i j k l}
  4  { SELECT b FROM f1 ORDER BY a LIMIT 3.0, '5' } {d e f g h}
  5  { SELECT b FROM f1 ORDER BY a LIMIT 0, '5' } {a b c d e}
  6  { SELECT b FROM f1 ORDER BY a LIMIT 10, 0 } {}
  7  { SELECT b FROM f1 ORDER BY a LIMIT '1'||'5', 3 } {p q r}

  8  { SELECT b FROM f1 ORDER BY a LIMIT 20, 10 } {u v w x y z}
  9  { SELECT a FROM f1 ORDER BY a DESC LIMIT 18+4, 100 } {4 3 2 1}

  10 { SELECT b FROM f1 ORDER BY a LIMIT -1, 5 } {a b c d e}
  11 { SELECT b FROM f1 ORDER BY a LIMIT -500, 5 } {a b c d e}
  12 { SELECT b FROM f1 ORDER BY a LIMIT 0, 5 } {a b c d e}
} {
  do_execsql_test e_select-9.11.$tn $select [list {*}$res]
}


finish_test