/ Check-in [6ef91a36]
Login

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

Overview
Comment:Fix the parsing of the LIMIT clause when the limit and offset are separated by a comma. The offset comes before the limit in that case. Ticket #245. (CVS 872)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 6ef91a364b2922f078b7de81816bca3f2ca0fe46
User & Date: drh 2003-02-20 00:44:52
Context
2003-02-20
01:48
When the right table in a LEFT OUTER JOIN contains an INTEGER PRIMARY KEY make sure that key is NULL if there is no row in the right table that matches the current row in the left table. Tickets #246 and #247. (CVS 873) check-in: 6a45fe3b user: drh tags: trunk
00:44
Fix the parsing of the LIMIT clause when the limit and offset are separated by a comma. The offset comes before the limit in that case. Ticket #245. (CVS 872) check-in: 6ef91a36 user: drh tags: trunk
2003-02-16
22:49
Version 2.8.0 (CVS 870) check-in: 5db98b3f user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/parse.y.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.90 2003/01/29 18:46:53 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  if( pParse->zErrMsg==0 ){
................................................................................
%destructor having_opt {sqliteExprDelete($$);}
having_opt(A) ::= .                {A = 0;}
having_opt(A) ::= HAVING expr(X).  {A = X;}

%type limit_opt {struct LimitVal}
limit_opt(A) ::= .                  {A.limit = -1; A.offset = 0;}
limit_opt(A) ::= LIMIT INTEGER(X).  {A.limit = atoi(X.z); A.offset = 0;}
limit_opt(A) ::= LIMIT INTEGER(X) limit_sep INTEGER(Y). 
                                    {A.limit = atoi(X.z); A.offset = atoi(Y.z);}
limit_sep ::= OFFSET.
limit_sep ::= COMMA.

/////////////////////////// The DELETE statement /////////////////////////////
//
cmd ::= DELETE FROM nm(X) where_opt(Y).
    {sqliteDeleteFrom(pParse, &X, Y);}

%type where_opt {Expr*}







|







 







|

|
|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.91 2003/02/20 00:44:52 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  if( pParse->zErrMsg==0 ){
................................................................................
%destructor having_opt {sqliteExprDelete($$);}
having_opt(A) ::= .                {A = 0;}
having_opt(A) ::= HAVING expr(X).  {A = X;}

%type limit_opt {struct LimitVal}
limit_opt(A) ::= .                  {A.limit = -1; A.offset = 0;}
limit_opt(A) ::= LIMIT INTEGER(X).  {A.limit = atoi(X.z); A.offset = 0;}
limit_opt(A) ::= LIMIT INTEGER(X) OFFSET INTEGER(Y). 
                                    {A.limit = atoi(X.z); A.offset = atoi(Y.z);}
limit_opt(A) ::= LIMIT INTEGER(X) COMMA INTEGER(Y). 
                                    {A.limit = atoi(Y.z); A.offset = atoi(X.z);}

/////////////////////////// The DELETE statement /////////////////////////////
//
cmd ::= DELETE FROM nm(X) where_opt(Y).
    {sqliteDeleteFrom(pParse, &X, Y);}

%type where_opt {Expr*}

Changes to test/limit.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
33
34
35
36
37
38
39
40
41
42






43
44
45
46
47
48



49
50
51
52
53
54
55
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the LIMIT ... OFFSET ... clause
#  of SELECT statements.
#
# $Id: limit.test,v 1.6 2002/09/08 17:23:45 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Build some test data
#
set fd [open data1.txt w]
................................................................................

do_test limit-1.0 {
  execsql {SELECT count(*) FROM t1}
} {32}
do_test limit-1.1 {
  execsql {SELECT count(*) FROM t1 LIMIT  5}
} {32}
do_test limit-1.2 {
  execsql {SELECT x FROM t1 ORDER BY x LIMIT 5}
} {0 1 2 3 4}






do_test limit-1.3 {
  execsql {SELECT x FROM t1 ORDER BY x LIMIT 5 OFFSET 5}
} {5 6 7 8 9}
do_test limit-1.4 {
  execsql {SELECT x FROM t1 ORDER BY x LIMIT 50 OFFSET 30}
} {30 31}



do_test limit-1.5 {
  execsql {SELECT x FROM t1 ORDER BY x LIMIT 50 OFFSET 50}
} {}
do_test limit-1.6 {
  execsql {SELECT * FROM t1 AS a, t1 AS b ORDER BY a.x, b.x LIMIT 5}
} {0 5 0 5 0 5 1 5 0 5 2 5 0 5 3 5 0 5 4 5}
do_test limit-1.7 {







|







 







|


>
>
>
>
>
>



|


>
>
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the LIMIT ... OFFSET ... clause
#  of SELECT statements.
#
# $Id: limit.test,v 1.7 2003/02/20 00:44:53 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Build some test data
#
set fd [open data1.txt w]
................................................................................

do_test limit-1.0 {
  execsql {SELECT count(*) FROM t1}
} {32}
do_test limit-1.1 {
  execsql {SELECT count(*) FROM t1 LIMIT  5}
} {32}
do_test limit-1.2.1 {
  execsql {SELECT x FROM t1 ORDER BY x LIMIT 5}
} {0 1 2 3 4}
do_test limit-1.2.2 {
  execsql {SELECT x FROM t1 ORDER BY x LIMIT 5 OFFSET 2}
} {2 3 4 5 6}
do_test limit-1.2.3 {
  execsql {SELECT x FROM t1 ORDER BY x LIMIT 2, 5}
} {2 3 4 5 6}
do_test limit-1.3 {
  execsql {SELECT x FROM t1 ORDER BY x LIMIT 5 OFFSET 5}
} {5 6 7 8 9}
do_test limit-1.4.1 {
  execsql {SELECT x FROM t1 ORDER BY x LIMIT 50 OFFSET 30}
} {30 31}
do_test limit-1.4.2 {
  execsql {SELECT x FROM t1 ORDER BY x LIMIT 30, 50}
} {30 31}
do_test limit-1.5 {
  execsql {SELECT x FROM t1 ORDER BY x LIMIT 50 OFFSET 50}
} {}
do_test limit-1.6 {
  execsql {SELECT * FROM t1 AS a, t1 AS b ORDER BY a.x, b.x LIMIT 5}
} {0 5 0 5 0 5 1 5 0 5 2 5 0 5 3 5 0 5 4 5}
do_test limit-1.7 {