/ Check-in [fc8c1393]
Login

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

Overview
Comment:Add initial infrastructure for cursors. In where.c, optimize out clauses of the form "ORDER BY rowid" if a table scan is being performed. Do a reverse table scan if "ORDER BY rowid DESC" is present. (CVS 2141)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:fc8c1393c86017a816beb52725b68af3b973f979
User & Date: drh 2004-11-22 19:12:20
Context
2004-11-23
01:47
More work on the implementation of cursors, but they are still not functioning. (CVS 2142) check-in: 8b61d1ae user: drh tags: trunk
2004-11-22
19:12
Add initial infrastructure for cursors. In where.c, optimize out clauses of the form "ORDER BY rowid" if a table scan is being performed. Do a reverse table scan if "ORDER BY rowid DESC" is present. (CVS 2141) check-in: fc8c1393 user: drh tags: trunk
19:07
Fix a long-standing bug in btree.c in the sqlite3BtreePrevious() routine. The problem has gone unnoticed before now because it only occurs when you use the OP_Prev opcode on a B+Tree. (CVS 2140) check-in: 3d2536c4 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to main.mk.

50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
..
67
68
69
70
71
72
73

74
75
76
77
78
79
80
...
221
222
223
224
225
226
227



228
229
230
231
232
233
234

# This is how we compile
#
TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src

# Object files for the SQLite library.
#
LIBOBJ+= attach.o auth.o btree.o build.o date.o delete.o \
         expr.o func.o hash.o insert.o \
         main.o opcodes.o os_mac.o os_unix.o os_win.o \
         pager.o parse.o pragma.o printf.o random.o \
         select.o table.o tclsqlite.o tokenize.o trigger.o \
         update.o util.o vacuum.o \
         vdbe.o vdbeapi.o vdbeaux.o vdbemem.o \
         where.o utf.o legacy.o
................................................................................
#
SRC = \
  $(TOP)/src/attach.c \
  $(TOP)/src/auth.c \
  $(TOP)/src/btree.c \
  $(TOP)/src/btree.h \
  $(TOP)/src/build.c \

  $(TOP)/src/date.c \
  $(TOP)/src/delete.c \
  $(TOP)/src/expr.c \
  $(TOP)/src/func.c \
  $(TOP)/src/hash.c \
  $(TOP)/src/hash.h \
  $(TOP)/src/insert.c \
................................................................................
	echo 'int main(){printf(' >>temp.c
	echo '"#define SQLITE_PTR_SZ %d",sizeof(char*));' >>temp.c
	echo 'exit(0);}' >>temp.c
	$(BCC) -o temp temp.c
	./temp >config.h
	echo >>config.h
	rm -f temp.c temp




date.o:	$(TOP)/src/date.c $(HDR)
	$(TCCX) -c $(TOP)/src/date.c

delete.o:	$(TOP)/src/delete.c $(HDR)
	$(TCCX) -c $(TOP)/src/delete.c








|







 







>







 







>
>
>







50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
..
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
...
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238

# This is how we compile
#
TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src

# Object files for the SQLite library.
#
LIBOBJ+= attach.o auth.o btree.o build.o cursor.o date.o delete.o \
         expr.o func.o hash.o insert.o \
         main.o opcodes.o os_mac.o os_unix.o os_win.o \
         pager.o parse.o pragma.o printf.o random.o \
         select.o table.o tclsqlite.o tokenize.o trigger.o \
         update.o util.o vacuum.o \
         vdbe.o vdbeapi.o vdbeaux.o vdbemem.o \
         where.o utf.o legacy.o
................................................................................
#
SRC = \
  $(TOP)/src/attach.c \
  $(TOP)/src/auth.c \
  $(TOP)/src/btree.c \
  $(TOP)/src/btree.h \
  $(TOP)/src/build.c \
  $(TOP)/src/cursor.c \
  $(TOP)/src/date.c \
  $(TOP)/src/delete.c \
  $(TOP)/src/expr.c \
  $(TOP)/src/func.c \
  $(TOP)/src/hash.c \
  $(TOP)/src/hash.h \
  $(TOP)/src/insert.c \
................................................................................
	echo 'int main(){printf(' >>temp.c
	echo '"#define SQLITE_PTR_SZ %d",sizeof(char*));' >>temp.c
	echo 'exit(0);}' >>temp.c
	$(BCC) -o temp temp.c
	./temp >config.h
	echo >>config.h
	rm -f temp.c temp

cursor.o:	$(TOP)/src/cursor.c $(HDR)
	$(TCCX) -c $(TOP)/src/cursor.c

date.o:	$(TOP)/src/date.c $(HDR)
	$(TCCX) -c $(TOP)/src/date.c

delete.o:	$(TOP)/src/delete.c $(HDR)
	$(TCCX) -c $(TOP)/src/delete.c

Added src/cursor.c.



















































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
32
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*
** 2004 November 21
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the DECLARE...CURSOR syntax
** of SQL and related processing.
**
** Do not confuse SQL cursors and B-tree cursors.  An SQL cursor (as
** implemented by this file) is a user-visible cursor that is created
** using the DECLARE...CURSOR command and deleted using CLOSE.  A
** B-tree cursor is an abstraction of the b-tree layer.  See the btree.c
** module for additional information.  There is also a VDBE-cursor that
** is used by the VDBE module.  Even though all these objects are called
** cursors, they are really very different things.  It is worth your while
** to fully understand the difference.
**
** @(#) $Id: cursor.c,v 1.1 2004/11/22 19:12:20 drh Exp $
*/
#ifndef SQLITE_OMIT_CURSOR
#include "sqliteInt.h"
#include "vdbeInt.h"

/*
** Delete a cursor object.
*/
void sqlite3CursorDelete(SqlCursor *p){
  if( p ){
    int i;
    sqlite3SelectDelete(p->pSelect);
    for(i=0; i<p->nPtr; i++){
      sqlite3VdbeMemRelease(&p->aPtr[i]);
    }
    sqliteFree(p->aPtr);
    sqliteFree(p);
  }
}

/*
** Look up a cursor by name.  Return NULL if not found.
*/
static SqlCursor *findCursor(sqlite3 *db, Token *pName){
  int i;
  SqlCursor *p;
  for(i=0; i<db->nSqlCursor; i++){
    p = db->apSqlCursor[i];
    if( p && sqlite3StrNICmp(p->zName, pName->z, pName->n)==0 ){
      return p;
    }
  }
  return 0;
}  

/*
** The parser calls this routine in order to create a new cursor.
** The arguments are the name of the new cursor and the SELECT statement
** that the new cursor will access.
*/
void sqlite3CursorCreate(Parse *pParse, Token *pName, Select *pSelect){
  SqlCursor *pNew;
  sqlite3 *db = pParse->db;
  int i;
  

  pNew = findCursor(db, pName);
  if( pNew ){
    sqlite3ErrorMsg(pParse, "another cursor named %T already exists", pName);
    goto end_create_cursor;
  }
  if( pSelect==0 ){
    /* This can only happen due to a prior malloc failure */
    goto end_create_cursor;
  }
  for(i=0; i<db->nSqlCursor; i++){
    if( db->apSqlCursor[i]==0 ) break;
  }
  if( i>=db->nSqlCursor ){
    db->apSqlCursor = sqliteRealloc(db->apSqlCursor, (i+1)*sizeof(pNew));
    db->nSqlCursor = i+1;
  }
  db->apSqlCursor[i] = pNew = sqliteMallocRaw( sizeof(*pNew) + pName->n + 1 );
  if( pNew==0 ) goto end_create_cursor;
  pNew->zName = (char*)&pNew[1];
  memcpy(pNew->zName, pName->z, pName->n);
  pNew->zName[pName->n] = 0;
  pNew->pSelect = sqlite3SelectDup(pSelect);
  pNew->nPtr = 0;
  pNew->aPtr = 0;
  pNew->idx = i;

end_create_cursor:
  sqlite3SelectDelete(pSelect);
}

/*
** The parser calls this routine in response to a CLOSE command.  Delete
** the cursor named in the argument.
*/
void sqlite3CursorClose(Parse *pParse, Token *pName){
  SqlCursor *p;
  sqlite3 *db = pParse->db;

  p = findCursor(db, pName);
  if( p==0 ){
    sqlite3ErrorMsg(pParse, "no such cursor: %T", pName);
    return;
  }
  assert( p->idx>=0 && p->idx<db->nSqlCursor );
  assert( db->apSqlCursor[p->idx]==p );
  db->apSqlCursor[p->idx] = 0;
  sqlite3CursorDelete(p);
}

/*
** The parser calls this routine when it sees a complete FETCH statement.
** This routine generates code to implement the FETCH.
**
** Information about the direction of the FETCH has already been inserted
** into the pParse structure by parser rules.  The arguments specify the
** name of the cursor from which we are fetching and the optional INTO
** clause.
*/
void sqlite3Fetch(Parse *pParse, Token *pName, IdList *pInto){
  SqlCursor *p;
  sqlite3 *db = pParse->db;
  Select *pCopy;
  Fetch sFetch;

  p = findCursor(db, pName);
  if( p==0 ){
    sqlite3ErrorMsg(pParse, "no such cursor: %T", pName);
    return;
  }
  sFetch.pCursor = p;
  pCopy = sqlite3SelectDup(p->pSelect);
  pCopy->pFetch = &sFetch;
  switch( pParse->fetchDir ){
    case TK_FIRST: {
      break;
    }
    case TK_LAST: {
      break;
    }
    case TK_NEXT: {
      break;
    }
    case TK_PRIOR: {
      break;
    }
    case TK_ABSOLUTE: {
      break;
    }
    default: {
      assert( pParse->fetchDir==TK_RELATIVE );
      break;
    }
  }
  sqlite3Select(pParse, pCopy, SRT_Callback, 0, 0, 0, 0, 0);
end_fetch:
  sqlite3IdListDelete(pInto);
}

#endif /* SQLITE_OMIT_CURSOR */

Changes to src/expr.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
499
500
501
502
503
504
505
506
507
508
509

510
511
512
513
514
515
516
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.172 2004/11/20 20:44:14 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Return the 'affinity' of the expression pExpr if any.
**
................................................................................
  pNew->pGroupBy = sqlite3ExprListDup(p->pGroupBy);
  pNew->pHaving = sqlite3ExprDup(p->pHaving);
  pNew->pOrderBy = sqlite3ExprListDup(p->pOrderBy);
  pNew->op = p->op;
  pNew->pPrior = sqlite3SelectDup(p->pPrior);
  pNew->nLimit = p->nLimit;
  pNew->nOffset = p->nOffset;
  pNew->zSelect = 0;
  pNew->iLimit = -1;
  pNew->iOffset = -1;
  pNew->ppOpenTemp = 0;

  return pNew;
}


/*
** Add a new element to the end of an expression list.  If pList is
** initially NULL, then create a new expression list.







|







 







<



>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
499
500
501
502
503
504
505

506
507
508
509
510
511
512
513
514
515
516
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.173 2004/11/22 19:12:20 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Return the 'affinity' of the expression pExpr if any.
**
................................................................................
  pNew->pGroupBy = sqlite3ExprListDup(p->pGroupBy);
  pNew->pHaving = sqlite3ExprDup(p->pHaving);
  pNew->pOrderBy = sqlite3ExprListDup(p->pOrderBy);
  pNew->op = p->op;
  pNew->pPrior = sqlite3SelectDup(p->pPrior);
  pNew->nLimit = p->nLimit;
  pNew->nOffset = p->nOffset;

  pNew->iLimit = -1;
  pNew->iOffset = -1;
  pNew->ppOpenTemp = 0;
  pNew->pFetch = 0;
  return pNew;
}


/*
** Add a new element to the end of an expression list.  If pList is
** initially NULL, then create a new expression list.

Changes to src/main.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
495
496
497
498
499
500
501







502
503
504
505
506
507
508
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.267 2004/11/22 05:26:27 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** The following constant value is used by the SQLITE_BIGENDIAN and
................................................................................
  sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
  if( db->pValue ){
    sqlite3ValueFree(db->pValue);
  }
  if( db->pErr ){
    sqlite3ValueFree(db->pErr);
  }








  db->magic = SQLITE_MAGIC_ERROR;
  sqliteFree(db);
  return SQLITE_OK;
}

/*







|







 







>
>
>
>
>
>
>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.268 2004/11/22 19:12:20 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** The following constant value is used by the SQLITE_BIGENDIAN and
................................................................................
  sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
  if( db->pValue ){
    sqlite3ValueFree(db->pValue);
  }
  if( db->pErr ){
    sqlite3ValueFree(db->pErr);
  }

#ifndef SQLITE_OMIT_CURSOR
  for(j=0; j<db->nSqlCursor; j++){
    sqlite3CursorDelete(db->apSqlCursor[j]);
  }
  sqliteFree(db->apSqlCursor);
#endif

  db->magic = SQLITE_MAGIC_ERROR;
  sqliteFree(db);
  return SQLITE_OK;
}

/*

Changes to src/parse.y.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
594
595
596
597
598
599
600



601
602
603
604
605
606
607
...
951
952
953
954
955
956
957





























**
*************************************************************************
** 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.157 2004/11/17 16:41:30 danielk1977 Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  if( pParse->zErrMsg==0 ){
................................................................................
  Expr *temp4 = sqlite3Expr(TK_DOT, temp2, temp3, 0);
  A = sqlite3Expr(TK_DOT, temp1, temp4, 0);
}
term(A) ::= INTEGER(X).      {A = sqlite3Expr(@X, 0, 0, &X);}
term(A) ::= FLOAT(X).        {A = sqlite3Expr(@X, 0, 0, &X);}
term(A) ::= STRING(X).       {A = sqlite3Expr(@X, 0, 0, &X);}
expr(A) ::= BLOB(X).         {A = sqlite3Expr(@X, 0, 0, &X);}



expr(A) ::= REGISTER(X).     {A = sqlite3RegisterExpr(pParse, &X);}
expr(A) ::= VARIABLE(X).     {
  Token *pToken = &X;
  Expr *pExpr = A = sqlite3Expr(TK_VARIABLE, 0, 0, pToken);
  sqlite3ExprAssignVarNumber(pParse, pExpr);
}
term(A) ::= ID(X) LP exprlist(Y) RP(E). {
................................................................................

//////////////////////// ALTER TABLE table ... ////////////////////////////////
%ifndef SQLITE_OMIT_ALTERTABLE
cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). {
  sqlite3AlterRenameTable(pParse,X,&Z);
}
%endif




































|







 







>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
...
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
**
*************************************************************************
** 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.158 2004/11/22 19:12:21 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  if( pParse->zErrMsg==0 ){
................................................................................
  Expr *temp4 = sqlite3Expr(TK_DOT, temp2, temp3, 0);
  A = sqlite3Expr(TK_DOT, temp1, temp4, 0);
}
term(A) ::= INTEGER(X).      {A = sqlite3Expr(@X, 0, 0, &X);}
term(A) ::= FLOAT(X).        {A = sqlite3Expr(@X, 0, 0, &X);}
term(A) ::= STRING(X).       {A = sqlite3Expr(@X, 0, 0, &X);}
expr(A) ::= BLOB(X).         {A = sqlite3Expr(@X, 0, 0, &X);}
%ifndef SQLITE_OMIT_CURSOR
expr(A) ::= CURRENT OF id.
%endif 
expr(A) ::= REGISTER(X).     {A = sqlite3RegisterExpr(pParse, &X);}
expr(A) ::= VARIABLE(X).     {
  Token *pToken = &X;
  Expr *pExpr = A = sqlite3Expr(TK_VARIABLE, 0, 0, pToken);
  sqlite3ExprAssignVarNumber(pParse, pExpr);
}
term(A) ::= ID(X) LP exprlist(Y) RP(E). {
................................................................................

//////////////////////// ALTER TABLE table ... ////////////////////////////////
%ifndef SQLITE_OMIT_ALTERTABLE
cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). {
  sqlite3AlterRenameTable(pParse,X,&Z);
}
%endif

////////////////////////////// CURSORS //////////////////////////////////////
%ifndef SQLITE_OMIT_CURSOR
cmd ::= DECLARE nm(X) CURSOR FOR select(Y).  {sqlite3CursorCreate(pParse,&X,Y);}
cmd ::= CLOSE nm(X).                         {sqlite3CursorClose(pParse,&X);}

cmd ::= FETCH direction FROM nm(N) into_opt(D).
                                      {sqlite3Fetch(pParse,&N,D);}

%type into_opt {IdList*}
%destructor into_opt {sqlite3IdListDelete($$);}
into_opt(A) ::= .                     {A = 0;}
into_opt(A) ::= INTO inscollist(X).   {A = X;}
direction ::= NEXT(X) count_opt(Y).   {pParse->fetchDir=@X; pParse->dirArg1=Y;}
direction ::= PRIOR(X) count_opt(Y).  {pParse->fetchDir=@X; pParse->dirArg1=Y;}
direction ::= FIRST(X) count_opt(Y).  {pParse->fetchDir=@X; pParse->dirArg1=Y;}
direction ::= LAST(X) count_opt(Y).   {pParse->fetchDir=@X; pParse->dirArg1=Y;}
direction ::= ABSOLUTE(X) signed(Z) comma_count_opt(Y).
                   {pParse->fetchDir=@X; pParse->dirArg1=Y; pParse->dirArg2=Z;}
direction ::= RELATIVE(X) signed(Z) comma_count_opt(Y).
                   {pParse->fetchDir=@X; pParse->dirArg1=Y; pParse->dirArg2=Z;}

%type count_opt {int}
count_opt(A) ::= .          {A = 1;}
count_opt(A) ::= signed(X). {A = X;}
%type comma_count_opt {int}
comma_count_opt(A) ::= .                 {A = 1;}
comma_count_opt(A) ::= COMMA signed(X).  {A = X;}
%endif // SQLITE_OMIT_CURSOR

Changes to src/pragma.c.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
474
475
476
477
478
479
480


















481
482
483
484
485
486
487
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.78 2004/11/13 15:59:15 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/* Ignore this whole file if pragmas are disabled
*/
#ifndef SQLITE_OMIT_PRAGMA
................................................................................
      sqlite3VdbeAddOp(v, OP_Integer, i, 0);
      sqlite3VdbeOp3(v, OP_String8, 0, 0, db->aDb[i].zName, 0);
      sqlite3VdbeOp3(v, OP_String8, 0, 0,
           sqlite3BtreeGetFilename(db->aDb[i].pBt), 0);
      sqlite3VdbeAddOp(v, OP_Callback, 3, 0);
    }
  }else


















#endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */

#ifndef SQLITE_OMIT_FOREIGN_KEY
  if( sqlite3StrICmp(zLeft, "foreign_key_list")==0 && zRight ){
    FKey *pFK;
    Table *pTab;
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;







|







 







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







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.79 2004/11/22 19:12:21 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/* Ignore this whole file if pragmas are disabled
*/
#ifndef SQLITE_OMIT_PRAGMA
................................................................................
      sqlite3VdbeAddOp(v, OP_Integer, i, 0);
      sqlite3VdbeOp3(v, OP_String8, 0, 0, db->aDb[i].zName, 0);
      sqlite3VdbeOp3(v, OP_String8, 0, 0,
           sqlite3BtreeGetFilename(db->aDb[i].pBt), 0);
      sqlite3VdbeAddOp(v, OP_Callback, 3, 0);
    }
  }else

#ifndef SQLITE_OMIT_CURSOR
  if( sqlite3StrICmp(zLeft, "cursor_list")==0 ){
    int i;
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
    sqlite3VdbeSetNumCols(v, 2);
    sqlite3VdbeSetColName(v, 0, "seq", P3_STATIC);
    sqlite3VdbeSetColName(v, 1, "name", P3_STATIC);
    for(i=0; i<db->nSqlCursor; i++){
      SqlCursor *p = db->apSqlCursor[i];
      if( p==0 ) continue;
      assert( p->zName!=0 );
      sqlite3VdbeAddOp(v, OP_Integer, i, 0);
      sqlite3VdbeOp3(v, OP_String8, 0, 0, p->zName, 0);
      sqlite3VdbeAddOp(v, OP_Callback, 2, 0);
    }
  }else
#endif /* SQLITE_OMIT_CURSOR */
#endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */

#ifndef SQLITE_OMIT_FOREIGN_KEY
  if( sqlite3StrICmp(zLeft, "foreign_key_list")==0 && zRight ){
    FKey *pFK;
    Table *pTab;
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;

Changes to src/select.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
....
2272
2273
2274
2275
2276
2277
2278






2279
2280
2281
2282
2283
2284
2285
....
2355
2356
2357
2358
2359
2360
2361




















2362
2363
2364
2365
2366
2367
2368
....
2518
2519
2520
2521
2522
2523
2524







2525
2526

2527
2528
2529
2530
2531
2532
2533
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.215 2004/11/22 10:02:11 danielk1977 Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
................................................................................
  sqlite3ExprListDelete(p->pEList);
  sqlite3SrcListDelete(p->pSrc);
  sqlite3ExprDelete(p->pWhere);
  sqlite3ExprListDelete(p->pGroupBy);
  sqlite3ExprDelete(p->pHaving);
  sqlite3ExprListDelete(p->pOrderBy);
  sqlite3SelectDelete(p->pPrior);
  sqliteFree(p->zSelect);
  sqliteFree(p);
}

/*
** Delete the aggregate information from the parse structure.
*/
static void sqliteAggregateInfoReset(Parse *pParse){
................................................................................
  if( sqlite3_malloc_failed || pParse->nErr || p==0 ) return 1;
  if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;

#ifndef SQLITE_OMIT_COMPOUND_SELECT
  /* If there is are a sequence of queries, do the earlier ones first.
  */
  if( p->pPrior ){






    return multiSelect(pParse, p, eDest, iParm, aff);
  }
#endif

  /* Make local copies of the parameters for this query.
  */
  pTabList = p->pSrc;
................................................................................
    }
  }
  if( processOrderGroupBy(pParse, pOrderBy, pTabList, pEList, isAgg, "ORDER")
   || processOrderGroupBy(pParse, pGroupBy, pTabList, pEList, isAgg, "GROUP")
  ){
    goto select_end;
  }





















  /* Begin generating code.
  */
  v = sqlite3GetVdbe(pParse);
  if( v==0 ) goto select_end;

  /* Identify column names if we will be using them in a callback.  This
................................................................................
    openTempIndex(pParse, p, distinct, 0);
  }else{
    distinct = -1;
  }

  /* Begin the database scan
  */







  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 
                            pGroupBy ? 0 : &pOrderBy);

  if( pWInfo==0 ) goto select_end;

  /* Use the standard inner loop if we are not dealing with
  ** aggregates
  */
  if( !isAgg ){
    if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest,







|







 







<







 







>
>
>
>
>
>







 







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







 







>
>
>
>
>
>
>
|
|
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
294
295
296
297
298
299
300

301
302
303
304
305
306
307
....
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
....
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
....
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.216 2004/11/22 19:12:21 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
................................................................................
  sqlite3ExprListDelete(p->pEList);
  sqlite3SrcListDelete(p->pSrc);
  sqlite3ExprDelete(p->pWhere);
  sqlite3ExprListDelete(p->pGroupBy);
  sqlite3ExprDelete(p->pHaving);
  sqlite3ExprListDelete(p->pOrderBy);
  sqlite3SelectDelete(p->pPrior);

  sqliteFree(p);
}

/*
** Delete the aggregate information from the parse structure.
*/
static void sqliteAggregateInfoReset(Parse *pParse){
................................................................................
  if( sqlite3_malloc_failed || pParse->nErr || p==0 ) return 1;
  if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;

#ifndef SQLITE_OMIT_COMPOUND_SELECT
  /* If there is are a sequence of queries, do the earlier ones first.
  */
  if( p->pPrior ){
#ifndef SQLITE_OMIT_CURSOR
    if( p->pFetch ){
      sqlite3ErrorMsg(pParse, "cursors cannot be used on compound queries");
      goto select_end;
    }
#endif
    return multiSelect(pParse, p, eDest, iParm, aff);
  }
#endif

  /* Make local copies of the parameters for this query.
  */
  pTabList = p->pSrc;
................................................................................
    }
  }
  if( processOrderGroupBy(pParse, pOrderBy, pTabList, pEList, isAgg, "ORDER")
   || processOrderGroupBy(pParse, pGroupBy, pTabList, pEList, isAgg, "GROUP")
  ){
    goto select_end;
  }

  /* We cannot use a SQL cursor on a join or on a DISTINCT query
  */
#ifndef SQLITE_OMIT_CURSOR
  if( p->pFetch ){
    if( p->isDistinct ){
      sqlite3ErrorMsg(pParse, "cursors cannot be used on DISTINCT queries");
      goto select_end;
    }
    if( pTabList->nSrc>0 ){
      sqlite3ErrorMsg(pParse, "cursors cannot be used on joins");
      goto select_end;
    }
    if( pTabList->a[0].pSelect ){
      sqlite3ErrorMsg(pParse, "cursor cannot be used with nested queries "
          "or views");
      goto select_end;
    }
  }
#endif

  /* Begin generating code.
  */
  v = sqlite3GetVdbe(pParse);
  if( v==0 ) goto select_end;

  /* Identify column names if we will be using them in a callback.  This
................................................................................
    openTempIndex(pParse, p, distinct, 0);
  }else{
    distinct = -1;
  }

  /* Begin the database scan
  */
#if 0 /* ndef SQLITE_OMIT_CURSOR */
  if( p->pFetch ){
    pWInfo = sqlite3WhereBeginFetch(pParse, pTabList, pWhere,
                                    pOrderby, p->pFetch);
  }else
#endif
  {
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0,
                               pGroupBy ? 0 : &pOrderBy);
  }
  if( pWInfo==0 ) goto select_end;

  /* Use the standard inner loop if we are not dealing with
  ** aggregates
  */
  if( !isAgg ){
    if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest,

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
303
304
305
306
307
308
309


310
311
312
313
314
315
316
...
416
417
418
419
420
421
422
423




424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
...
924
925
926
927
928
929
930










931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
...
954
955
956
957
958
959
960
961
962

963
964
965
966
967
968
969
....
1035
1036
1037
1038
1039
1040
1041





1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052

1053
1054
1055
1056
1057
1058
1059
....
1208
1209
1210
1211
1212
1213
1214












1215
1216
1217
1218
1219
1220
1221
....
1310
1311
1312
1313
1314
1315
1316

1317
1318
1319
1320
1321
1322
1323
....
1459
1460
1461
1462
1463
1464
1465







1466
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.342 2004/11/22 10:02:11 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** These #defines should enable >2GB file support on Posix if the
** underlying operating system supports it.  If the OS lacks
................................................................................
typedef struct TriggerStack TriggerStack;
typedef struct FKey FKey;
typedef struct Db Db;
typedef struct AuthContext AuthContext;
typedef struct KeyClass KeyClass;
typedef struct CollSeq CollSeq;
typedef struct KeyInfo KeyInfo;



/*
** Each database file to be accessed by the system is an instance
** of the following structure.  There are normally two of these structures
** in the sqlite.aDb[] array.  aDb[0] is the main database file and
** aDb[1] is the database file used to hold temporary tables.  Additional
** databases may be attached.
................................................................................
  void *pAuthArg;               /* 1st argument to the access auth function */
#endif
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  int (*xProgress)(void *);     /* The progress callback */
  void *pProgressArg;           /* Argument to the progress callback */
  int nProgressOps;             /* Number of opcodes for progress callback */
#endif





  int errCode;                  /* Most recent error code (SQLITE_*) */
  u8 enc;                       /* Text encoding for this database. */
  u8 autoCommit;                /* The auto-commit flag. */
  void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*);
  void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*);
  void *pCollNeededArg;
  sqlite3_value *pValue;        /* Value used for transient conversions */
  sqlite3_value *pErr;          /* Most recent error message */

  char *zErrMsg;                /* Most recent error message (UTF-8 encoded) */
  char *zErrMsg16;              /* Most recent error message (UTF-8 encoded) */
};

/*
** Possible values for the sqlite.flags and or Db.flags fields.
**
** On sqlite.flags, the SQLITE_InTrans value means that we have
** executed a BEGIN.  On Db.flags, SQLITE_InTrans means a statement
................................................................................
  SrcList *pTabList;   /* List of tables in the join */
  int iContinue;       /* Jump here to continue with next record */
  int iBreak;          /* Jump here to break out of the loop */
  int nLevel;          /* Number of nested loop */
  WhereLevel a[1];     /* Information about each nest loop in the WHERE */
};











/*
** An instance of the following structure contains all information
** needed to generate code for a single SELECT statement.
**
** The zSelect field is used when the Select structure must be persistent.
** Normally, the expression tree points to tokens in the original input
** string that encodes the select.  But if the Select structure must live
** longer than its input string (for example when it is used to describe
** a VIEW) we have to make a copy of the input string so that the nodes
** of the expression tree will have something to point to.  zSelect is used
** to hold that copy.
**
** nLimit is set to -1 if there is no LIMIT clause.  nOffset is set to 0.
** If there is a LIMIT clause, the parser sets nLimit to the value of the
** limit and nOffset to the value of the offset (or 0 if there is not
** offset).  But later on, nLimit and nOffset become the memory locations
** in the VDBE that record the limit and offset counters.
*/
struct Select {
................................................................................
  Expr *pWhere;          /* The WHERE clause */
  ExprList *pGroupBy;    /* The GROUP BY clause */
  Expr *pHaving;         /* The HAVING clause */
  ExprList *pOrderBy;    /* The ORDER BY clause */
  Select *pPrior;        /* Prior select in a compound select statement */
  int nLimit, nOffset;   /* LIMIT and OFFSET values.  -1 means not used */
  int iLimit, iOffset;   /* Memory registers holding LIMIT & OFFSET counters */
  char *zSelect;         /* Complete text of the SELECT command */
  IdList **ppOpenTemp;   /* OP_OpenTemp addresses used by multi-selects */

};

/*
** The results of a select can be distributed in several ways.
*/
#define SRT_Callback     1  /* Invoke a callback with each row of result */
#define SRT_Mem          2  /* Store result in a memory cell */
................................................................................
  int nVar;            /* Number of '?' variables seen in the SQL so far */
  int nVarExpr;        /* Number of used slots in apVarExpr[] */
  int nVarExprAlloc;   /* Number of allocated slots in apVarExpr[] */
  Expr **apVarExpr;    /* Pointers to :aaa and $aaaa wildcard expressions */
  u8 explain;          /* True if the EXPLAIN flag is found on the query */
  u8 useAgg;           /* If true, extract field values from the aggregator
                       ** while generating expressions.  Normally false */





  int nAgg;            /* Number of aggregate expressions */
  AggExpr *aAgg;       /* An array of aggregate expressions */
  Token sErrToken;     /* The token at which the error occurred */
  Token sNameToken;    /* Token with unqualified schema object name */
  Token sLastToken;    /* The last token parsed */
  const char *zSql;    /* All SQL text */
  const char *zTail;   /* All SQL text past the last semicolon parsed */
  Table *pNewTable;    /* A table being constructed by CREATE TABLE */
  Trigger *pNewTrigger;     /* Trigger under construct by a CREATE TRIGGER */
  TriggerStack *trigStack;  /* Trigger actions being coded */
  const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */

};

/*
** An instance of the following structure can be declared on a stack and used
** to save the Parse.zAuthContext value so that it can be restored later.
*/
struct AuthContext {
................................................................................
** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback.
*/
typedef struct {
  sqlite3 *db;        /* The database being initialized */
  char **pzErrMsg;    /* Error message stored here */
} InitData;














/*
 * This global flag is set for performance testing of triggers. When it is set
 * SQLite will perform the overhead of building new and old trigger references 
 * even when no triggers exist
 */
extern int sqlite3_always_code_trigger_setup;
................................................................................
Select *sqlite3SelectNew(ExprList*,SrcList*,Expr*,ExprList*,Expr*,ExprList*,
                        int,int,int);
void sqlite3SelectDelete(Select*);
void sqlite3SelectUnbind(Select*);
Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, int);
void sqlite3OpenTableForReading(Vdbe*, int iCur, Table*);

void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, int, ExprList**);
void sqlite3WhereEnd(WhereInfo*);
void sqlite3ExprCode(Parse*, Expr*);
int sqlite3ExprCodeExprList(Parse*, ExprList*);
void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
................................................................................
extern const unsigned char sqlite3UpperToLower[];
void sqlite3RootPageMoved(Db*, int, int);
void sqlite3Reindex(Parse*, Token*, Token*);
void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
int sqlite3GetToken(const unsigned char *, int *);
void sqlite3NestedParse(Parse*, const char*, ...);








#endif







|







 







>
>







 







<
>
>
>
>








<

|







 







>
>
>
>
>
>
>
>
>
>




<
<
<
<
<
<
<
<







 







<

>







 







>
>
>
>
>











>







 







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







 







>







 







>
>
>
>
>
>
>

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
...
418
419
420
421
422
423
424

425
426
427
428
429
430
431
432
433
434
435
436

437
438
439
440
441
442
443
444
445
...
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948








949
950
951
952
953
954
955
...
960
961
962
963
964
965
966

967
968
969
970
971
972
973
974
975
....
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
....
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
....
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
....
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.343 2004/11/22 19:12:21 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** These #defines should enable >2GB file support on Posix if the
** underlying operating system supports it.  If the OS lacks
................................................................................
typedef struct TriggerStack TriggerStack;
typedef struct FKey FKey;
typedef struct Db Db;
typedef struct AuthContext AuthContext;
typedef struct KeyClass KeyClass;
typedef struct CollSeq CollSeq;
typedef struct KeyInfo KeyInfo;
typedef struct SqlCursor SqlCursor;
typedef struct Fetch Fetch;

/*
** Each database file to be accessed by the system is an instance
** of the following structure.  There are normally two of these structures
** in the sqlite.aDb[] array.  aDb[0] is the main database file and
** aDb[1] is the database file used to hold temporary tables.  Additional
** databases may be attached.
................................................................................
  void *pAuthArg;               /* 1st argument to the access auth function */
#endif
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  int (*xProgress)(void *);     /* The progress callback */
  void *pProgressArg;           /* Argument to the progress callback */
  int nProgressOps;             /* Number of opcodes for progress callback */
#endif

#ifndef SQLITE_OMIT_CURSOR
  int nSqlCursor;               /* Number of slots in apSqlCursor[] */
  SqlCursor **apSqlCursor;      /* Pointers to all active SQL cursors */
#endif
  int errCode;                  /* Most recent error code (SQLITE_*) */
  u8 enc;                       /* Text encoding for this database. */
  u8 autoCommit;                /* The auto-commit flag. */
  void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*);
  void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*);
  void *pCollNeededArg;
  sqlite3_value *pValue;        /* Value used for transient conversions */
  sqlite3_value *pErr;          /* Most recent error message */

  char *zErrMsg;                /* Most recent error message (UTF-8 encoded) */
  char *zErrMsg16;              /* Most recent error message (UTF-16 encoded) */
};

/*
** Possible values for the sqlite.flags and or Db.flags fields.
**
** On sqlite.flags, the SQLITE_InTrans value means that we have
** executed a BEGIN.  On Db.flags, SQLITE_InTrans means a statement
................................................................................
  SrcList *pTabList;   /* List of tables in the join */
  int iContinue;       /* Jump here to continue with next record */
  int iBreak;          /* Jump here to break out of the loop */
  int nLevel;          /* Number of nested loop */
  WhereLevel a[1];     /* Information about each nest loop in the WHERE */
};

/*
** An instance of the following structure is used to store information
** about a single FETCH sql command.
*/
struct Fetch {
  SqlCursor *pCursor;  /* Cursor used by the fetch */
  int isBackwards;     /* Cursor moves backwards if true, forward if false */
  int doRewind;        /* True to rewind cursor before starting */
};

/*
** An instance of the following structure contains all information
** needed to generate code for a single SELECT statement.
**








** nLimit is set to -1 if there is no LIMIT clause.  nOffset is set to 0.
** If there is a LIMIT clause, the parser sets nLimit to the value of the
** limit and nOffset to the value of the offset (or 0 if there is not
** offset).  But later on, nLimit and nOffset become the memory locations
** in the VDBE that record the limit and offset counters.
*/
struct Select {
................................................................................
  Expr *pWhere;          /* The WHERE clause */
  ExprList *pGroupBy;    /* The GROUP BY clause */
  Expr *pHaving;         /* The HAVING clause */
  ExprList *pOrderBy;    /* The ORDER BY clause */
  Select *pPrior;        /* Prior select in a compound select statement */
  int nLimit, nOffset;   /* LIMIT and OFFSET values.  -1 means not used */
  int iLimit, iOffset;   /* Memory registers holding LIMIT & OFFSET counters */

  IdList **ppOpenTemp;   /* OP_OpenTemp addresses used by multi-selects */
  Fetch *pFetch;         /* If this stmt is part of a FETCH command */
};

/*
** The results of a select can be distributed in several ways.
*/
#define SRT_Callback     1  /* Invoke a callback with each row of result */
#define SRT_Mem          2  /* Store result in a memory cell */
................................................................................
  int nVar;            /* Number of '?' variables seen in the SQL so far */
  int nVarExpr;        /* Number of used slots in apVarExpr[] */
  int nVarExprAlloc;   /* Number of allocated slots in apVarExpr[] */
  Expr **apVarExpr;    /* Pointers to :aaa and $aaaa wildcard expressions */
  u8 explain;          /* True if the EXPLAIN flag is found on the query */
  u8 useAgg;           /* If true, extract field values from the aggregator
                       ** while generating expressions.  Normally false */
#ifndef SQLITE_OMIT_CURSOR
  u8 fetchDir;         /* The direction argument to the FETCH command */
  int dirArg1;         /* First argument to the direction */
  int dirArg2;         /* Second argument to the direction */
#endif
  int nAgg;            /* Number of aggregate expressions */
  AggExpr *aAgg;       /* An array of aggregate expressions */
  Token sErrToken;     /* The token at which the error occurred */
  Token sNameToken;    /* Token with unqualified schema object name */
  Token sLastToken;    /* The last token parsed */
  const char *zSql;    /* All SQL text */
  const char *zTail;   /* All SQL text past the last semicolon parsed */
  Table *pNewTable;    /* A table being constructed by CREATE TABLE */
  Trigger *pNewTrigger;     /* Trigger under construct by a CREATE TRIGGER */
  TriggerStack *trigStack;  /* Trigger actions being coded */
  const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
  
};

/*
** An instance of the following structure can be declared on a stack and used
** to save the Parse.zAuthContext value so that it can be restored later.
*/
struct AuthContext {
................................................................................
** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback.
*/
typedef struct {
  sqlite3 *db;        /* The database being initialized */
  char **pzErrMsg;    /* Error message stored here */
} InitData;

/*
** Each SQL cursor (a cursor created by the DECLARE ... CURSOR syntax)
** is represented by an instance of the following structure.
*/
struct SqlCursor {
  char *zName;           /* Name of this cursor */
  int idx;               /* Index of this cursor in db->apSqlCursor[] */
  Select *pSelect;       /* The SELECT statement that defines this cursor */
  int nPtr;              /* Number of slots in aPtr[] */
  sqlite3_value *aPtr;   /* Values that define the current cursor position */
};


/*
 * This global flag is set for performance testing of triggers. When it is set
 * SQLite will perform the overhead of building new and old trigger references 
 * even when no triggers exist
 */
extern int sqlite3_always_code_trigger_setup;
................................................................................
Select *sqlite3SelectNew(ExprList*,SrcList*,Expr*,ExprList*,Expr*,ExprList*,
                        int,int,int);
void sqlite3SelectDelete(Select*);
void sqlite3SelectUnbind(Select*);
Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, int);
void sqlite3OpenTableForReading(Vdbe*, int iCur, Table*);
void sqlite3OpenTable(Vdbe*, int iCur, Table*, int);
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, int, ExprList**);
void sqlite3WhereEnd(WhereInfo*);
void sqlite3ExprCode(Parse*, Expr*);
int sqlite3ExprCodeExprList(Parse*, ExprList*);
void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
................................................................................
extern const unsigned char sqlite3UpperToLower[];
void sqlite3RootPageMoved(Db*, int, int);
void sqlite3Reindex(Parse*, Token*, Token*);
void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
int sqlite3GetToken(const unsigned char *, int *);
void sqlite3NestedParse(Parse*, const char*, ...);

#ifndef SQLITE_OMIT_CURSOR
void sqlite3CursorDelete(SqlCursor*);
void sqlite3CursorCreate(Parse*, Token*, Select*);
void sqlite3CursorClose(Parse*, Token*);
void sqlite3Fetch(Parse*, Token*, IdList*);
#endif /* SQLITE_OMIT_CURSOR */

#endif

Changes to src/test1.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
....
2547
2548
2549
2550
2551
2552
2553






2554
2555
2556
2557
2558
2559
2560
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the printf() interface to SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.116 2004/11/20 19:18:01 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

................................................................................
#endif

#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
  Tcl_SetVar2(interp, "sqlite_options", "conflict", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "conflict", "1", TCL_GLOBAL_ONLY);
#endif







#ifdef SQLITE_OMIT_DATETIME_FUNCS
  Tcl_SetVar2(interp, "sqlite_options", "datetime", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "datetime", "1", TCL_GLOBAL_ONLY);
#endif








|







 







>
>
>
>
>
>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
....
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the printf() interface to SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.117 2004/11/22 19:12:21 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

................................................................................
#endif

#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
  Tcl_SetVar2(interp, "sqlite_options", "conflict", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "conflict", "1", TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_OMIT_CURSOR
  Tcl_SetVar2(interp, "sqlite_options", "cursor", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "cursor", "1", TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_OMIT_DATETIME_FUNCS
  Tcl_SetVar2(interp, "sqlite_options", "datetime", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "datetime", "1", TCL_GLOBAL_ONLY);
#endif

Changes to src/where.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
244
245
246
247
248
249
250




251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268

269
270
271
272
273
274
275
...
278
279
280
281
282
283
284
285

286
287

288
289
290
291
292
293
294
...
310
311
312
313
314
315
316
317
318

319


















320
321



322
323
324
325
326
327
328
...
611
612
613
614
615
616
617






618
619
620
621
622
623
624
...
731
732
733
734
735
736
737
738
739
740
741


742
743
744
745









746
747
748
749
750
751
752
753

754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
...
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
...
888
889
890
891
892
893
894

895
896
897





898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945

946
947
948







949
950
951
952
953
954
955
956
957
958
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.
**
** $Id: where.c,v 1.118 2004/11/22 10:02:20 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.
................................................................................
** equality constraints.  Any index returned must have exactly this same
** set of columns.  The ORDER BY clause only matches index columns beyond the
** the first nEqCol columns.
**
** All terms of the ORDER BY clause must be either ASC or DESC.  The
** *pbRev value is set to 1 if the ORDER BY clause is all DESC and it is
** set to 0 if the ORDER BY clause is all ASC.




*/
static Index *findSortingIndex(
  Parse *pParse,
  Table *pTab,            /* The table to be sorted */
  int base,               /* Cursor number for pTab */
  ExprList *pOrderBy,     /* The ORDER BY clause */
  Index *pPreferredIdx,   /* Use this index, if possible and not NULL */
  int nEqCol,             /* Number of index columns used with == constraints */
  int *pbRev              /* Set to 1 if ORDER BY is DESC */
){
  int i, j;
  Index *pMatch;
  Index *pIdx;
  int sortOrder;
  sqlite3 *db = pParse->db;

  assert( pOrderBy!=0 );
  assert( pOrderBy->nExpr>0 );

  sortOrder = pOrderBy->a[0].sortOrder;
  for(i=0; i<pOrderBy->nExpr; i++){
    Expr *p;
    if( pOrderBy->a[i].sortOrder!=sortOrder ){
      /* Indices can only be used if all ORDER BY terms are either
      ** DESC or ASC.  Indices cannot be used on a mixture. */
      return 0;
................................................................................
    if( p->op!=TK_COLUMN || p->iTable!=base ){
      /* Can not use an index sort on anything that is not a column in the
      ** left-most table of the FROM clause */
      return 0;
    }
  }

  /* If we get this far, it means the ORDER BY clause consists only of

  ** ascending columns in the left-most table of the FROM clause.  Now
  ** check for a matching index.

  */
  pMatch = 0;
  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
    int nExpr = pOrderBy->nExpr;
    if( pIdx->nColumn < nEqCol || pIdx->nColumn < nExpr ) continue;
    for(i=j=0; i<nEqCol; i++){
      CollSeq *pColl = sqlite3ExprCollSeq(pParse, pOrderBy->a[j].pExpr);
................................................................................
          pColl!=pIdx->keyInfo.aColl[i+nEqCol] ) break;
    }
    if( i+j>=nExpr ){
      pMatch = pIdx;
      if( pIdx==pPreferredIdx ) break;
    }
  }
  if( pMatch && pbRev ){
    *pbRev = sortOrder==SQLITE_SO_DESC;

  }


















  return pMatch;
}




/*
** Disable a term in the WHERE clause.  Except, do not disable the term
** if it controls a LEFT OUTER JOIN and it did not originate in the ON
** or USING clause of that join.
**
** Consider the term t2.z='ok' in the following queries:
................................................................................
          case TK_LE:
          case TK_LT: iDirectLt[i] = j; break;
          case TK_GE:
          case TK_GT: iDirectGt[i] = j;  break;
        }
      }
    }






    if( iDirectEq[i]>=0 ){
      loopMask |= mask;
      pLevel->pIdx = 0;
      continue;
    }

    /* Do a search for usable indices.  Leave pBestIdx pointing to
................................................................................
    }
  }

  /* Check to see if the ORDER BY clause is or can be satisfied by the
  ** use of an index on the first table.
  */
  if( ppOrderBy && *ppOrderBy && pTabList->nSrc>0 ){
     Index *pSortIdx;
     Index *pIdx;
     Table *pTab;
     int bRev = 0;



     pTab = pTabList->a[0].pTab;
     pIdx = pWInfo->a[0].pIdx;
     if( pIdx && pWInfo->a[0].score==4 ){









       /* If there is already an IN index on the left-most table,
       ** it will not give the correct sort order.
       ** So, pretend that no suitable index is found.
       */
       pSortIdx = 0;
     }else if( iDirectEq[0]>=0 || iDirectLt[0]>=0 || iDirectGt[0]>=0 ){
       /* If the left-most column is accessed using its ROWID, then do
       ** not try to sort by index.

       */
       pSortIdx = 0;
     }else{
       int nEqCol = (pWInfo->a[0].score+4)/8;
       pSortIdx = findSortingIndex(pParse, pTab, pTabList->a[0].iCursor, 
                                   *ppOrderBy, pIdx, nEqCol, &bRev);
     }
     if( pSortIdx && (pIdx==0 || pIdx==pSortIdx) ){
       if( pIdx==0 ){
         pWInfo->a[0].pIdx = pSortIdx;
         pWInfo->a[0].iCur = pParse->nTab++;
       }
       pWInfo->a[0].bRev = bRev;
       *ppOrderBy = 0;
     }
  }

  /* Open all tables in the pTabList and all indices used by those tables.
  */
  sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
................................................................................
      cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
      sqlite3VdbeAddOp(v, OP_MustBeInt, 1, brk);
      haveKey = 0;
      sqlite3VdbeAddOp(v, OP_NotExists, iCur, brk);
      pLevel->op = OP_Noop;
    }else if( pIdx!=0 && pLevel->score>0 && pLevel->score%4==0 ){
      /* Case 2:  There is an index and all terms of the WHERE clause that
      **          refer to the index use the "==" or "IN" operators.
      */
      int start;
      int nColumn = (pLevel->score+4)/8;
      brk = pLevel->brk = sqlite3VdbeMakeLabel(v);

      /* For each column of the index, find the term of the WHERE clause that
      ** constraints that column.  If the WHERE clause term is X=expr, then
................................................................................
      pLevel->p1 = pLevel->iCur;
      pLevel->p2 = start;
    }else if( i<ARRAYSIZE(iDirectLt) && (iDirectLt[i]>=0 || iDirectGt[i]>=0) ){
      /* Case 3:  We have an inequality comparison against the ROWID field.
      */
      int testOp = OP_Noop;
      int start;


      brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
      cont = pLevel->cont = sqlite3VdbeMakeLabel(v);





      if( iDirectGt[i]>=0 ){
        Expr *pX;
        k = iDirectGt[i];
        assert( k<nExpr );
        pTerm = &aExpr[k];
        pX = pTerm->p;
        assert( pX!=0 );
        assert( pTerm->idxLeft==iCur );
        sqlite3ExprCode(pParse, pX->pRight);
        sqlite3VdbeAddOp(v, OP_ForceInt, pX->op==TK_LT || pX->op==TK_GT, brk);
        sqlite3VdbeAddOp(v, OP_MoveGe, iCur, brk);
        disableTerm(pLevel, &pTerm->p);
      }else{
        sqlite3VdbeAddOp(v, OP_Rewind, iCur, brk);
      }
      if( iDirectLt[i]>=0 ){
        Expr *pX;
        k = iDirectLt[i];
        assert( k<nExpr );
        pTerm = &aExpr[k];
        pX = pTerm->p;
        assert( pX!=0 );
        assert( pTerm->idxLeft==iCur );
        sqlite3ExprCode(pParse, pX->pRight);
        pLevel->iMem = pParse->nMem++;
        sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
        if( pX->op==TK_LT || pX->op==TK_GT ){
          testOp = OP_Ge;
        }else{
          testOp = OP_Gt;
        }
        disableTerm(pLevel, &pTerm->p);
      }
      start = sqlite3VdbeCurrentAddr(v);
      pLevel->op = OP_Next;
      pLevel->p1 = iCur;
      pLevel->p2 = start;
      if( testOp!=OP_Noop ){
        sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
        sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
        sqlite3VdbeAddOp(v, testOp, 0, brk);
      }
      haveKey = 0;
    }else if( pIdx==0 ){
      /* Case 4:  There is no usable index.  We must do a complete
      **          scan of the entire database table.
      */
      int start;


      brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
      cont = pLevel->cont = sqlite3VdbeMakeLabel(v);







      sqlite3VdbeAddOp(v, OP_Rewind, iCur, brk);
      start = sqlite3VdbeCurrentAddr(v);
      pLevel->op = OP_Next;
      pLevel->p1 = iCur;
      pLevel->p2 = start;
      haveKey = 0;
    }else{
      /* Case 5: The WHERE clause term that refers to the right-most
      **         column of the index is an inequality.  For example, if
      **         the index is on (x,y,z) and the WHERE clause is of the







|







 







>
>
>
>


|







|
|
|
|




>







 







|
>
|
<
>







 







<
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>







 







>
>
>
>
>
>







 







|
|
|
|
>
>


<
<
>
>
>
>
>
>
>
>
>




<


|
>

<

|
|




|
|

|







 







|







 







>



>
>
>
>
>










|


|













|

|




|













>



>
>
>
>
>
>
>
|

<







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
...
283
284
285
286
287
288
289
290
291
292

293
294
295
296
297
298
299
300
...
316
317
318
319
320
321
322

323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
...
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
...
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778


779
780
781
782
783
784
785
786
787
788
789
790
791

792
793
794
795
796

797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
...
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
...
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005

1006
1007
1008
1009
1010
1011
1012
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.
**
** $Id: where.c,v 1.119 2004/11/22 19:12:21 drh Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.
................................................................................
** equality constraints.  Any index returned must have exactly this same
** set of columns.  The ORDER BY clause only matches index columns beyond the
** the first nEqCol columns.
**
** All terms of the ORDER BY clause must be either ASC or DESC.  The
** *pbRev value is set to 1 if the ORDER BY clause is all DESC and it is
** set to 0 if the ORDER BY clause is all ASC.
**
** TODO:  If earlier terms of an ORDER BY clause match all terms of a
** UNIQUE index, then subsequent terms of the ORDER BY can be ignored.
** This optimization needs to be implemented.
*/
static Index *findSortingIndex(
  Parse *pParse,          /* Parsing context */
  Table *pTab,            /* The table to be sorted */
  int base,               /* Cursor number for pTab */
  ExprList *pOrderBy,     /* The ORDER BY clause */
  Index *pPreferredIdx,   /* Use this index, if possible and not NULL */
  int nEqCol,             /* Number of index columns used with == constraints */
  int *pbRev              /* Set to 1 if ORDER BY is DESC */
){
  int i, j;                    /* Loop counters */
  Index *pMatch;               /* Best matching index so far */
  Index *pIdx;                 /* Current index */
  int sortOrder;               /* Which direction we are sorting */
  sqlite3 *db = pParse->db;

  assert( pOrderBy!=0 );
  assert( pOrderBy->nExpr>0 );
  assert( pPreferredIdx!=0 || nEqCol==0 );
  sortOrder = pOrderBy->a[0].sortOrder;
  for(i=0; i<pOrderBy->nExpr; i++){
    Expr *p;
    if( pOrderBy->a[i].sortOrder!=sortOrder ){
      /* Indices can only be used if all ORDER BY terms are either
      ** DESC or ASC.  Indices cannot be used on a mixture. */
      return 0;
................................................................................
    if( p->op!=TK_COLUMN || p->iTable!=base ){
      /* Can not use an index sort on anything that is not a column in the
      ** left-most table of the FROM clause */
      return 0;
    }
  }

  /* If we get this far, it means the ORDER BY clause consists of columns
  ** that are all either ascending or descending and which refer only to
  ** the left-most table of the FROM clause.  Find the index that is best

  ** used for sorting.
  */
  pMatch = 0;
  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
    int nExpr = pOrderBy->nExpr;
    if( pIdx->nColumn < nEqCol || pIdx->nColumn < nExpr ) continue;
    for(i=j=0; i<nEqCol; i++){
      CollSeq *pColl = sqlite3ExprCollSeq(pParse, pOrderBy->a[j].pExpr);
................................................................................
          pColl!=pIdx->keyInfo.aColl[i+nEqCol] ) break;
    }
    if( i+j>=nExpr ){
      pMatch = pIdx;
      if( pIdx==pPreferredIdx ) break;
    }
  }

  *pbRev = sortOrder==SQLITE_SO_DESC;
  return pMatch;
}

/*
** Check table to see if the ORDER BY clause in pOrderBy can be satisfied
** by sorting in order of ROWID.  Return true if so and set *pbRev to be
** true for reverse ROWID and false for forward ROWID order.
*/
static int sortableByRowid(
  int base,               /* Cursor number for table to be sorted */
  ExprList *pOrderBy,     /* The ORDER BY clause */
  int *pbRev              /* Set to 1 if ORDER BY is DESC */
){
  Expr *p;

  assert( pOrderBy!=0 );
  assert( pOrderBy->nExpr>0 );
  p = pOrderBy->a[0].pExpr;
  if( p->op==TK_COLUMN && p->iTable==base && p->iColumn==-1 ){
    *pbRev = pOrderBy->a[0].sortOrder;
    return 1;
  }
  return 0;
}


/*
** Disable a term in the WHERE clause.  Except, do not disable the term
** if it controls a LEFT OUTER JOIN and it did not originate in the ON
** or USING clause of that join.
**
** Consider the term t2.z='ok' in the following queries:
................................................................................
          case TK_LE:
          case TK_LT: iDirectLt[i] = j; break;
          case TK_GE:
          case TK_GT: iDirectGt[i] = j;  break;
        }
      }
    }

    /* If we found a term that tests ROWID with == or IN, that term
    ** will be used to locate the rows in the database table.  There
    ** is not need to continue into the code below that looks for
    ** an index.  We will always use the ROWID over an index.
    */
    if( iDirectEq[i]>=0 ){
      loopMask |= mask;
      pLevel->pIdx = 0;
      continue;
    }

    /* Do a search for usable indices.  Leave pBestIdx pointing to
................................................................................
    }
  }

  /* Check to see if the ORDER BY clause is or can be satisfied by the
  ** use of an index on the first table.
  */
  if( ppOrderBy && *ppOrderBy && pTabList->nSrc>0 ){
     Index *pSortIdx = 0;     /* Index that satisfies the ORDER BY clause */
     Index *pIdx;             /* Index derived from the WHERE clause */
     Table *pTab;             /* Left-most table in the FROM clause */
     int bRev = 0;            /* True to reverse the output order */
     int iCur;                /* Btree-cursor that will be used by pTab */
     WhereLevel *pLevel0 = &pWInfo->a[0];

     pTab = pTabList->a[0].pTab;


     pIdx = pLevel0->pIdx;
     iCur = pTabList->a[0].iCursor;
     if( pIdx==0 && sortableByRowid(iCur, *ppOrderBy, &bRev) ){
       /* The ORDER BY clause specifies ROWID order, which is what we
       ** were going to be doing anyway...
       */
       *ppOrderBy = 0;
       pLevel0->bRev = bRev;
     }else if( pLevel0->score==4 ){
       /* If there is already an IN index on the left-most table,
       ** it will not give the correct sort order.
       ** So, pretend that no suitable index is found.
       */

     }else if( iDirectEq[0]>=0 || iDirectLt[0]>=0 || iDirectGt[0]>=0 ){
       /* If the left-most column is accessed using its ROWID, then do
       ** not try to sort by index.  But do delete the ORDER BY clause
       ** if it is redundant.
       */

     }else{
       int nEqCol = (pLevel0->score+4)/8;
       pSortIdx = findSortingIndex(pParse, pTab, iCur, 
                                   *ppOrderBy, pIdx, nEqCol, &bRev);
     }
     if( pSortIdx && (pIdx==0 || pIdx==pSortIdx) ){
       if( pIdx==0 ){
         pLevel0->pIdx = pSortIdx;
         pLevel0->iCur = pParse->nTab++;
       }
       pLevel0->bRev = bRev;
       *ppOrderBy = 0;
     }
  }

  /* Open all tables in the pTabList and all indices used by those tables.
  */
  sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
................................................................................
      cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
      sqlite3VdbeAddOp(v, OP_MustBeInt, 1, brk);
      haveKey = 0;
      sqlite3VdbeAddOp(v, OP_NotExists, iCur, brk);
      pLevel->op = OP_Noop;
    }else if( pIdx!=0 && pLevel->score>0 && pLevel->score%4==0 ){
      /* Case 2:  There is an index and all terms of the WHERE clause that
      **          refer to the index using the "==" or "IN" operators.
      */
      int start;
      int nColumn = (pLevel->score+4)/8;
      brk = pLevel->brk = sqlite3VdbeMakeLabel(v);

      /* For each column of the index, find the term of the WHERE clause that
      ** constraints that column.  If the WHERE clause term is X=expr, then
................................................................................
      pLevel->p1 = pLevel->iCur;
      pLevel->p2 = start;
    }else if( i<ARRAYSIZE(iDirectLt) && (iDirectLt[i]>=0 || iDirectGt[i]>=0) ){
      /* Case 3:  We have an inequality comparison against the ROWID field.
      */
      int testOp = OP_Noop;
      int start;
      int bRev = pLevel->bRev;

      brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
      cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
      if( bRev ){
        int t = iDirectGt[i];
        iDirectGt[i] = iDirectLt[i];
        iDirectLt[i] = t;
      }
      if( iDirectGt[i]>=0 ){
        Expr *pX;
        k = iDirectGt[i];
        assert( k<nExpr );
        pTerm = &aExpr[k];
        pX = pTerm->p;
        assert( pX!=0 );
        assert( pTerm->idxLeft==iCur );
        sqlite3ExprCode(pParse, pX->pRight);
        sqlite3VdbeAddOp(v, OP_ForceInt, pX->op==TK_LT || pX->op==TK_GT, brk);
        sqlite3VdbeAddOp(v, bRev ? OP_MoveLt : OP_MoveGe, iCur, brk);
        disableTerm(pLevel, &pTerm->p);
      }else{
        sqlite3VdbeAddOp(v, bRev ? OP_Last : OP_Rewind, iCur, brk);
      }
      if( iDirectLt[i]>=0 ){
        Expr *pX;
        k = iDirectLt[i];
        assert( k<nExpr );
        pTerm = &aExpr[k];
        pX = pTerm->p;
        assert( pX!=0 );
        assert( pTerm->idxLeft==iCur );
        sqlite3ExprCode(pParse, pX->pRight);
        pLevel->iMem = pParse->nMem++;
        sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
        if( pX->op==TK_LT || pX->op==TK_GT ){
          testOp = bRev ? OP_Le : OP_Ge;
        }else{
          testOp = bRev ? OP_Lt : OP_Gt;
        }
        disableTerm(pLevel, &pTerm->p);
      }
      start = sqlite3VdbeCurrentAddr(v);
      pLevel->op = bRev ? OP_Prev : OP_Next;
      pLevel->p1 = iCur;
      pLevel->p2 = start;
      if( testOp!=OP_Noop ){
        sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
        sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
        sqlite3VdbeAddOp(v, testOp, 0, brk);
      }
      haveKey = 0;
    }else if( pIdx==0 ){
      /* Case 4:  There is no usable index.  We must do a complete
      **          scan of the entire database table.
      */
      int start;
      int opRewind;

      brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
      cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
      if( pLevel->bRev ){
        opRewind = OP_Last;
        pLevel->op = OP_Prev;
      }else{
        opRewind = OP_Rewind;
        pLevel->op = OP_Next;
      }
      sqlite3VdbeAddOp(v, opRewind, iCur, brk);
      start = sqlite3VdbeCurrentAddr(v);

      pLevel->p1 = iCur;
      pLevel->p2 = start;
      haveKey = 0;
    }else{
      /* Case 5: The WHERE clause term that refers to the right-most
      **         column of the index is an inequality.  For example, if
      **         the index is on (x,y,z) and the WHERE clause is of the

Changes to test/alter.test.


1
2
3
4
5




6
7
8
9
10
11
12
13
14
15
16
17
18

#
# The author or author's hereby grant to the public domain a non-exclusive,
# fully paid-up, perpetual, license in the software and all related
# intellectual property to make, have made, use, have used, reproduce,
# prepare derivative works, distribute, perform and display the work.  




#
#*************************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the ALTER TABLE statement.
#
# $Id: alter.test,v 1.7 2004/11/22 13:35:42 danielk1977 Exp $
#

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

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
>

<
|
|
<
>
>
>
>





|







1
2

3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2004 November 10
#

# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:

#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the ALTER TABLE statement.
#
# $Id: alter.test,v 1.8 2004/11/22 19:12:21 drh Exp $
#

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

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {

Changes to test/collate4.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
665
666
667
668
669
670
671

672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is page cache subsystem.
#
# $Id: collate4.test,v 1.4 2004/11/03 16:27:02 drh Exp $

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

db collate TEXT text_collate
proc text_collate {a b} {
  return [string compare $a $b]
................................................................................
#
# These tests - collate4.6.* - ensure that implict INTEGER PRIMARY KEY 
# indices do not confuse collation sequences. 
#
# These indices are never used for sorting in SQLite. And you can't
# create another index on an INTEGER PRIMARY KEY column, so we don't have 
# to test that.

#
do_test collate4-6.0 {
  execsql {
    CREATE TABLE collate4t1(a INTEGER PRIMARY KEY);
    INSERT INTO collate4t1 VALUES(101);
    INSERT INTO collate4t1 VALUES(10);
    INSERT INTO collate4t1 VALUES(15);
  }
} {}
do_test collate4-6.1 {
  cksort {
    SELECT * FROM collate4t1 ORDER BY 1;
  }
} {10 15 101 sort}
do_test collate4-6.2 {
  cksort {
    SELECT * FROM collate4t1 ORDER BY oid;
  }
} {10 15 101 sort}
do_test collate4-6.3 {
  cksort {
    SELECT * FROM collate4t1 ORDER BY oid||'' COLLATE TEXT;
  }
} {10 101 15 sort}

finish_test







|







 







>













|




|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is page cache subsystem.
#
# $Id: collate4.test,v 1.5 2004/11/22 19:12:21 drh Exp $

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

db collate TEXT text_collate
proc text_collate {a b} {
  return [string compare $a $b]
................................................................................
#
# These tests - collate4.6.* - ensure that implict INTEGER PRIMARY KEY 
# indices do not confuse collation sequences. 
#
# These indices are never used for sorting in SQLite. And you can't
# create another index on an INTEGER PRIMARY KEY column, so we don't have 
# to test that.
# (Revised 2004-Nov-22):  The ROWID can be used for sorting now.
#
do_test collate4-6.0 {
  execsql {
    CREATE TABLE collate4t1(a INTEGER PRIMARY KEY);
    INSERT INTO collate4t1 VALUES(101);
    INSERT INTO collate4t1 VALUES(10);
    INSERT INTO collate4t1 VALUES(15);
  }
} {}
do_test collate4-6.1 {
  cksort {
    SELECT * FROM collate4t1 ORDER BY 1;
  }
} {10 15 101 nosort}
do_test collate4-6.2 {
  cksort {
    SELECT * FROM collate4t1 ORDER BY oid;
  }
} {10 15 101 nosort}
do_test collate4-6.3 {
  cksort {
    SELECT * FROM collate4t1 ORDER BY oid||'' COLLATE TEXT;
  }
} {10 101 15 sort}

finish_test

Added test/cursor.test.

















































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
32
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# 2004 November 22
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is DECLARE...CURSOR functionality
#
# $Id: cursor.test,v 1.1 2004/11/22 19:12:21 drh Exp $
#

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

# If SQLITE_OMIT_CURSOR is defined, omit this file.
ifcapable {!cursor} {
  finish_test
  return
}

########
# Test the logic that creates and destroys cursors
########
do_test cursor-1.1 {
  execsql {
    CREATE TABLE t1(a,b,c);
    CREATE INDEX t1i1 ON t1(a);
    CREATE INDEX t1i2 ON t1(b,c);
  }
  execsql {
    DECLARE c1 CURSOR FOR SELECT c FROM t1 ORDER BY a;
  }
} {}
ifcapable schema_pragmas {
  do_test cursor-1.2 {
    execsql {PRAGMA cursor_list}
  } {0 c1}
}
do_test cursor-1.3 {
  execsql {
    DECLARE c2 CURSOR FOR SELECT a FROM t1 ORDER BY b, c;
  }
} {}
ifcapable schema_pragmas {
  do_test cursor-1.4 {
    execsql {PRAGMA cursor_list}
  } {0 c1 1 c2}
}
do_test cursor-1.5 {
  catchsql {
    CLOSE c3;
  }
} {1 {no such cursor: c3}}
ifcapable schema_pragmas {
  do_test cursor-1.6 {
    execsql {PRAGMA cursor_list}
  } {0 c1 1 c2}
}
do_test cursor-1.7 {
  catchsql {
    CLOSE c1;
  }
} {0 {}}
ifcapable schema_pragmas {
  do_test cursor-1.8 {
    execsql {PRAGMA cursor_list}
  } {1 c2}
}
do_test cursor-1.9 {
  catchsql {
    CLOSE c1;
  }
} {1 {no such cursor: c1}}
ifcapable schema_pragmas {
  do_test cursor-1.10 {
    execsql {PRAGMA cursor_list}
  } {1 c2}
}
do_test cursor-1.11 {
  catchsql {
    DECLARE c2 CURSOR FOR SELECT * FROM t1;
  }
} {1 {another cursor named c2 already exists}}
do_test cursor-1.12 {
  catchsql {
    DECLARE c3 CURSOR FOR SELECT * FROM t1;
  }
} {0 {}}
ifcapable schema_pragmas {
  do_test cursor-1.13 {
    execsql {PRAGMA cursor_list}
  } {0 c3 1 c2}
}
do_test cursor-1.14 {
  execsql {
    CLOSE c2;
    CLOSE c3;
  }
} {}
ifcapable schema_pragmas {
  do_test cursor-1.15 {
    execsql {PRAGMA cursor_list}
  } {}
}

set all {}
for {set i 1} {$i<=50} {incr i} {
  lappend all [expr {$i-1}] x$i
  do_test cursor-2.1.$i.1 {
    execsql "DECLARE x$i CURSOR FOR SELECT * FROM t1"
  } {}
  ifcapable schema_pragmas {
    do_test cursor-2.1.$i.2 {
      execsql {PRAGMA cursor_list}
    } $all
  }
}
for {set i 1} {$i<=50} {incr i} {
  set all [lrange $all 2 end]
  do_test cursor-2.2.$i.1 {
    execsql "CLOSE x$i"
  } {}
  ifcapable schema_pragmas {
    do_test cursor-2.2.$i.2 {
      execsql {PRAGMA cursor_list}
    } $all
  }
}  


finish_test

Changes to test/where.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
504
505
506
507
508
509
510









































511
512
513
514
515
516
517
...
657
658
659
660
661
662
663

























664
665
666
667
668
669
670
#    May you find forgiveness for yourself and forgive others.
#    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 use of indices in WHERE clases.
#
# $Id: where.test,v 1.23 2004/11/03 16:27:02 drh Exp $

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

# Build some test data
#
do_test where-1.0 {
................................................................................
  }
} {1 0 2 1 3 1 sort}
do_test where-6.19 {
  cksort {
    SELECT y FROM t1 ORDER BY w LIMIT 3;
  }
} {4 9 16 nosort}










































# Tests for reverse-order sorting.
#
do_test where-7.1 {
  cksort {
    SELECT w FROM t1 WHERE x=3 ORDER BY y;
  }
................................................................................
  }
} {nosort}
do_test where-7.30 {
  cksort {
    SELECT w FROM t1 WHERE x=6 AND y>=10201 ORDER BY y DESC;
  }
} {100 nosort}


























do_test where-8.1 {
  execsql {
    CREATE TABLE t4 AS SELECT * FROM t1;
    CREATE INDEX i4xy ON t4(x,y);
  }
  cksort {







|







 







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







 







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







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
...
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
#    May you find forgiveness for yourself and forgive others.
#    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 use of indices in WHERE clases.
#
# $Id: where.test,v 1.24 2004/11/22 19:12:21 drh Exp $

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

# Build some test data
#
do_test where-1.0 {
................................................................................
  }
} {1 0 2 1 3 1 sort}
do_test where-6.19 {
  cksort {
    SELECT y FROM t1 ORDER BY w LIMIT 3;
  }
} {4 9 16 nosort}
do_test where-6.20 {
  cksort {
    SELECT y FROM t1 ORDER BY rowid LIMIT 3;
  }
} {4 9 16 nosort}
do_test where-6.21 {
  cksort {
    SELECT y FROM t1 ORDER BY rowid, y LIMIT 3;
  }
} {4 9 16 nosort}
do_test where-6.22 {
  cksort {
    SELECT y FROM t1 ORDER BY rowid, y DESC LIMIT 3;
  }
} {4 9 16 nosort}
do_test where-6.23 {
  cksort {
    SELECT y FROM t1 WHERE y>4 ORDER BY rowid, w, x LIMIT 3;
  }
} {9 16 25 nosort}
do_test where-6.24 {
  cksort {
    SELECT y FROM t1 WHERE y>=9 ORDER BY rowid, x DESC, w LIMIT 3;
  }
} {9 16 25 nosort}
do_test where-6.25 {
  cksort {
    SELECT y FROM t1 WHERE y>4 AND y<25 ORDER BY rowid;
  }
} {9 16 nosort}
do_test where-6.26 {
  cksort {
    SELECT y FROM t1 WHERE y>=4 AND y<=25 ORDER BY oid;
  }
} {4 9 16 25 nosort}
do_test where-6.27 {
  cksort {
    SELECT y FROM t1 WHERE y<=25 ORDER BY _rowid_, w+y;
  }
} {4 9 16 25 nosort}


# Tests for reverse-order sorting.
#
do_test where-7.1 {
  cksort {
    SELECT w FROM t1 WHERE x=3 ORDER BY y;
  }
................................................................................
  }
} {nosort}
do_test where-7.30 {
  cksort {
    SELECT w FROM t1 WHERE x=6 AND y>=10201 ORDER BY y DESC;
  }
} {100 nosort}
do_test where-7.31 {
  cksort {
    SELECT y FROM t1 ORDER BY rowid DESC LIMIT 3
  }
} {10201 10000 9801 nosort}
do_test where-7.32 {
  cksort {
    SELECT y FROM t1 WHERE y<25 ORDER BY rowid DESC, x
  }
} {16 9 4 nosort}
do_test where-7.33 {
  cksort {
    SELECT y FROM t1 WHERE y<=25 ORDER BY rowid DESC, x
  }
} {25 16 9 4 nosort}
do_test where-7.34 {
  cksort {
    SELECT y FROM t1 WHERE y<25 AND y>4 ORDER BY rowid DESC, y DESC
  }
} {16 9 nosort}
do_test where-7.35 {
  cksort {
    SELECT y FROM t1 WHERE y<25 AND y>=4 ORDER BY rowid DESC
  }
} {16 9 4 nosort}

do_test where-8.1 {
  execsql {
    CREATE TABLE t4 AS SELECT * FROM t1;
    CREATE INDEX i4xy ON t4(x,y);
  }
  cksort {

Changes to tool/mkkeywordhash.c.

50
51
52
53
54
55
56





57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

100
101
102
103
104
105
106
...
108
109
110
111
112
113
114

115
116
117
118
119
120


121
122
123
124

125
126
127
128
129
130
131
...
134
135
136
137
138
139
140


141
142
143
144
145
146
147
...
160
161
162
163
164
165
166

167
168
169
170
171
172
173
174
175
176

177
178
179
180

181
182
183
184
185
186
187
#else
#  define COMPOUND   16
#endif
#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
#  define CONFLICT   0
#else
#  define CONFLICT   32





#endif
#ifdef SQLITE_OMIT_EXPLAIN
#  define EXPLAIN    0
#else
#  define EXPLAIN    64
#endif
#ifdef SQLITE_OMIT_FOREIGN_KEY
#  define FKEY       0
#else
#  define FKEY       128
#endif
#ifdef SQLITE_OMIT_PRAGMA
#  define PRAGMA     0
#else
#  define PRAGMA     256
#endif
#ifdef SQLITE_OMIT_REINDEX
#  define REINDEX    0
#else
#  define REINDEX    512
#endif
#ifdef SQLITE_OMIT_TRIGGER
#  define TRIGGER    0
#else
#  define TRIGGER    1024
#endif
#ifdef SQLITE_OMIT_VACUUM
#  define VACUUM     0
#else
#  define VACUUM     2048
#endif
#ifdef SQLITE_OMIT_VIEW
#  define VIEW       0
#else
#  define VIEW       4096
#endif


/*
** These are the keywords
*/
static Keyword aKeywordTable[] = {
  { "ABORT",            "TK_ABORT",        CONFLICT|TRIGGER       },

  { "AFTER",            "TK_AFTER",        TRIGGER                },
  { "ALL",              "TK_ALL",          ALWAYS                 },
  { "ALTER",            "TK_ALTER",        ALTER                  },
  { "AND",              "TK_AND",          ALWAYS                 },
  { "AS",               "TK_AS",           ALWAYS                 },
  { "ASC",              "TK_ASC",          ALWAYS                 },
  { "ATTACH",           "TK_ATTACH",       ATTACH                 },
................................................................................
  { "BEFORE",           "TK_BEFORE",       TRIGGER                },
  { "BEGIN",            "TK_BEGIN",        ALWAYS                 },
  { "BETWEEN",          "TK_BETWEEN",      ALWAYS                 },
  { "BY",               "TK_BY",           ALWAYS                 },
  { "CASCADE",          "TK_CASCADE",      FKEY                   },
  { "CASE",             "TK_CASE",         ALWAYS                 },
  { "CHECK",            "TK_CHECK",        ALWAYS                 },

  { "COLLATE",          "TK_COLLATE",      ALWAYS                 },
  { "COMMIT",           "TK_COMMIT",       ALWAYS                 },
  { "CONFLICT",         "TK_CONFLICT",     CONFLICT               },
  { "CONSTRAINT",       "TK_CONSTRAINT",   ALWAYS                 },
  { "CREATE",           "TK_CREATE",       ALWAYS                 },
  { "CROSS",            "TK_JOIN_KW",      ALWAYS                 },


  { "CURRENT_DATE",     "TK_CDATE",        ALWAYS                 },
  { "CURRENT_TIME",     "TK_CTIME",        ALWAYS                 },
  { "CURRENT_TIMESTAMP","TK_CTIMESTAMP",   ALWAYS                 },
  { "DATABASE",         "TK_DATABASE",     ATTACH                 },

  { "DEFAULT",          "TK_DEFAULT",      ALWAYS                 },
  { "DEFERRED",         "TK_DEFERRED",     ALWAYS                 },
  { "DEFERRABLE",       "TK_DEFERRABLE",   FKEY                   },
  { "DELETE",           "TK_DELETE",       ALWAYS                 },
  { "DESC",             "TK_DESC",         ALWAYS                 },
  { "DETACH",           "TK_DETACH",       ATTACH                 },
  { "DISTINCT",         "TK_DISTINCT",     ALWAYS                 },
................................................................................
  { "EACH",             "TK_EACH",         TRIGGER                },
  { "ELSE",             "TK_ELSE",         ALWAYS                 },
  { "ESCAPE",           "TK_ESCAPE",       ALWAYS                 },
  { "EXCEPT",           "TK_EXCEPT",       COMPOUND               },
  { "EXCLUSIVE",        "TK_EXCLUSIVE",    ALWAYS                 },
  { "EXPLAIN",          "TK_EXPLAIN",      EXPLAIN                },
  { "FAIL",             "TK_FAIL",         CONFLICT|TRIGGER       },


  { "FOR",              "TK_FOR",          TRIGGER                },
  { "FOREIGN",          "TK_FOREIGN",      FKEY                   },
  { "FROM",             "TK_FROM",         ALWAYS                 },
  { "FULL",             "TK_JOIN_KW",      ALWAYS                 },
  { "GLOB",             "TK_GLOB",         ALWAYS                 },
  { "GROUP",            "TK_GROUP",        ALWAYS                 },
  { "HAVING",           "TK_HAVING",       ALWAYS                 },
................................................................................
  { "JOIN",             "TK_JOIN",         ALWAYS                 },
  { "KEY",              "TK_KEY",          ALWAYS                 },
  { "LEFT",             "TK_JOIN_KW",      ALWAYS                 },
  { "LIKE",             "TK_LIKE",         ALWAYS                 },
  { "LIMIT",            "TK_LIMIT",        ALWAYS                 },
  { "MATCH",            "TK_MATCH",        ALWAYS                 },
  { "NATURAL",          "TK_JOIN_KW",      ALWAYS                 },

  { "NOT",              "TK_NOT",          ALWAYS                 },
  { "NOTNULL",          "TK_NOTNULL",      ALWAYS                 },
  { "NULL",             "TK_NULL",         ALWAYS                 },
  { "OF",               "TK_OF",           ALWAYS                 },
  { "OFFSET",           "TK_OFFSET",       ALWAYS                 },
  { "ON",               "TK_ON",           ALWAYS                 },
  { "OR",               "TK_OR",           ALWAYS                 },
  { "ORDER",            "TK_ORDER",        ALWAYS                 },
  { "OUTER",            "TK_JOIN_KW",      ALWAYS                 },
  { "PRAGMA",           "TK_PRAGMA",       PRAGMA                 },

  { "PRIMARY",          "TK_PRIMARY",      ALWAYS                 },
  { "RAISE",            "TK_RAISE",        TRIGGER                },
  { "REFERENCES",       "TK_REFERENCES",   FKEY                   },
  { "REINDEX",          "TK_REINDEX",      REINDEX                },

  { "RENAME",           "TK_RENAME",       ALTER                  },
  { "REPLACE",          "TK_REPLACE",      CONFLICT               },
  { "RESTRICT",         "TK_RESTRICT",     FKEY                   },
  { "RIGHT",            "TK_JOIN_KW",      ALWAYS                 },
  { "ROLLBACK",         "TK_ROLLBACK",     ALWAYS                 },
  { "ROW",              "TK_ROW",          TRIGGER                },
  { "SELECT",           "TK_SELECT",       ALWAYS                 },







>
>
>
>
>




|




|




|




|




|




|




|








>







 







>






>
>




>







 







>
>







 







>










>




>







50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
...
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#else
#  define COMPOUND   16
#endif
#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
#  define CONFLICT   0
#else
#  define CONFLICT   32
#endif
#ifdef SQLITE_OMIT_CURSOR
#  define CURSOR     0
#else
#  define CURSOR     64
#endif
#ifdef SQLITE_OMIT_EXPLAIN
#  define EXPLAIN    0
#else
#  define EXPLAIN    128
#endif
#ifdef SQLITE_OMIT_FOREIGN_KEY
#  define FKEY       0
#else
#  define FKEY       256
#endif
#ifdef SQLITE_OMIT_PRAGMA
#  define PRAGMA     0
#else
#  define PRAGMA     512
#endif
#ifdef SQLITE_OMIT_REINDEX
#  define REINDEX    0
#else
#  define REINDEX    1024
#endif
#ifdef SQLITE_OMIT_TRIGGER
#  define TRIGGER    0
#else
#  define TRIGGER    2048
#endif
#ifdef SQLITE_OMIT_VACUUM
#  define VACUUM     0
#else
#  define VACUUM     4096
#endif
#ifdef SQLITE_OMIT_VIEW
#  define VIEW       0
#else
#  define VIEW       8192
#endif


/*
** These are the keywords
*/
static Keyword aKeywordTable[] = {
  { "ABORT",            "TK_ABORT",        CONFLICT|TRIGGER       },
  { "ABSOLUTE",         "TK_ABSOLUTE",     CURSOR                 },
  { "AFTER",            "TK_AFTER",        TRIGGER                },
  { "ALL",              "TK_ALL",          ALWAYS                 },
  { "ALTER",            "TK_ALTER",        ALTER                  },
  { "AND",              "TK_AND",          ALWAYS                 },
  { "AS",               "TK_AS",           ALWAYS                 },
  { "ASC",              "TK_ASC",          ALWAYS                 },
  { "ATTACH",           "TK_ATTACH",       ATTACH                 },
................................................................................
  { "BEFORE",           "TK_BEFORE",       TRIGGER                },
  { "BEGIN",            "TK_BEGIN",        ALWAYS                 },
  { "BETWEEN",          "TK_BETWEEN",      ALWAYS                 },
  { "BY",               "TK_BY",           ALWAYS                 },
  { "CASCADE",          "TK_CASCADE",      FKEY                   },
  { "CASE",             "TK_CASE",         ALWAYS                 },
  { "CHECK",            "TK_CHECK",        ALWAYS                 },
  { "CLOSE",            "TK_CLOSE",        CURSOR                 },
  { "COLLATE",          "TK_COLLATE",      ALWAYS                 },
  { "COMMIT",           "TK_COMMIT",       ALWAYS                 },
  { "CONFLICT",         "TK_CONFLICT",     CONFLICT               },
  { "CONSTRAINT",       "TK_CONSTRAINT",   ALWAYS                 },
  { "CREATE",           "TK_CREATE",       ALWAYS                 },
  { "CROSS",            "TK_JOIN_KW",      ALWAYS                 },
  { "CURSOR",           "TK_CURSOR",       CURSOR                 },
  { "CURRENT",          "TK_CURRENT",      CURSOR                 },
  { "CURRENT_DATE",     "TK_CDATE",        ALWAYS                 },
  { "CURRENT_TIME",     "TK_CTIME",        ALWAYS                 },
  { "CURRENT_TIMESTAMP","TK_CTIMESTAMP",   ALWAYS                 },
  { "DATABASE",         "TK_DATABASE",     ATTACH                 },
  { "DECLARE",          "TK_DECLARE",      CURSOR                 },
  { "DEFAULT",          "TK_DEFAULT",      ALWAYS                 },
  { "DEFERRED",         "TK_DEFERRED",     ALWAYS                 },
  { "DEFERRABLE",       "TK_DEFERRABLE",   FKEY                   },
  { "DELETE",           "TK_DELETE",       ALWAYS                 },
  { "DESC",             "TK_DESC",         ALWAYS                 },
  { "DETACH",           "TK_DETACH",       ATTACH                 },
  { "DISTINCT",         "TK_DISTINCT",     ALWAYS                 },
................................................................................
  { "EACH",             "TK_EACH",         TRIGGER                },
  { "ELSE",             "TK_ELSE",         ALWAYS                 },
  { "ESCAPE",           "TK_ESCAPE",       ALWAYS                 },
  { "EXCEPT",           "TK_EXCEPT",       COMPOUND               },
  { "EXCLUSIVE",        "TK_EXCLUSIVE",    ALWAYS                 },
  { "EXPLAIN",          "TK_EXPLAIN",      EXPLAIN                },
  { "FAIL",             "TK_FAIL",         CONFLICT|TRIGGER       },
  { "FETCH",            "TK_FETCH",        CURSOR                 },
  { "FIRST",            "TK_FIRST",        CURSOR                 },
  { "FOR",              "TK_FOR",          TRIGGER                },
  { "FOREIGN",          "TK_FOREIGN",      FKEY                   },
  { "FROM",             "TK_FROM",         ALWAYS                 },
  { "FULL",             "TK_JOIN_KW",      ALWAYS                 },
  { "GLOB",             "TK_GLOB",         ALWAYS                 },
  { "GROUP",            "TK_GROUP",        ALWAYS                 },
  { "HAVING",           "TK_HAVING",       ALWAYS                 },
................................................................................
  { "JOIN",             "TK_JOIN",         ALWAYS                 },
  { "KEY",              "TK_KEY",          ALWAYS                 },
  { "LEFT",             "TK_JOIN_KW",      ALWAYS                 },
  { "LIKE",             "TK_LIKE",         ALWAYS                 },
  { "LIMIT",            "TK_LIMIT",        ALWAYS                 },
  { "MATCH",            "TK_MATCH",        ALWAYS                 },
  { "NATURAL",          "TK_JOIN_KW",      ALWAYS                 },
  { "NEXT",             "TK_NEXT",         CURSOR                 },
  { "NOT",              "TK_NOT",          ALWAYS                 },
  { "NOTNULL",          "TK_NOTNULL",      ALWAYS                 },
  { "NULL",             "TK_NULL",         ALWAYS                 },
  { "OF",               "TK_OF",           ALWAYS                 },
  { "OFFSET",           "TK_OFFSET",       ALWAYS                 },
  { "ON",               "TK_ON",           ALWAYS                 },
  { "OR",               "TK_OR",           ALWAYS                 },
  { "ORDER",            "TK_ORDER",        ALWAYS                 },
  { "OUTER",            "TK_JOIN_KW",      ALWAYS                 },
  { "PRAGMA",           "TK_PRAGMA",       PRAGMA                 },
  { "PRIOR",            "TK_PRIOR",        CURSOR                 },
  { "PRIMARY",          "TK_PRIMARY",      ALWAYS                 },
  { "RAISE",            "TK_RAISE",        TRIGGER                },
  { "REFERENCES",       "TK_REFERENCES",   FKEY                   },
  { "REINDEX",          "TK_REINDEX",      REINDEX                },
  { "RELATIVE",         "TK_RELATIVE",     CURSOR                 },
  { "RENAME",           "TK_RENAME",       ALTER                  },
  { "REPLACE",          "TK_REPLACE",      CONFLICT               },
  { "RESTRICT",         "TK_RESTRICT",     FKEY                   },
  { "RIGHT",            "TK_JOIN_KW",      ALWAYS                 },
  { "ROLLBACK",         "TK_ROLLBACK",     ALWAYS                 },
  { "ROW",              "TK_ROW",          TRIGGER                },
  { "SELECT",           "TK_SELECT",       ALWAYS                 },