Index: Makefile.in ================================================================== --- Makefile.in +++ Makefile.in @@ -109,11 +109,11 @@ OPTS += -DSQLITE_OMIT_CURSOR # Cursors do not work at this time TCC += -DSQLITE_OMIT_CURSOR # Object files for the SQLite library. # -LIBOBJ = attach.lo auth.lo btree.lo build.lo cursor.lo date.lo \ +LIBOBJ = attach.lo auth.lo btree.lo build.lo date.lo \ delete.lo expr.lo func.lo hash.lo insert.lo \ main.lo opcodes.lo os_unix.lo os_win.lo \ pager.lo parse.lo pragma.lo printf.lo random.lo \ select.lo table.lo tokenize.lo trigger.lo update.lo \ util.lo vacuum.lo vdbe.lo vdbeapi.lo vdbeaux.lo vdbemem.lo \ @@ -125,11 +125,10 @@ $(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 \ @@ -286,13 +285,10 @@ $(BCC) -o temp temp.c ./temp >config.h echo >>config.h rm -f temp.c temp -cursor.lo: $(TOP)/src/cursor.c $(HDR) - $(LTCOMPILE) -c $(TOP)/src/cursor.c - date.lo: $(TOP)/src/date.c $(HDR) $(LTCOMPILE) -c $(TOP)/src/date.c delete.lo: $(TOP)/src/delete.c $(HDR) $(LTCOMPILE) -c $(TOP)/src/delete.c Index: main.mk ================================================================== --- main.mk +++ main.mk @@ -52,11 +52,11 @@ # 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 \ +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_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 \ @@ -69,11 +69,10 @@ $(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 \ @@ -222,13 +221,10 @@ $(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 Index: src/btree.c ================================================================== --- src/btree.c +++ src/btree.c @@ -7,11 +7,11 @@ ** 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. ** ************************************************************************* -** $Id: btree.c,v 1.244 2005/01/21 11:55:26 danielk1977 Exp $ +** $Id: btree.c,v 1.245 2005/02/04 04:07:17 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: @@ -1949,11 +1949,10 @@ #ifdef SQLITE_TEST /* ** Print debugging information about all cursors to standard output. */ void sqlite3BtreeCursorList(Btree *pBt){ -#ifndef SQLITE_OMIT_CURSOR BtCursor *pCur; for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ MemPage *pPage = pCur->pPage; char *zMode = pCur->wrFlag ? "rw" : "ro"; sqlite3DebugPrintf("CURSOR %p rooted at %4d(%s) currently at %d.%d%s\n", @@ -1960,11 +1959,10 @@ pCur, pCur->pgnoRoot, zMode, pPage ? pPage->pgno : 0, pCur->idx, pCur->isValid ? "" : " eof" ); } -#endif } #endif /* ** Rollback the transaction in progress. All cursors will be DELETED src/cursor.c Index: src/cursor.c ================================================================== --- src/cursor.c +++ /dev/null @@ -1,239 +0,0 @@ -/* -** 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.3 2005/01/20 02:14:31 drh Exp $ -*/ -#include "sqliteInt.h" -#ifndef SQLITE_OMIT_CURSOR -#include "vdbeInt.h" - -/* -** Delete a cursor object. -*/ -void sqlite3CursorDelete(SqlCursor *p){ - if( p ){ - int i; - sqlite3SelectDelete(p->pSelect); - for(i=0; inPtr; 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; inSqlCursor; 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; inSqlCursor; 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->idx = i; - pNew->zName = (char*)&pNew[1]; - memcpy(pNew->zName, pName->z, pName->n); - pNew->zName[pName->n] = 0; - pNew->pSelect = sqlite3SelectDup(pSelect); - pNew->nPtr = 2; - pNew->aPtr = sqliteMalloc( sizeof(Mem)*2 ); - for(i=0; i<2; i++){ - pNew->aPtr[i].flags = MEM_Null; - } - -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->idxnSqlCursor ); - assert( db->apSqlCursor[p->idx]==p ); - db->apSqlCursor[p->idx] = 0; - sqlite3CursorDelete(p); -} - -/* -** Reverse the direction the ORDER BY clause on the SELECT statement. -*/ -static void reverseSortOrder(Select *p){ - if( p->pOrderBy==0 ){ - /* If there no ORDER BY clause, add a new one that is "rowid DESC" */ - static const Token rowid = { "ROWID", 0, 5 }; - Expr *pExpr = sqlite3Expr(TK_ID, 0, 0, &rowid); - ExprList *pList = sqlite3ExprListAppend(0, pExpr, 0); - if( pList ) pList->a[0].sortOrder = SQLITE_SO_DESC; - p->pOrderBy = pList; - }else{ - int i; - ExprList *pList = p->pOrderBy; - for(i=0; inExpr; i++){ - pList->a[i].sortOrder = !pList->a[i].sortOrder; - } - } -} - -/* -** 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: { - sFetch.isBackwards = 0; - sFetch.doRewind = 1; - pCopy->nLimit = pParse->dirArg1; - pCopy->nOffset = 0; - break; - } - case TK_LAST: { - reverseSortOrder(pCopy); - sFetch.isBackwards = 1; - sFetch.doRewind = 1; - pCopy->nLimit = pParse->dirArg1; - pCopy->nOffset = 0; - break; - } - case TK_NEXT: { - sFetch.isBackwards = 0; - sFetch.doRewind = 0; - pCopy->nLimit = pParse->dirArg1; - pCopy->nOffset = 0; - break; - } - case TK_PRIOR: { - reverseSortOrder(pCopy); - sFetch.isBackwards = 1; - sFetch.doRewind = 0; - pCopy->nLimit = pParse->dirArg1; - pCopy->nOffset = 0; - break; - } - case TK_ABSOLUTE: { - sFetch.isBackwards = 0; - sFetch.doRewind = 1; - pCopy->nLimit = pParse->dirArg1; - pCopy->nOffset = pParse->dirArg2; - break; - } - default: { - assert( pParse->fetchDir==TK_RELATIVE ); - if( pParse->dirArg2>=0 ){ - /* The index parameter is positive. Move forward from the current - ** location */ - sFetch.isBackwards = 0; - sFetch.doRewind = 0; - pCopy->nLimit = pParse->dirArg1; - pCopy->nOffset = pParse->dirArg2; - }else{ - /* The index is negative. We have to code two separate SELECTs. - ** The first one seeks to the no position and the second one does - ** the query. - */ - Select *pSeek = sqlite3SelectDup(pCopy); - reverseSortOrder(pSeek); - sFetch.isBackwards = 1; - sFetch.doRewind = 0; - pSeek->nLimit = pParse->dirArg2; - pSeek->pFetch = &sFetch; - sqlite3Select(pParse, pSeek, SRT_Discard, 0, 0, 0, 0, 0); - sFetch.isBackwards = 0; - sFetch.doRewind = 0; - pCopy->nLimit = pParse->dirArg1; - pCopy->nOffset = 0; - } - break; - } - } - sqlite3Select(pParse, pCopy, SRT_Callback, 0, 0, 0, 0, 0); - -end_fetch: - sqlite3IdListDelete(pInto); -} - -#endif /* SQLITE_OMIT_CURSOR */ Index: src/expr.c ================================================================== --- src/expr.c +++ src/expr.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.190 2005/01/30 09:17:59 danielk1977 Exp $ +** $Id: expr.c,v 1.191 2005/02/04 04:07:17 danielk1977 Exp $ */ #include "sqliteInt.h" #include /* @@ -451,12 +451,12 @@ ** If cursors, triggers, views and subqueries are all omitted from ** the build, then none of the following routines, except for ** sqlite3SelectDup(), can be called. sqlite3SelectDup() is sometimes ** called with a NULL argument. */ -#if !defined(SQLITE_OMIT_CURSOR) || !defined(SQLITE_OMIT_VIEW) \ - || !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_SUBQUERY) +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \ + || !defined(SQLITE_OMIT_SUBQUERY) SrcList *sqlite3SrcListDup(SrcList *p){ SrcList *pNew; int i; int nByte; if( p==0 ) return 0; Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -12,11 +12,11 @@ ** 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.277 2005/01/31 12:42:29 danielk1977 Exp $ +** $Id: main.c,v 1.278 2005/02/04 04:07:17 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include @@ -498,17 +498,10 @@ } if( db->pErr ){ sqlite3ValueFree(db->pErr); } -#ifndef SQLITE_OMIT_CURSOR - for(j=0; jnSqlCursor; j++){ - sqlite3CursorDelete(db->apSqlCursor[j]); - } - sqliteFree(db->apSqlCursor); -#endif - db->magic = SQLITE_MAGIC_ERROR; sqliteFree(db); return SQLITE_OK; } Index: src/parse.y ================================================================== --- src/parse.y +++ src/parse.y @@ -12,11 +12,11 @@ ** 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.163 2005/01/29 08:32:45 danielk1977 Exp $ +** @(#) $Id: parse.y,v 1.164 2005/02/04 04:07:17 danielk1977 Exp $ */ %token_prefix TK_ %token_type {Token} %default_type {Token} %extra_argument {Parse *pParse} @@ -598,13 +598,10 @@ } 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);} -%ifdef SQLITE_ENABLE_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); @@ -966,34 +963,5 @@ %ifndef SQLITE_OMIT_ALTERTABLE cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). { sqlite3AlterRenameTable(pParse,X,&Z); } %endif - -////////////////////////////// CURSORS ////////////////////////////////////// -%ifdef SQLITE_ENABLE_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_ENABLE_CURSOR Index: src/pragma.c ================================================================== --- src/pragma.c +++ src/pragma.c @@ -9,11 +9,11 @@ ** 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.86 2005/01/24 10:25:59 danielk1977 Exp $ +** $Id: pragma.c,v 1.87 2005/02/04 04:07:17 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include @@ -536,28 +536,10 @@ 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; inSqlCursor; 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; Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.237 2005/01/31 12:42:29 danielk1977 Exp $ +** $Id: select.c,v 1.238 2005/02/04 04:07:17 danielk1977 Exp $ */ #include "sqliteInt.h" /* @@ -545,11 +545,11 @@ sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm); } break; } -#if !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_CURSOR) +#if !defined(SQLITE_OMIT_TRIGGER) /* Discard the results. This is used for SELECT statements inside ** the body of a TRIGGER. The purpose of such selects is to call ** user-defined functions that have side effects. We do not care ** about the actual results of the select. */ @@ -2520,16 +2520,10 @@ #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 saveAggregateInfo(pParse, &sAggInfo); @@ -2581,30 +2575,10 @@ break; default: break; } - /* 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; Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -9,23 +9,15 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.365 2005/01/31 12:56:44 danielk1977 Exp $ +** @(#) $Id: sqliteInt.h,v 1.366 2005/02/04 04:07:17 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ -/* -** Cursor support is turned off unless the SQLITE_ENABLE_CURSOR option -** is defined. -*/ -#ifndef SQLITE_ENABLE_CURSOR -# define SQLITE_OMIT_CURSOR 1 -#endif - /* ** These #defines should enable >2GB file support on Posix if the ** underlying operating system supports it. If the OS lacks ** large file support, or if the OS is windows, these should be no-ops. ** @@ -326,14 +318,12 @@ 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 NameContext NameContext; typedef struct Fetch Fetch; -typedef struct CursorSubst CursorSubst; /* ** 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 @@ -443,14 +433,10 @@ #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*); @@ -972,20 +958,10 @@ 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 */ -}; - /* ** A NameContext defines a context in which to resolve table and column ** names. The context consists of a list of tables (the pSrcList) field and ** a list of named expression (pEList). The named expression list may ** be NULL. The pSrc corresponds to the FROM clause of a SELECT or @@ -1121,15 +1097,10 @@ 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 */ -#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 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 */ @@ -1309,23 +1280,10 @@ */ 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 @@ -1576,13 +1534,6 @@ void sqlite3NestedParse(Parse*, const char*, ...); void sqlite3ExpirePreparedStatements(sqlite3*); void sqlite3CodeSubselect(Parse *, Expr *); int sqlite3SelectResolve(Parse *, Select *, NameContext *); -#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 Index: src/test1.c ================================================================== --- src/test1.c +++ src/test1.c @@ -11,11 +11,11 @@ ************************************************************************* ** 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.128 2005/01/25 04:27:55 danielk1977 Exp $ +** $Id: test1.c,v 1.129 2005/02/04 04:07:18 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include "os.h" #include @@ -2727,16 +2727,10 @@ 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 Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -41,11 +41,11 @@ ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.449 2005/01/29 08:32:45 danielk1977 Exp $ +** $Id: vdbe.c,v 1.450 2005/02/04 04:07:18 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include #include "vdbeInt.h" @@ -4475,58 +4475,10 @@ rc = sqlite3RunVacuum(&p->zErrMsg, db); if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; break; } -#ifndef SQLITE_OMIT_CURSOR -/* Opcode: CursorStore P1 P2 * -** -** The implementation of SQL cursors (not to be confused with VDBE cursors -** or B-tree cursors) stores information in the SQLite database connection -** structure (the sqlite3* pointer) that identifies the row -** in a table that an SQL cursor is pointing to. This opcode is -** used to store that information. P1 is an index of an SQL cursor. -** P2 is the index of a memory slot within that SQL cursor. This opcode -** pops the top of the stack and stores it in the SQL cursor. -*/ -case OP_CursorStore: { - SqlCursor *pCursor; - assert( pTos>=p->aStack ); - assert( pOp->p1>=0 && pOp->p1nSqlCursor ); - pCursor = db->apSqlCursor[pOp->p1]; - assert( pCursor!=0 ); - assert( pOp->p2>=0 && pOp->p2<2 ); - rc = sqlite3VdbeMemMove(&pCursor->aPtr[pOp->p1], pTos); - pTos--; - break; -} - -/* Opcode: CursorLoad P1 P2 * -** -** The implementation of SQL cursors (not to be confused with VDBE cursors -** or B-tree cursors) stores information in the SQLite database connection -** structure (the sqlite3* pointer) that effectively records the current -** location in a table that an SQL cursor is pointing to. This opcode is -** used to recover that information. P1 is an index of an SQL cursor. -** P2 is the index of a memory slot within that SQL cursor. This opcode -** pushes a new value onto the stack which is a copy of the information -** obtained from entry P2 of cursor P1. -*/ -case OP_CursorLoad: { - SqlCursor *pCursor; - int i = pOp->p1; - assert( pTos>=p->aStack ); - assert( pOp->p1>=0 && pOp->p1nSqlCursor ); - pCursor = db->apSqlCursor[pOp->p1]; - assert( pCursor!=0 ); - assert( pOp->p2>=0 && pOp->p2<2 ); - pTos++; - sqlite3VdbeMemShallowCopy(pTos, &pCursor->aPtr[i], MEM_Ephem); - break; -} -#endif /* SQLITE_OMIT_CURSOR */ - /* Opcode: Expire P1 * * ** ** Cause precompiled statements to become expired. An expired statement ** fails with an error code of SQLITE_SCHEMA if it is ever executed ** (via sqlite3_step()). Index: test/capi2.test ================================================================== --- test/capi2.test +++ test/capi2.test @@ -9,11 +9,11 @@ # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script testing the callback-free C/C++ API. # -# $Id: capi2.test,v 1.24 2005/01/20 22:48:48 drh Exp $ +# $Id: capi2.test,v 1.25 2005/02/04 04:07:18 danielk1977 Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -250,10 +250,30 @@ } {SQLITE_ERROR 0 {} {}} do_test capi2-3.19 { list [sqlite3_finalize $VM] [sqlite3_errmsg $DB] } {SQLITE_CONSTRAINT {t2.a may not be NULL}} +do_test capi2-3.20 { + execsql { + CREATE TABLE a1(message_id, name , UNIQUE(message_id, name) ); + INSERT INTO a1 VALUES(1, 1); + } +} {} +do_test capi2-3.21 { + set VM [sqlite3_prepare $DB {INSERT INTO a1 VALUES(1, 1)} -1 TAIL] + sqlite3_step $VM +} {SQLITE_ERROR} +do_test capi2-3.22 { + sqlite3_errcode $DB +} {SQLITE_ERROR} +do_test capi2-3.23 { + sqlite3_finalize $VM +} {SQLITE_CONSTRAINT} +do_test capi2-3.24 { + sqlite3_errcode $DB +} {SQLITE_CONSTRAINT} + # Two or more virtual machines exists at the same time. # do_test capi2-4.1 { set VM1 [sqlite3_prepare $DB {INSERT INTO t2 VALUES(1,2)} -1 TAIL] set TAIL Index: test/corrupt.test ================================================================== --- test/corrupt.test +++ test/corrupt.test @@ -11,11 +11,11 @@ # This file implements regression tests for SQLite library. # # This file implements tests to make sure SQLite does not crash or # segfault if it sees a corrupt database file. # -# $Id: corrupt.test,v 1.4 2005/01/20 02:17:02 danielk1977 Exp $ +# $Id: corrupt.test,v 1.5 2005/02/04 04:07:18 danielk1977 Exp $ catch {file delete -force test.db} catch {file delete -force test.db-journal} set testdir [file dirname $argv0] @@ -79,11 +79,10 @@ set fd [open test.db r+] fconfigure $fd -translation binary seek $fd $i puts -nonewline $fd $junk close $fd - sqlite3 db test.db do_test corrupt-2.$tn.1 { sqlite3 db test.db catchsql {SELECT count(*) FROM sqlite_master} set x {} } {} DELETED test/cursor.test Index: test/cursor.test ================================================================== --- test/cursor.test +++ /dev/null @@ -1,136 +0,0 @@ -# 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.2 2004/11/23 01:47:31 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 Index: tool/mkkeywordhash.c ================================================================== --- tool/mkkeywordhash.c +++ tool/mkkeywordhash.c @@ -5,17 +5,10 @@ */ #include #include #include -/* -** Cursor support is off by default. -*/ -#if !defined(SQLITE_ENABLE_CURSOR) && !defined(SQLITE_OMIT_CURSOR) -# define SQLITE_OMIT_CURSOR 1 -#endif - /* ** All the keywords of the SQL language are stored as in a hash ** table composed of instances of the following structure. */ typedef struct Keyword Keyword; @@ -60,15 +53,10 @@ #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 @@ -112,11 +100,10 @@ /* ** 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 }, @@ -128,24 +115,20 @@ { "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 }, @@ -159,13 +142,11 @@ { "EXCEPT", "TK_EXCEPT", COMPOUND }, { "EXCLUSIVE", "TK_EXCLUSIVE", ALWAYS }, { "EXISTS", "TK_EXISTS", SUBQUERY }, { "EXPLAIN", "TK_EXPLAIN", EXPLAIN }, { "FAIL", "TK_FAIL", CONFLICT|TRIGGER }, - { "FETCH", "TK_FETCH", CURSOR }, - { "FIRST", "TK_FIRST", CURSOR }, - { "FOR", "TK_FOR", TRIGGER|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 }, @@ -187,11 +168,10 @@ { "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 }, @@ -198,16 +178,14 @@ { "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 },