os/persistentdata/persistentstorage/sqlite3api/TEST/TclScript/limit.test
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 # 2001 November 6
     2 #
     3 # The author disclaims copyright to this source code.  In place of
     4 # a legal notice, here is a blessing:
     5 #
     6 #    May you do good and not evil.
     7 #    May you find forgiveness for yourself and forgive others.
     8 #    May you share freely, never taking more than you give.
     9 #
    10 #***********************************************************************
    11 # This file implements regression tests for SQLite library.  The
    12 # focus of this file is testing the LIMIT ... OFFSET ... clause
    13 #  of SELECT statements.
    14 #
    15 # $Id: limit.test,v 1.32 2008/08/02 03:50:39 drh Exp $
    16 
    17 set testdir [file dirname $argv0]
    18 source $testdir/tester.tcl
    19 
    20 # Build some test data
    21 #
    22 execsql {
    23   CREATE TABLE t1(x int, y int);
    24   BEGIN;
    25 }
    26 for {set i 1} {$i<=32} {incr i} {
    27   for {set j 0} {(1<<$j)<$i} {incr j} {}
    28   execsql "INSERT INTO t1 VALUES([expr {32-$i}],[expr {10-$j}])"
    29 }
    30 execsql {
    31   COMMIT;
    32 }
    33 
    34 do_test limit-1.0 {
    35   execsql {SELECT count(*) FROM t1}
    36 } {32}
    37 do_test limit-1.1 {
    38   execsql {SELECT count(*) FROM t1 LIMIT  5}
    39 } {32}
    40 do_test limit-1.2.1 {
    41   execsql {SELECT x FROM t1 ORDER BY x LIMIT 5}
    42 } {0 1 2 3 4}
    43 do_test limit-1.2.2 {
    44   execsql {SELECT x FROM t1 ORDER BY x LIMIT 5 OFFSET 2}
    45 } {2 3 4 5 6}
    46 do_test limit-1.2.3 {
    47   execsql {SELECT x FROM t1 ORDER BY x+1 LIMIT 5 OFFSET -2}
    48 } {0 1 2 3 4}
    49 do_test limit-1.2.4 {
    50   execsql {SELECT x FROM t1 ORDER BY x+1 LIMIT 2, -5}
    51 } {2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31}
    52 do_test limit-1.2.5 {
    53   execsql {SELECT x FROM t1 ORDER BY x+1 LIMIT -2, 5}
    54 } {0 1 2 3 4}
    55 do_test limit-1.2.6 {
    56   execsql {SELECT x FROM t1 ORDER BY x+1 LIMIT -2, -5}
    57 } {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31}
    58 do_test limit-1.2.7 {
    59   execsql {SELECT x FROM t1 ORDER BY x LIMIT 2, 5}
    60 } {2 3 4 5 6}
    61 do_test limit-1.3 {
    62   execsql {SELECT x FROM t1 ORDER BY x LIMIT 5 OFFSET 5}
    63 } {5 6 7 8 9}
    64 do_test limit-1.4.1 {
    65   execsql {SELECT x FROM t1 ORDER BY x LIMIT 50 OFFSET 30}
    66 } {30 31}
    67 do_test limit-1.4.2 {
    68   execsql {SELECT x FROM t1 ORDER BY x LIMIT 30, 50}
    69 } {30 31}
    70 do_test limit-1.5 {
    71   execsql {SELECT x FROM t1 ORDER BY x LIMIT 50 OFFSET 50}
    72 } {}
    73 do_test limit-1.6 {
    74   execsql {SELECT * FROM t1 AS a, t1 AS b ORDER BY a.x, b.x LIMIT 5}
    75 } {0 5 0 5 0 5 1 5 0 5 2 5 0 5 3 5 0 5 4 5}
    76 do_test limit-1.7 {
    77   execsql {SELECT * FROM t1 AS a, t1 AS b ORDER BY a.x, b.x LIMIT 5 OFFSET 32}
    78 } {1 5 0 5 1 5 1 5 1 5 2 5 1 5 3 5 1 5 4 5}
    79 
    80 ifcapable {view && subquery} {
    81   do_test limit-2.1 {
    82     execsql {
    83       CREATE VIEW v1 AS SELECT * FROM t1 LIMIT 2;
    84       SELECT count(*) FROM (SELECT * FROM v1);
    85     }
    86   } 2
    87 } ;# ifcapable view
    88 do_test limit-2.2 {
    89   execsql {
    90     CREATE TABLE t2 AS SELECT * FROM t1 LIMIT 2;
    91     SELECT count(*) FROM t2;
    92   }
    93 } 2
    94 ifcapable subquery {
    95   do_test limit-2.3 {
    96     execsql {
    97       SELECT count(*) FROM t1 WHERE rowid IN (SELECT rowid FROM t1 LIMIT 2);
    98     }
    99   } 2
   100 }
   101 
   102 ifcapable subquery {
   103   do_test limit-3.1 {
   104     execsql {
   105       SELECT z FROM (SELECT y*10+x AS z FROM t1 ORDER BY x LIMIT 10)
   106       ORDER BY z LIMIT 5;
   107     }
   108   } {50 51 52 53 54}
   109 }
   110 
   111 do_test limit-4.1 {
   112   ifcapable subquery { 
   113     execsql {
   114       BEGIN;
   115       CREATE TABLE t3(x);
   116       INSERT INTO t3 SELECT x FROM t1 ORDER BY x LIMIT 10 OFFSET 1;
   117       INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
   118       INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
   119       INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
   120       INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
   121       INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
   122       INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
   123       INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
   124       INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
   125       INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
   126       INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
   127       END;
   128       SELECT count(*) FROM t3;
   129     }
   130   } else {
   131     execsql {
   132       BEGIN;
   133       CREATE TABLE t3(x);
   134       INSERT INTO t3 SELECT x FROM t1 ORDER BY x LIMIT 10 OFFSET 1;
   135     }
   136     for {set i 0} {$i<10} {incr i} {
   137       set max_x_t3 [execsql {SELECT max(x) FROM t3}]
   138       execsql "INSERT INTO t3 SELECT x+$max_x_t3 FROM t3;"
   139     }
   140     execsql {
   141       END;
   142       SELECT count(*) FROM t3;
   143     }
   144   }
   145 } {10240}
   146 do_test limit-4.2 {
   147   execsql {
   148     SELECT x FROM t3 LIMIT 2 OFFSET 10000
   149   }
   150 } {10001 10002}
   151 do_test limit-4.3 {
   152   execsql {
   153     CREATE TABLE t4 AS SELECT x,
   154        'abcdefghijklmnopqrstuvwyxz ABCDEFGHIJKLMNOPQRSTUVWYXZ' || x ||
   155        'abcdefghijklmnopqrstuvwyxz ABCDEFGHIJKLMNOPQRSTUVWYXZ' || x ||
   156        'abcdefghijklmnopqrstuvwyxz ABCDEFGHIJKLMNOPQRSTUVWYXZ' || x ||
   157        'abcdefghijklmnopqrstuvwyxz ABCDEFGHIJKLMNOPQRSTUVWYXZ' || x ||
   158        'abcdefghijklmnopqrstuvwyxz ABCDEFGHIJKLMNOPQRSTUVWYXZ' || x AS y
   159     FROM t3 LIMIT 1000;
   160     SELECT x FROM t4 ORDER BY y DESC LIMIT 1 OFFSET 999;
   161   }
   162 } {1000}
   163 
   164 do_test limit-5.1 {
   165   execsql {
   166     CREATE TABLE t5(x,y);
   167     INSERT INTO t5 SELECT x-y, x+y FROM t1 WHERE x BETWEEN 10 AND 15
   168         ORDER BY x LIMIT 2;
   169     SELECT * FROM t5 ORDER BY x;
   170   }
   171 } {5 15 6 16}
   172 do_test limit-5.2 {
   173   execsql {
   174     DELETE FROM t5;
   175     INSERT INTO t5 SELECT x-y, x+y FROM t1 WHERE x BETWEEN 10 AND 15
   176         ORDER BY x DESC LIMIT 2;
   177     SELECT * FROM t5 ORDER BY x;
   178   }
   179 } {9 19 10 20}
   180 do_test limit-5.3 {
   181   execsql {
   182     DELETE FROM t5;
   183     INSERT INTO t5 SELECT x-y, x+y FROM t1 WHERE x ORDER BY x DESC LIMIT 31;
   184     SELECT * FROM t5 ORDER BY x LIMIT 2;
   185   }
   186 } {-4 6 -3 7}
   187 do_test limit-5.4 {
   188   execsql {
   189     SELECT * FROM t5 ORDER BY x DESC, y DESC LIMIT 2;
   190   }
   191 } {21 41 21 39}
   192 do_test limit-5.5 {
   193   execsql {
   194     DELETE FROM t5;
   195     INSERT INTO t5 SELECT a.x*100+b.x, a.y*100+b.y FROM t1 AS a, t1 AS b
   196                    ORDER BY 1, 2 LIMIT 1000;
   197     SELECT count(*), sum(x), sum(y), min(x), max(x), min(y), max(y) FROM t5;
   198   }
   199 } {1000 1528204 593161 0 3107 505 1005}
   200 
   201 # There is some contraversy about whether LIMIT 0 should be the same as
   202 # no limit at all or if LIMIT 0 should result in zero output rows.
   203 #
   204 do_test limit-6.1 {
   205   execsql {
   206     BEGIN;
   207     CREATE TABLE t6(a);
   208     INSERT INTO t6 VALUES(1);
   209     INSERT INTO t6 VALUES(2);
   210     INSERT INTO t6 SELECT a+2 FROM t6;
   211     COMMIT;
   212     SELECT * FROM t6;
   213   }
   214 } {1 2 3 4}
   215 do_test limit-6.2 {
   216   execsql {
   217     SELECT * FROM t6 LIMIT -1 OFFSET -1;
   218   }
   219 } {1 2 3 4}
   220 do_test limit-6.3 {
   221   execsql {
   222     SELECT * FROM t6 LIMIT 2 OFFSET -123;
   223   }
   224 } {1 2}
   225 do_test limit-6.4 {
   226   execsql {
   227     SELECT * FROM t6 LIMIT -432 OFFSET 2;
   228   }
   229 } {3 4}
   230 do_test limit-6.5 {
   231   execsql {
   232     SELECT * FROM t6 LIMIT -1
   233   }
   234 } {1 2 3 4}
   235 do_test limit-6.6 {
   236   execsql {
   237     SELECT * FROM t6 LIMIT -1 OFFSET 1
   238   }
   239 } {2 3 4}
   240 do_test limit-6.7 {
   241   execsql {
   242     SELECT * FROM t6 LIMIT 0
   243   }
   244 } {}
   245 do_test limit-6.8 {
   246   execsql {
   247     SELECT * FROM t6 LIMIT 0 OFFSET 1
   248   }
   249 } {}
   250 
   251 # Make sure LIMIT works well with compound SELECT statements.
   252 # Ticket #393
   253 #
   254 ifcapable compound {
   255 do_test limit-7.1.1 {
   256   catchsql {
   257     SELECT x FROM t2 LIMIT 5 UNION ALL SELECT a FROM t6;
   258   }
   259 } {1 {LIMIT clause should come after UNION ALL not before}}
   260 do_test limit-7.1.2 {
   261   catchsql {
   262     SELECT x FROM t2 LIMIT 5 UNION SELECT a FROM t6;
   263   }
   264 } {1 {LIMIT clause should come after UNION not before}}
   265 do_test limit-7.1.3 {
   266   catchsql {
   267     SELECT x FROM t2 LIMIT 5 EXCEPT SELECT a FROM t6 LIMIT 3;
   268   }
   269 } {1 {LIMIT clause should come after EXCEPT not before}}
   270 do_test limit-7.1.4 {
   271   catchsql {
   272     SELECT x FROM t2 LIMIT 0,5 INTERSECT SELECT a FROM t6;
   273   }
   274 } {1 {LIMIT clause should come after INTERSECT not before}}
   275 do_test limit-7.2 {
   276   execsql {
   277     SELECT x FROM t2 UNION ALL SELECT a FROM t6 LIMIT 5;
   278   }
   279 } {31 30 1 2 3}
   280 do_test limit-7.3 {
   281   execsql {
   282     SELECT x FROM t2 UNION ALL SELECT a FROM t6 LIMIT 3 OFFSET 1;
   283   }
   284 } {30 1 2}
   285 do_test limit-7.4 {
   286   execsql {
   287     SELECT x FROM t2 UNION ALL SELECT a FROM t6 ORDER BY 1 LIMIT 3 OFFSET 1;
   288   }
   289 } {2 3 4}
   290 do_test limit-7.5 {
   291   execsql {
   292     SELECT x FROM t2 UNION SELECT x+2 FROM t2 LIMIT 2 OFFSET 1;
   293   }
   294 } {31 32}
   295 do_test limit-7.6 {
   296   execsql {
   297     SELECT x FROM t2 UNION SELECT x+2 FROM t2 ORDER BY 1 DESC LIMIT 2 OFFSET 1;
   298   }
   299 } {32 31}
   300 do_test limit-7.7 {
   301   execsql {
   302     SELECT a+9 FROM t6 EXCEPT SELECT y FROM t2 LIMIT 2;
   303   }
   304 } {11 12}
   305 do_test limit-7.8 {
   306   execsql {
   307     SELECT a+9 FROM t6 EXCEPT SELECT y FROM t2 ORDER BY 1 DESC LIMIT 2;
   308   }
   309 } {13 12}
   310 do_test limit-7.9 {
   311   execsql {
   312     SELECT a+26 FROM t6 INTERSECT SELECT x FROM t2 LIMIT 1;
   313   }
   314 } {30}
   315 do_test limit-7.10 {
   316   execsql {
   317     SELECT a+27 FROM t6 INTERSECT SELECT x FROM t2 LIMIT 1;
   318   }
   319 } {30}
   320 do_test limit-7.11 {
   321   execsql {
   322     SELECT a+27 FROM t6 INTERSECT SELECT x FROM t2 LIMIT 1 OFFSET 1;
   323   }
   324 } {31}
   325 do_test limit-7.12 {
   326   execsql {
   327     SELECT a+27 FROM t6 INTERSECT SELECT x FROM t2 
   328        ORDER BY 1 DESC LIMIT 1 OFFSET 1;
   329   }
   330 } {30}
   331 } ;# ifcapable compound
   332 
   333 # Tests for limit in conjunction with distinct.  The distinct should
   334 # occur before both the limit and the offset.  Ticket #749.
   335 #
   336 do_test limit-8.1 {
   337   execsql {
   338     SELECT DISTINCT cast(round(x/100) as integer) FROM t3 LIMIT 5;
   339   }
   340 } {0 1 2 3 4}
   341 do_test limit-8.2 {
   342   execsql {
   343     SELECT DISTINCT cast(round(x/100) as integer) FROM t3 LIMIT 5 OFFSET 5;
   344   }
   345 } {5 6 7 8 9}
   346 do_test limit-8.3 {
   347   execsql {
   348     SELECT DISTINCT cast(round(x/100) as integer) FROM t3 LIMIT 5 OFFSET 25;
   349   }
   350 } {25 26 27 28 29}
   351 
   352 # Make sure limits on multiple subqueries work correctly.
   353 # Ticket #1035
   354 #
   355 ifcapable subquery {
   356   do_test limit-9.1 {
   357     execsql {
   358       SELECT * FROM (SELECT * FROM t6 LIMIT 3);
   359     }
   360   } {1 2 3}
   361 }
   362 do_test limit-9.2.1 {
   363   execsql {
   364     CREATE TABLE t7 AS SELECT * FROM t6;
   365   }
   366 } {}
   367 ifcapable subquery {
   368   do_test limit-9.2.2 {
   369     execsql {
   370       SELECT * FROM (SELECT * FROM t7 LIMIT 3);
   371     }
   372   } {1 2 3}
   373 }
   374 ifcapable compound {
   375   ifcapable subquery {
   376     do_test limit-9.3 {
   377       execsql {
   378         SELECT * FROM (SELECT * FROM t6 LIMIT 3)
   379         UNION
   380         SELECT * FROM (SELECT * FROM t7 LIMIT 3)
   381         ORDER BY 1
   382       }
   383     } {1 2 3}
   384     do_test limit-9.4 {
   385       execsql {
   386         SELECT * FROM (SELECT * FROM t6 LIMIT 3)
   387         UNION
   388         SELECT * FROM (SELECT * FROM t7 LIMIT 3)
   389         ORDER BY 1
   390         LIMIT 2
   391       }
   392     } {1 2}
   393   }
   394   do_test limit-9.5 {
   395     catchsql {
   396       SELECT * FROM t6 LIMIT 3
   397       UNION
   398       SELECT * FROM t7 LIMIT 3
   399     }
   400   } {1 {LIMIT clause should come after UNION not before}}
   401 }
   402 
   403 # Test LIMIT and OFFSET using SQL variables.
   404 do_test limit-10.1 {
   405   set limit 10
   406   db eval {
   407     SELECT x FROM t1 LIMIT :limit;
   408   }
   409 } {31 30 29 28 27 26 25 24 23 22}
   410 do_test limit-10.2 {
   411   set limit 5
   412   set offset 5
   413   db eval {
   414     SELECT x FROM t1 LIMIT :limit OFFSET :offset;
   415   }
   416 } {26 25 24 23 22}
   417 do_test limit-10.3 {
   418   set limit -1
   419   db eval {
   420     SELECT x FROM t1 WHERE x<10 LIMIT :limit;
   421   }
   422 } {9 8 7 6 5 4 3 2 1 0}
   423 do_test limit-10.4 {
   424   set limit 1.5
   425   set rc [catch {
   426   db eval {
   427     SELECT x FROM t1 WHERE x<10 LIMIT :limit;
   428   } } msg]
   429   list $rc $msg
   430 } {1 {datatype mismatch}}
   431 do_test limit-10.5 {
   432   set limit "hello world"
   433   set rc [catch {
   434   db eval {
   435     SELECT x FROM t1 WHERE x<10 LIMIT :limit;
   436   } } msg]
   437   list $rc $msg
   438 } {1 {datatype mismatch}}
   439 
   440 ifcapable subquery {
   441 do_test limit-11.1 {
   442   db eval {
   443      SELECT x FROM (SELECT x FROM t1 ORDER BY x LIMIT 0) ORDER BY x
   444   }
   445 } {}
   446 } ;# ifcapable subquery
   447 
   448 # Test error processing.
   449 #
   450 do_test limit-12.1 {
   451   catchsql {
   452      SELECT * FROM t1 LIMIT replace(1)
   453   }
   454 } {1 {wrong number of arguments to function replace()}}
   455 do_test limit-12.2 {
   456   catchsql {
   457      SELECT * FROM t1 LIMIT 5 OFFSET replace(1)
   458   }
   459 } {1 {wrong number of arguments to function replace()}}
   460 do_test limit-12.3 {
   461   catchsql {
   462      SELECT * FROM t1 LIMIT x
   463   }
   464 } {1 {no such column: x}}
   465 do_test limit-12.4 {
   466   catchsql {
   467      SELECT * FROM t1 LIMIT 1 OFFSET x
   468   }
   469 } {1 {no such column: x}}
   470 
   471 
   472 finish_test