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 |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
fc8c1393c86017a816beb52725b68af3 |
User & Date: | drh 2004-11-22 19:12:20.000 |
Context
2004-11-23
| ||
01:47 | More work on the implementation of cursors, but they are still not functioning. (CVS 2142) (check-in: 8b61d1ae1c 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: fc8c1393c8 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: 3d2536c479 user: drh tags: trunk) | |
Changes
Changes to main.mk.
︙ | ︙ | |||
50 51 52 53 54 55 56 | # This is how we compile # TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src # Object files for the SQLite library. # | | > | 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 | # 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 # All of the source code files. # 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 \ |
︙ | ︙ | |||
221 222 223 224 225 226 227 228 229 230 231 232 233 234 | 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 | > > > | 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 | 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 | ** 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. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** 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. ** |
︙ | ︙ | |||
499 500 501 502 503 504 505 | 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; | < > | 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 | 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 | ** ************************************************************************* ** 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. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** 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 |
︙ | ︙ | |||
495 496 497 498 499 500 501 502 503 504 505 506 507 508 | 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; } /* | > > > > > > > | 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 | 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 | ** ************************************************************************* ** 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. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** 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 ){ |
︙ | ︙ | |||
594 595 596 597 598 599 600 601 602 603 604 605 606 607 | 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). { | > > > | 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 | 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). { |
︙ | ︙ | |||
951 952 953 954 955 956 957 | //////////////////////// ALTER TABLE table ... //////////////////////////////// %ifndef SQLITE_OMIT_ALTERTABLE cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). { sqlite3AlterRenameTable(pParse,X,&Z); } %endif | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | //////////////////////// 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2003 April 6 ** ** 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 PRAGMA command. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2003 April 6 ** ** 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 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 |
︙ | ︙ | |||
474 475 476 477 478 479 480 481 482 483 484 485 486 487 | 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; | > > > > > > > > > > > > > > > > > > | 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 | 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 | ** 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. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** 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. |
︙ | ︙ | |||
294 295 296 297 298 299 300 | sqlite3ExprListDelete(p->pEList); sqlite3SrcListDelete(p->pSrc); sqlite3ExprDelete(p->pWhere); sqlite3ExprListDelete(p->pGroupBy); sqlite3ExprDelete(p->pHaving); sqlite3ExprListDelete(p->pOrderBy); sqlite3SelectDelete(p->pPrior); | < | 294 295 296 297 298 299 300 301 302 303 304 305 306 307 | 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){ |
︙ | ︙ | |||
2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 | 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; | > > > > > > | 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 | 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; |
︙ | ︙ | |||
2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 | } } 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 | > > > > > > > > > > > > > > > > > > > > | 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 | } } 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 |
︙ | ︙ | |||
2518 2519 2520 2521 2522 2523 2524 | openTempIndex(pParse, p, distinct, 0); }else{ distinct = -1; } /* Begin the database scan */ | > > > > > > > | | > | 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 | 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** 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. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** 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. ** ************************************************************************* ** 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 |
︙ | ︙ | |||
303 304 305 306 307 308 309 310 311 312 313 314 315 316 | 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. | > > | 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | 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. |
︙ | ︙ | |||
416 417 418 419 420 421 422 | 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 | | > > > < | | 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 | 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 |
︙ | ︙ | |||
924 925 926 927 928 929 930 931 932 933 934 | 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. ** | > > > > > > > > > > < < < < < < < < < > | 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 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 | 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 { ExprList *pEList; /* The fields of the result */ u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ u8 isDistinct; /* True if the DISTINCT keyword is present */ SrcList *pSrc; /* The FROM clause */ 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 */ |
︙ | ︙ | |||
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 | 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 { | > > > > > > | 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 | 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 { |
︙ | ︙ | |||
1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 | ** 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; | > > > > > > > > > > > > | 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 | ** 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; |
︙ | ︙ | |||
1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 | 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); | > | 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 | 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); |
︙ | ︙ | |||
1459 1460 1461 1462 1463 1464 1465 1466 | 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 | > > > > > > > | 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 | 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 | ** 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. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** 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> |
︙ | ︙ | |||
2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 | #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 | > > > > > > | 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 | #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 | ** 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. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** 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. |
︙ | ︙ | |||
244 245 246 247 248 249 250 251 252 | ** 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( | > > > > | | | | | > | > | | | 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 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 | ** 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; } p = pOrderBy->a[i].pExpr; 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); |
︙ | ︙ | |||
310 311 312 313 314 315 316 | pColl!=pIdx->keyInfo.aColl[i+nEqCol] ) break; } if( i+j>=nExpr ){ pMatch = pIdx; if( pIdx==pPreferredIdx ) break; } } | < | > | > > > > > > > > > > > > > > > > > > | | > > > | 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 | 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: |
︙ | ︙ | |||
611 612 613 614 615 616 617 618 619 620 621 622 623 624 | 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 | > > > > > > | 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 | 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 |
︙ | ︙ | |||
731 732 733 734 735 736 737 | } } /* 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 ){ | | | | | > > | > > > > > > > | < | > < | | | | | | 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 | } } /* 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 */ |
︙ | ︙ | |||
824 825 826 827 828 829 830 | 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 | | | 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 | 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 |
︙ | ︙ | |||
888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 | 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); | > > > > > > | | | | | > > > > > > > > | < | 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 | 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 | # | > | < | < > > > > | | 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 | # 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. # | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # 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] |
︙ | ︙ | |||
665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 | # # 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; } | > | | | 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 | # # 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # 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 file is testing the use of indices in WHERE clases. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2001 September 15 # # 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 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 { |
︙ | ︙ | |||
504 505 506 507 508 509 510 511 512 513 514 515 516 517 | } } {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; } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | } } {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; } |
︙ | ︙ | |||
657 658 659 660 661 662 663 664 665 666 667 668 669 670 | } } {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 { | > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | } } {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 | #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 | > > > > > | | | | | | | > > > > > > > | 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 | #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 }, { "AUTOINCREMENT", "TK_AUTOINCR", AUTOINCR }, { "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 }, { "DROP", "TK_DROP", ALWAYS }, { "END", "TK_END", 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 }, |
︙ | ︙ | |||
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 | { "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 }, | > > > | 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 | { "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 }, |
︙ | ︙ |