Index: SQLite.Interop/src/alter.c ================================================================== --- SQLite.Interop/src/alter.c +++ SQLite.Interop/src/alter.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ** -** $Id: alter.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ +** $Id: alter.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include /* Index: SQLite.Interop/src/analyze.c ================================================================== --- SQLite.Interop/src/analyze.c +++ SQLite.Interop/src/analyze.c @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code associated with the ANALYZE command. ** -** @(#) $Id: analyze.c,v 1.8 2006/01/12 20:54:07 rmsimpson Exp $ +** @(#) $Id: analyze.c,v 1.9 2006/01/16 15:51:47 rmsimpson Exp $ */ #ifndef SQLITE_OMIT_ANALYZE #include "sqliteInt.h" /* Index: SQLite.Interop/src/attach.c ================================================================== --- SQLite.Interop/src/attach.c +++ SQLite.Interop/src/attach.c @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to implement the ATTACH and DETACH commands. ** -** $Id: attach.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ +** $Id: attach.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** Resolve an expression that was part of an ATTACH or DETACH statement. This Index: SQLite.Interop/src/auth.c ================================================================== --- SQLite.Interop/src/auth.c +++ SQLite.Interop/src/auth.c @@ -12,11 +12,11 @@ ** This file contains code used to implement the sqlite3_set_authorizer() ** API. This facility is an optional feature of the library. Embedded ** systems that do not need this facility may omit it by recompiling ** the library with -DSQLITE_OMIT_AUTHORIZATION=1 ** -** $Id: auth.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ +** $Id: auth.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** All of the code in this file may be omitted by defining a single @@ -116,10 +116,15 @@ if( db->xAuth==0 ) return; if( pExpr->op==TK_AS ) return; assert( pExpr->op==TK_COLUMN ); iDb = sqlite3SchemaToIndex(pParse->db, pExpr->pSchema); + if( iDb<0 ){ + /* An attempt to read a column out of a subquery or other + ** temporary table. */ + return; + } for(iSrc=0; pTabList && iSrcnSrc; iSrc++){ if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break; } if( iSrc>=0 && pTabList && iSrcnSrc ){ pTab = pTabList->a[iSrc].pTab; @@ -140,11 +145,11 @@ assert( pTab->iPKeynCol ); zCol = pTab->aCol[pTab->iPKey].zName; }else{ zCol = "ROWID"; } - assert( iDbnDb ); + assert( iDb>=0 && iDbnDb ); zDBase = db->aDb[iDb].zName; rc = db->xAuth(db->pAuthArg, SQLITE_READ, pTab->zName, zCol, zDBase, pParse->zAuthContext); if( rc==SQLITE_IGNORE ){ pExpr->op = TK_NULL; Index: SQLite.Interop/src/btree.c ================================================================== --- SQLite.Interop/src/btree.c +++ SQLite.Interop/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.16 2006/01/12 20:54:07 rmsimpson Exp $ +** $Id: btree.c,v 1.17 2006/01/16 15:51:47 rmsimpson 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: @@ -409,11 +409,11 @@ ** ** CURSOR_REQUIRESEEK: ** The table that this cursor was opened on still exists, but has been ** modified since the cursor was last used. The cursor position is saved ** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in -** this state, restoreCursorPosition() can be called to attempt to seek +** this state, restoreOrClearCursorPosition() can be called to attempt to seek ** the cursor to the saved position. */ #define CURSOR_INVALID 0 #define CURSOR_VALID 1 #define CURSOR_REQUIRESEEK 2 @@ -499,11 +499,11 @@ ** So define the lock related functions as no-ops. */ #define queryTableLock(a,b,c) SQLITE_OK #define lockTable(a,b,c) SQLITE_OK #define unlockAllTables(a) - #define restoreCursorPosition(a,b) SQLITE_OK + #define restoreOrClearCursorPosition(a,b) SQLITE_OK #define saveAllCursors(a,b,c) SQLITE_OK #else /* @@ -572,35 +572,37 @@ /* ** Restore the cursor to the position it was in (or as close to as possible) ** when saveCursorPosition() was called. Note that this call deletes the ** saved position info stored by saveCursorPosition(), so there can be -** at most one effective restoreCursorPosition() call after each +** at most one effective restoreOrClearCursorPosition() call after each ** saveCursorPosition(). ** ** If the second argument argument - doSeek - is false, then instead of ** returning the cursor to it's saved position, any saved position is deleted ** and the cursor state set to CURSOR_INVALID. */ -static int restoreCursorPosition(BtCursor *pCur, int doSeek){ +static int restoreOrClearCursorPositionX(BtCursor *pCur, int doSeek){ int rc = SQLITE_OK; - if( pCur->eState==CURSOR_REQUIRESEEK ){ - assert( sqlite3ThreadDataReadOnly()->useSharedData ); - if( doSeek ){ - rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, &pCur->skip); - }else{ - pCur->eState = CURSOR_INVALID; - } - if( rc==SQLITE_OK ){ - sqliteFree(pCur->pKey); - pCur->pKey = 0; - assert( CURSOR_VALID==pCur->eState || CURSOR_INVALID==pCur->eState ); - } + assert( sqlite3ThreadDataReadOnly()->useSharedData ); + assert( pCur->eState==CURSOR_REQUIRESEEK ); + if( doSeek ){ + rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, &pCur->skip); + }else{ + pCur->eState = CURSOR_INVALID; + } + if( rc==SQLITE_OK ){ + sqliteFree(pCur->pKey); + pCur->pKey = 0; + assert( CURSOR_VALID==pCur->eState || CURSOR_INVALID==pCur->eState ); } return rc; } +#define restoreOrClearCursorPosition(p,x) \ + (p->eState==CURSOR_REQUIRESEEK?restoreOrClearCursorPositionX(p,x):SQLITE_OK) + /* ** Query to see if btree handle p may obtain a lock of type eLock ** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return ** SQLITE_OK if the lock may be obtained (by calling lockTable()), or ** SQLITE_LOCKED if not. @@ -1693,10 +1695,12 @@ if( pTmp->pBtree==p ){ sqlite3BtreeCloseCursor(pTmp); } } + /* Rollback any active transaction and free the handle structure */ + sqlite3BtreeRollback(p); sqliteFree(p); #ifndef SQLITE_OMIT_SHARED_CACHE /* If there are still other outstanding references to the shared-btree ** structure, return now. The remainder of this procedure cleans @@ -2707,11 +2711,10 @@ if( pCur==0 ){ rc = SQLITE_NOMEM; goto create_cursor_exception; } pCur->pgnoRoot = (Pgno)iTable; - pCur->pPage = 0; /* For exit-handler, in case getAndInitPage() fails. */ if( iTable==1 && sqlite3pager_pagecount(pBt->pPager)==0 ){ rc = SQLITE_EMPTY; goto create_cursor_exception; } rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->pPage, 0); @@ -2725,17 +2728,14 @@ */ pCur->xCompare = xCmp ? xCmp : dfltCompare; pCur->pArg = pArg; pCur->pBtree = p; pCur->wrFlag = wrFlag; - pCur->idx = 0; - memset(&pCur->info, 0, sizeof(pCur->info)); pCur->pNext = pBt->pCursor; if( pCur->pNext ){ pCur->pNext->pPrev = pCur; } - pCur->pPrev = 0; pBt->pCursor = pCur; pCur->eState = CURSOR_INVALID; *ppCur = pCur; return SQLITE_OK; @@ -2766,11 +2766,11 @@ ** Close a cursor. The read lock on the database file is released ** when the last cursor is closed. */ int sqlite3BtreeCloseCursor(BtCursor *pCur){ BtShared *pBt = pCur->pBtree->pBt; - restoreCursorPosition(pCur, 0); + restoreOrClearCursorPosition(pCur, 0); if( pCur->pPrev ){ pCur->pPrev->pNext = pCur->pNext; }else{ pBt->pCursor = pCur->pNext; } @@ -2833,11 +2833,11 @@ ** ** For a table with the INTKEY flag set, this routine returns the key ** itself, not the number of bytes in the key. */ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ - int rc = restoreCursorPosition(pCur, 1); + int rc = restoreOrClearCursorPosition(pCur, 1); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); if( pCur->eState==CURSOR_INVALID ){ *pSize = 0; }else{ @@ -2854,11 +2854,11 @@ ** Failure is not possible. If the cursor is not currently ** pointing to an entry (which can happen, for example, if ** the database is empty) then *pSize is set to 0. */ int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ - int rc = restoreCursorPosition(pCur, 1); + int rc = restoreOrClearCursorPosition(pCur, 1); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); if( pCur->eState==CURSOR_INVALID ){ /* Not pointing at a valid entry - set *pSize to 0. */ *pSize = 0; @@ -2899,12 +2899,11 @@ pBt = pCur->pBtree->pBt; pPage = pCur->pPage; pageIntegrity(pPage); assert( pCur->idx>=0 && pCur->idxnCell ); getCellInfo(pCur); - aPayload = pCur->info.pCell; - aPayload += pCur->info.nHeader; + aPayload = pCur->info.pCell + pCur->info.nHeader; if( pPage->intKey ){ nKey = 0; }else{ nKey = pCur->info.nKey; } @@ -2969,11 +2968,11 @@ ** Return SQLITE_OK on success or an error code if anything goes ** wrong. An error is returned if "offset+amt" is larger than ** the available payload. */ int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ - int rc = restoreCursorPosition(pCur, 1); + int rc = restoreOrClearCursorPosition(pCur, 1); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_VALID ); assert( pCur->pPage!=0 ); if( pCur->pPage->intKey ){ return SQLITE_CORRUPT_BKPT; @@ -2993,11 +2992,11 @@ ** Return SQLITE_OK on success or an error code if anything goes ** wrong. An error is returned if "offset+amt" is larger than ** the available payload. */ int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ - int rc = restoreCursorPosition(pCur, 1); + int rc = restoreOrClearCursorPosition(pCur, 1); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_VALID ); assert( pCur->pPage!=0 ); assert( pCur->idx>=0 && pCur->idxpPage->nCell ); rc = getPayload(pCur, offset, amt, pBuf, 1); @@ -3163,23 +3162,29 @@ /* ** Move the cursor to the root page */ static int moveToRoot(BtCursor *pCur){ MemPage *pRoot; - int rc; + int rc = SQLITE_OK; BtShared *pBt = pCur->pBtree->pBt; - if( - SQLITE_OK!=(rc = restoreCursorPosition(pCur, 0)) || - SQLITE_OK!=(rc = getAndInitPage(pBt, pCur->pgnoRoot, &pRoot, 0)) - ){ - pCur->eState = CURSOR_INVALID; - return rc; - } - releasePage(pCur->pPage); - pageIntegrity(pRoot); - pCur->pPage = pRoot; + restoreOrClearCursorPosition(pCur, 0); + assert( pCur->pPage ); + pRoot = pCur->pPage; + if( pRoot->pgno==pCur->pgnoRoot ){ + assert( pRoot->isInit ); + }else{ + if( + SQLITE_OK!=(rc = getAndInitPage(pBt, pCur->pgnoRoot, &pRoot, 0)) + ){ + pCur->eState = CURSOR_INVALID; + return rc; + } + releasePage(pCur->pPage); + pageIntegrity(pRoot); + pCur->pPage = pRoot; + } pCur->idx = 0; pCur->info.nSize = 0; if( pRoot->nCell==0 && !pRoot->leaf ){ Pgno subpage; assert( pRoot->pgno==1 ); @@ -3193,10 +3198,13 @@ } /* ** Move the cursor down to the left-most leaf entry beneath the ** entry to which it is currently pointing. +** +** The left-most leaf is the one with the smallest key - the first +** in ascending order. */ static int moveToLeftmost(BtCursor *pCur){ Pgno pgno; int rc; MemPage *pPage; @@ -3215,10 +3223,13 @@ ** Move the cursor down to the right-most leaf entry beneath the ** page to which it is currently pointing. Notice the difference ** between moveToLeftmost() and moveToRightmost(). moveToLeftmost() ** finds the left-most entry beneath the *entry* whereas moveToRightmost() ** finds the right-most entry beneath the *page*. +** +** The right-most entry is the one with the largest key - the last +** key in ascending order. */ static int moveToRightmost(BtCursor *pCur){ Pgno pgno; int rc; MemPage *pPage; @@ -3300,14 +3311,16 @@ ** *pRes>0 The cursor is left pointing at an entry that ** is larger than pKey. */ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){ int rc; + int tryRightmost; rc = moveToRoot(pCur); if( rc ) return rc; assert( pCur->pPage ); assert( pCur->pPage->isInit ); + tryRightmost = pCur->pPage->intKey; if( pCur->eState==CURSOR_INVALID ){ *pRes = -1; assert( pCur->pPage->nCell==0 ); return SQLITE_OK; } @@ -3324,31 +3337,34 @@ pageIntegrity(pPage); while( lwr<=upr ){ void *pCellKey; i64 nCellKey; pCur->idx = (lwr+upr)/2; + pCur->info.nSize = 0; if( pPage->intKey ){ - u8 *pCell = findCell(pPage, pCur->idx); - pCell += pPage->childPtrSize; + u8 *pCell; + if( tryRightmost ){ + pCur->idx = upr; + } + pCell = findCell(pPage, pCur->idx) + pPage->childPtrSize; if( pPage->hasData ){ int dummy; pCell += getVarint32(pCell, &dummy); } getVarint(pCell, &nCellKey); - pCur->info.nSize = 0; if( nCellKeynKey ){ c = +1; + tryRightmost = 0; }else{ c = 0; } }else{ int available; - parseCell(pPage, pCur->idx, &pCur->info); - nCellKey = pCur->info.nKey; pCellKey = (void *)fetchPayload(pCur, &available, 0); + nCellKey = pCur->info.nKey; if( available>=nCellKey ){ c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey); }else{ pCellKey = sqliteMallocRaw( nCellKey ); if( pCellKey==0 ) return SQLITE_NOMEM; @@ -3422,11 +3438,11 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ int rc; MemPage *pPage = pCur->pPage; #ifndef SQLITE_OMIT_SHARED_CACHE - rc = restoreCursorPosition(pCur, 1); + rc = restoreOrClearCursorPosition(pCur, 1); if( rc!=SQLITE_OK ){ return rc; } if( pCur->skip>0 ){ pCur->skip = 0; @@ -3489,11 +3505,11 @@ int rc; Pgno pgno; MemPage *pPage; #ifndef SQLITE_OMIT_SHARED_CACHE - rc = restoreCursorPosition(pCur, 1); + rc = restoreOrClearCursorPosition(pCur, 1); if( rc!=SQLITE_OK ){ return rc; } if( pCur->skip<0 ){ pCur->skip = 0; @@ -5159,12 +5175,12 @@ if( checkReadLocks(pBt, pCur->pgnoRoot, pCur) ){ return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } /* Save the positions of any other cursors open on this table */ + restoreOrClearCursorPosition(pCur, 0); if( - SQLITE_OK!=(rc = restoreCursorPosition(pCur, 0)) || SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, &loc)) ){ return rc; } @@ -5246,11 +5262,11 @@ ** CURSOR_REQUIRESEEK state) and save the positions of any other cursors ** open on the same table. Then call sqlite3pager_write() on the page ** that the entry will be deleted from. */ if( - (rc = restoreCursorPosition(pCur, 1)) || + (rc = restoreOrClearCursorPosition(pCur, 1)) || (rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || (rc = sqlite3pager_write(pPage->aData)) ){ return rc; } @@ -5728,11 +5744,11 @@ ** Return the flag byte at the beginning of the page that the cursor ** is currently pointing to. */ int sqlite3BtreeFlags(BtCursor *pCur){ /* TODO: What about CURSOR_REQUIRESEEK state? Probably need to call - ** restoreCursorPosition() here. + ** restoreOrClearCursorPosition() here. */ MemPage *pPage = pCur->pPage; return pPage ? pPage->aData[pPage->hdrOffset] : 0; } @@ -5863,11 +5879,11 @@ int sqlite3BtreeCursorInfo(BtCursor *pCur, int *aResult, int upCnt){ int cnt, idx; MemPage *pPage = pCur->pPage; BtCursor tmpCur; - int rc = restoreCursorPosition(pCur, 1); + int rc = restoreOrClearCursorPosition(pCur, 1); if( rc!=SQLITE_OK ){ return rc; } pageIntegrity(pPage); Index: SQLite.Interop/src/btree.h ================================================================== --- SQLite.Interop/src/btree.h +++ SQLite.Interop/src/btree.h @@ -11,11 +11,11 @@ ************************************************************************* ** This header file defines the interface that the sqlite B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** -** @(#) $Id: btree.h,v 1.15 2006/01/12 20:54:07 rmsimpson Exp $ +** @(#) $Id: btree.h,v 1.16 2006/01/16 15:51:47 rmsimpson Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ /* TODO: This definition is just included so other modules compile. It Index: SQLite.Interop/src/build.c ================================================================== --- SQLite.Interop/src/build.c +++ SQLite.Interop/src/build.c @@ -20,11 +20,11 @@ ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ +** $Id: build.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include /* @@ -1171,11 +1171,11 @@ if( (p = pParse->pNewTable)==0 ) return; i = p->nCol-1; if( sqlite3LocateCollSeq(pParse, zType, nType) ){ Index *pIdx; - p->aCol[i].zColl = sqlite3StrNDup(zType, nType); + p->aCol[i].zColl = sqliteStrNDup(zType, nType); /* If the column is declared as " PRIMARY KEY COLLATE ", ** then an index may have been created on this column before the ** collation type was added. Correct this if it is the case. */ @@ -1545,13 +1545,14 @@ db->nTable++; db->flags |= SQLITE_InternChanges; #ifndef SQLITE_OMIT_ALTERTABLE if( !p->pSelect ){ + const unsigned char *zName = pParse->sNameToken.z; assert( !pSelect && pCons && pEnd ); if( pCons->z==0 ) pCons = pEnd; - p->addColOffset = 13 + (pCons->z - pParse->sNameToken.z); + p->addColOffset = 13 + sqlite3utf8CharLen(zName, pCons->z - zName); } #endif } } @@ -3151,11 +3152,11 @@ return; }else if( pName2==0 || pName2->z==0 ){ assert( pName1->z ); pColl = sqlite3FindCollSeq(db, ENC(db), (char*)pName1->z, pName1->n, 0); if( pColl ){ - char *z = sqlite3StrNDup(pName1->z, pName1->n); + char *z = sqliteStrNDup(pName1->z, pName1->n); if( z ){ reindexDatabases(pParse, z); sqliteFree(z); } return; Index: SQLite.Interop/src/callback.c ================================================================== --- SQLite.Interop/src/callback.c +++ SQLite.Interop/src/callback.c @@ -11,11 +11,11 @@ ************************************************************************* ** ** This file contains functions used to access the internal hash tables ** of user defined functions and collation sequences. ** -** $Id: callback.c,v 1.10 2006/01/12 20:54:07 rmsimpson Exp $ +** $Id: callback.c,v 1.11 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" /* Index: SQLite.Interop/src/complete.c ================================================================== --- SQLite.Interop/src/complete.c +++ SQLite.Interop/src/complete.c @@ -14,11 +14,11 @@ ** This file contains C code that implements the sqlite3_complete() API. ** This code used to be part of the tokenizer.c source file. But by ** separating it out, the code will be automatically omitted from ** static links that do not use it. ** -** $Id: complete.c,v 1.8 2006/01/12 20:54:07 rmsimpson Exp $ +** $Id: complete.c,v 1.9 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #ifndef SQLITE_OMIT_COMPLETE /* Index: SQLite.Interop/src/date.c ================================================================== --- SQLite.Interop/src/date.c +++ SQLite.Interop/src/date.c @@ -14,11 +14,11 @@ ** ** There is only one exported symbol in this file - the function ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: date.c,v 1.15 2006/01/13 03:36:39 rmsimpson Exp $ +** $Id: date.c,v 1.16 2006/01/16 15:51:47 rmsimpson Exp $ ** ** NOTES: ** ** SQLite processes all times and dates as Julian Day numbers. The ** dates and times are stored as the number of days since noon @@ -103,23 +103,24 @@ nextC = va_arg(ap, int); pVal = va_arg(ap, int*); val = 0; while( N-- ){ if( !isdigit(*(u8*)zDate) ){ - return cnt; + goto end_getDigits; } val = val*10 + *zDate - '0'; zDate++; } if( valmax || (nextC!=0 && nextC!=*zDate) ){ - return cnt; + goto end_getDigits; } *pVal = val; zDate++; cnt++; }while( nextC ); va_end(ap); +end_getDigits: return cnt; } /* ** Read text from z[] and convert into a floating point number. Return Index: SQLite.Interop/src/delete.c ================================================================== --- SQLite.Interop/src/delete.c +++ SQLite.Interop/src/delete.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** -** $Id: delete.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ +** $Id: delete.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** Look up every table that is named in pSrc. If any table is not found, Index: SQLite.Interop/src/experimental.c ================================================================== --- SQLite.Interop/src/experimental.c +++ SQLite.Interop/src/experimental.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains C code routines that are not a part of the official ** SQLite API. These routines are unsupported. ** -** $Id: experimental.c,v 1.4 2006/01/12 20:54:07 rmsimpson Exp $ +** $Id: experimental.c,v 1.5 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** Set all the parameters in the compiled SQL statement to NULL. Index: SQLite.Interop/src/expr.c ================================================================== --- SQLite.Interop/src/expr.c +++ SQLite.Interop/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.21 2006/01/12 20:54:07 rmsimpson Exp $ +** $Id: expr.c,v 1.22 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include /* @@ -353,11 +353,11 @@ } if( i>=pParse->nVarExpr ){ pExpr->iTable = ++pParse->nVar; if( pParse->nVarExpr>=pParse->nVarExprAlloc-1 ){ pParse->nVarExprAlloc += pParse->nVarExprAlloc + 10; - sqlite3ReallocOrFree((void**)&pParse->apVarExpr, + sqliteReallocOrFree((void**)&pParse->apVarExpr, pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0]) ); } if( !sqlite3ThreadDataReadOnly()->mallocFailed ){ assert( pParse->apVarExpr!=0 ); pParse->apVarExpr[pParse->nVarExpr++] = pExpr; Index: SQLite.Interop/src/func.c ================================================================== --- SQLite.Interop/src/func.c +++ SQLite.Interop/src/func.c @@ -14,11 +14,11 @@ ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: func.c,v 1.16 2006/01/13 03:36:39 rmsimpson Exp $ +** $Id: func.c,v 1.17 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include /* #include */ #include Index: SQLite.Interop/src/hash.c ================================================================== --- SQLite.Interop/src/hash.c +++ SQLite.Interop/src/hash.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This is the implementation of generic hash-tables ** used in SQLite. ** -** $Id: hash.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ +** $Id: hash.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include /* Turn bulk memory into a hash table object by initializing the Index: SQLite.Interop/src/hash.h ================================================================== --- SQLite.Interop/src/hash.h +++ SQLite.Interop/src/hash.h @@ -10,11 +10,11 @@ ** ************************************************************************* ** This is the header file for the generic hash-table implemenation ** used in SQLite. ** -** $Id: hash.h,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ +** $Id: hash.h,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #ifndef _SQLITE_HASH_H_ #define _SQLITE_HASH_H_ /* Forward declarations of structures. */ Index: SQLite.Interop/src/insert.c ================================================================== --- SQLite.Interop/src/insert.c +++ SQLite.Interop/src/insert.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ +** $Id: insert.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** Set P3 of the most recently inserted opcode to a column affinity Index: SQLite.Interop/src/legacy.c ================================================================== --- SQLite.Interop/src/legacy.c +++ SQLite.Interop/src/legacy.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: legacy.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ +** $Id: legacy.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include Index: SQLite.Interop/src/main.c ================================================================== --- SQLite.Interop/src/main.c +++ SQLite.Interop/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.14 2006/01/12 20:54:07 rmsimpson Exp $ +** $Id: main.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include Index: SQLite.Interop/src/os_common.h ================================================================== --- SQLite.Interop/src/os_common.h +++ SQLite.Interop/src/os_common.h @@ -130,31 +130,62 @@ ** sqlite3GenericAllocationSize ** ** Implementation of the os level dynamic memory allocation interface in terms ** of the standard malloc(), realloc() and free() found in many operating ** systems. No rocket science here. +** +** There are two versions of these four functions here. The version +** implemented here is only used if memory-management or memory-debugging is +** enabled. This version allocates an extra 8-bytes at the beginning of each +** block and stores the size of the allocation there. +** +** If neither memory-management or debugging is enabled, the second +** set of implementations is used instead. */ +#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || defined (SQLITE_MEMDEBUG) void *sqlite3GenericMalloc(int n){ char *p = (char *)malloc(n+8); assert(n>0); assert(sizeof(int)<=8); if( p ){ *(int *)p = n; + p += 8; } - return (void *)(p + 8); + return (void *)p; } void *sqlite3GenericRealloc(void *p, int n){ char *p2 = ((char *)p - 8); assert(n>0); p2 = realloc(p2, n+8); if( p2 ){ *(int *)p2 = n; + p2 += 8; } - return (void *)((char *)p2 + 8); + return (void *)p2; } void sqlite3GenericFree(void *p){ assert(p); free((void *)((char *)p - 8)); } int sqlite3GenericAllocationSize(void *p){ return p ? *(int *)((char *)p - 8) : 0; } +#else +void *sqlite3GenericMalloc(int n){ + char *p = (char *)malloc(n); + return (void *)p; +} +void *sqlite3GenericRealloc(void *p, int n){ + assert(n>0); + p = realloc(p, n); + return p; +} +void sqlite3GenericFree(void *p){ + assert(p); + free(p); +} +#if 0 /* Never actually invoked */ +int sqlite3GenericAllocationSize(void *p){ + assert(0); +} +#endif +#endif Index: SQLite.Interop/src/os_unix.c ================================================================== --- SQLite.Interop/src/os_unix.c +++ SQLite.Interop/src/os_unix.c @@ -17,21 +17,19 @@ #if OS_UNIX /* This file is used on unix only */ /* ** 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. +** large file support, these should be no-ops. ** ** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch ** on the compiler command line. This is necessary if you are compiling ** on a recent machine (ex: RedHat 7.2) but you want your code to work ** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2 ** without this option, LFS is enable. But LFS does not exist in the kernel ** in RedHat 6.0, so the code won't work. Hence, for maximum binary ** portability you should omit LFS. -** -** Similar is true for MacOS. LFS is only supported on MacOS 9 and later. */ #ifndef SQLITE_DISABLE_LFS # define _LARGE_FILE 1 # ifndef _FILE_OFFSET_BITS # define _FILE_OFFSET_BITS 64 @@ -49,14 +47,12 @@ #include #include #include /* -** Macros used to determine whether or not to use threads. The -** SQLITE_UNIX_THREADS macro is defined if we are synchronizing for -** Posix threads and SQLITE_W32_THREADS is defined if we are -** synchronizing using Win32 threads. +** If we are to be thread-safe, include the pthreads header and define +** the SQLITE_UNIX_THREADS macro. */ #if defined(THREADSAFE) && THREADSAFE # include # define SQLITE_UNIX_THREADS 1 #endif @@ -83,11 +79,11 @@ unsigned char locktype; /* The type of lock held on this fd */ unsigned char isOpen; /* True if needs to be closed */ unsigned char fullSync; /* Use F_FULLSYNC if available */ int dirfd; /* File descriptor for the directory */ #ifdef SQLITE_UNIX_THREADS - pthread_t tid; /* The thread authorized to use this OsFile */ + pthread_t tid; /* The thread that "owns" this OsFile */ #endif }; /* ** Provide the ability to override some OS-layer functions during @@ -111,11 +107,11 @@ */ #include "os_common.h" /* ** Do not include any of the File I/O interface procedures if the -** SQLITE_OMIT_DISKIO macro is defined (indicating that there database +** SQLITE_OMIT_DISKIO macro is defined (indicating that the database ** will be in-memory only) */ #ifndef SQLITE_OMIT_DISKIO @@ -162,14 +158,22 @@ ** same thread is operating on the OsFile. Some operating systems do ** not allow locks to be overridden by other threads and that restriction ** means that sqlite3* database handles cannot be moved from one thread ** to another. This logic makes sure a user does not try to do that ** by mistake. +** +** Version 3.3.1 (2006-01-15): OsFiles can be moved from one thread to +** another as long as we are running on a system that supports threads +** overriding each others locks (which now the most common behavior) +** or if no locks are held. But the OsFile.pLock field needs to be +** recomputed because its key includes the thread-id. See the +** transferOwnership() function below for additional information */ -#if defined(SQLITE_UNIX_THREADS) && !defined(SQLITE_ALLOW_XTHREAD_CONNECTIONS) +#if defined(SQLITE_UNIX_THREADS) # define SET_THREADID(X) (X)->tid = pthread_self() -# define CHECK_THREADID(X) (!pthread_equal((X)->tid, pthread_self())) +# define CHECK_THREADID(X) (threadsOverrideEachOthersLocks==0 && \ + !pthread_equal((X)->tid, pthread_self())) #else # define SET_THREADID(X) # define CHECK_THREADID(X) 0 #endif @@ -277,12 +281,12 @@ ** An instance of the following structure serves as the key used ** to locate a particular lockInfo structure given its inode. ** ** If threads cannot override each others locks, then we set the ** lockKey.tid field to the thread ID. If threads can override -** each others locks then tid is always set to zero. tid is also -** set to zero if we compile without threading support. +** each others locks then tid is always set to zero. tid is omitted +** if we compile without threading support. */ struct lockKey { dev_t dev; /* Device number */ ino_t ino; /* Inode number */ #ifdef SQLITE_UNIX_THREADS @@ -330,12 +334,13 @@ int nPending; /* Number of pending close() operations */ int *aPending; /* Malloced space holding fd's awaiting a close() */ }; /* -** These hash table maps inodes and process IDs into lockInfo and openCnt -** structures. Access to these hash tables must be protected by a mutex. +** These hash tables map inodes and file descriptors (really, lockKey and +** openKey structures) into lockInfo and openCnt structures. Access to +** these hash tables must be protected by a mutex. */ static Hash lockHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; static Hash openHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; @@ -345,12 +350,20 @@ ** locks. ** ** 0: No. Threads cannot override each others locks. ** 1: Yes. Threads can override each others locks. ** -1: We don't know yet. +** +** This variable normally has file scope only. But during testing, we make +** it a global so that the test code can change its value in order to verify +** that the right stuff happens in either case. */ +#ifdef SQLITE_TEST +int threadsOverrideEachOthersLocks = -1; +#else static int threadsOverrideEachOthersLocks = -1; +#endif /* ** This structure holds information passed into individual test ** threads by the testThreadLockingBehavior() routine. */ @@ -365,11 +378,11 @@ ** Print out information about all locking operations. ** ** This routine is used for troubleshooting locks on multithreaded ** platforms. Enable by compiling with the -DSQLITE_LOCK_TRACE ** command-line option on the compiler. This code is normally -** turnned off. +** turned off. */ static int lockTrace(int fd, int op, struct flock *p){ char *zOpName, *zType; int s; int savedErrno; @@ -463,10 +476,11 @@ /* ** Release a lockInfo structure previously allocated by findLockInfo(). */ static void releaseLockInfo(struct lockInfo *pLock){ + assert( sqlite3OsInMutex() ); pLock->nRef--; if( pLock->nRef==0 ){ sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0); sqliteFree(pLock); } @@ -474,22 +488,23 @@ /* ** Release a openCnt structure previously allocated by findLockInfo(). */ static void releaseOpenCnt(struct openCnt *pOpen){ + assert( sqlite3OsInMutex() ); pOpen->nRef--; if( pOpen->nRef==0 ){ sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0); - sqliteFree(pOpen->aPending); + free(pOpen->aPending); sqliteFree(pOpen); } } /* ** Given a file descriptor, locate lockInfo and openCnt structures that -** describes that file descriptor. Create a new ones if necessary. The -** return values might be unset if an error occurs. +** describes that file descriptor. Create new ones if necessary. The +** return values might be uninitialized if an error occurs. ** ** Return the number of errors. */ static int findLockInfo( int fd, /* The file descriptor used in the key */ @@ -503,10 +518,11 @@ struct lockInfo *pLock; struct openCnt *pOpen; rc = fstat(fd, &statbuf); if( rc!=0 ) return 1; + assert( sqlite3OsInMutex() ); memset(&key1, 0, sizeof(key1)); key1.dev = statbuf.st_dev; key1.ino = statbuf.st_ino; #ifdef SQLITE_UNIX_THREADS if( threadsOverrideEachOthersLocks<0 ){ @@ -538,40 +554,105 @@ } }else{ pLock->nRef++; } *ppLock = pLock; - pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2)); - if( pOpen==0 ){ - struct openCnt *pOld; - pOpen = sqliteMallocRaw( sizeof(*pOpen) ); - if( pOpen==0 ){ - releaseLockInfo(pLock); - rc = 1; - goto exit_findlockinfo; - } - pOpen->key = key2; - pOpen->nRef = 1; - pOpen->nLock = 0; - pOpen->nPending = 0; - pOpen->aPending = 0; - pOld = sqlite3HashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen); - if( pOld!=0 ){ - assert( pOld==pOpen ); - sqliteFree(pOpen); - releaseLockInfo(pLock); - rc = 1; - goto exit_findlockinfo; - } - }else{ - pOpen->nRef++; - } - *ppOpen = pOpen; + if( ppOpen!=0 ){ + pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2)); + if( pOpen==0 ){ + struct openCnt *pOld; + pOpen = sqliteMallocRaw( sizeof(*pOpen) ); + if( pOpen==0 ){ + releaseLockInfo(pLock); + rc = 1; + goto exit_findlockinfo; + } + pOpen->key = key2; + pOpen->nRef = 1; + pOpen->nLock = 0; + pOpen->nPending = 0; + pOpen->aPending = 0; + pOld = sqlite3HashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen); + if( pOld!=0 ){ + assert( pOld==pOpen ); + sqliteFree(pOpen); + releaseLockInfo(pLock); + rc = 1; + goto exit_findlockinfo; + } + }else{ + pOpen->nRef++; + } + *ppOpen = pOpen; + } exit_findlockinfo: return rc; } + +#ifdef SQLITE_DEBUG +/* +** Helper function for printing out trace information from debugging +** binaries. This returns the string represetation of the supplied +** integer lock-type. +*/ +static const char *locktypeName(int locktype){ + switch( locktype ){ + case NO_LOCK: return "NONE"; + case SHARED_LOCK: return "SHARED"; + case RESERVED_LOCK: return "RESERVED"; + case PENDING_LOCK: return "PENDING"; + case EXCLUSIVE_LOCK: return "EXCLUSIVE"; + } + return "ERROR"; +} +#endif + +/* +** If we are currently in a different thread than the thread that the +** unixFile argument belongs to, then transfer ownership of the unixFile +** over to the current thread. +** +** A unixFile is only owned by a thread on systems where one thread is +** unable to override locks created by a different thread. RedHat9 is +** an example of such a system. +** +** Ownership transfer is only allowed if the unixFile is currently unlocked. +** If the unixFile is locked and an ownership is wrong, then return +** SQLITE_MISUSE. SQLITE_OK is returned if everything works. +*/ +#ifdef SQLITE_UNIX_THREADS +static int transferOwnership(unixFile *pFile){ + int rc; + pthread_t hSelf; + if( threadsOverrideEachOthersLocks ){ + /* Ownership transfers not needed on this system */ + return SQLITE_OK; + } + hSelf = pthread_self(); + if( pthread_equal(pFile->tid, hSelf) ){ + /* We are still in the same thread */ + TRACE1("No-transfer, same thread\n"); + return SQLITE_OK; + } + if( pFile->locktype!=NO_LOCK ){ + /* We cannot change ownership while we are holding a lock! */ + return SQLITE_MISUSE; + } + TRACE4("Transfer ownership of %d from %d to %d\n", pFile->h,pFile->tid,hSelf); + pFile->tid = hSelf; + releaseLockInfo(pFile->pLock); + rc = findLockInfo(pFile->h, &pFile->pLock, 0); + TRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h, + locktypeName(pFile->locktype), + locktypeName(pFile->pLock->locktype), pFile->pLock->cnt); + return rc; +} +#else + /* On single-threaded builds, ownership transfer is a no-op */ +# define transferOwnership(X) SQLITE_OK +#endif /* ** Delete the named file */ int sqlite3UnixDelete(const char *zFilename){ @@ -760,10 +841,12 @@ /* ** If the following global variable points to a string which is the ** name of a directory, then that directory will be used to store ** temporary files. +** +** See also the "PRAGMA temp_store_directory" SQL command. */ char *sqlite3_temp_directory = 0; /* ** Create a temporary file name in zBuf. zBuf must be big enough to @@ -1045,11 +1128,10 @@ static int unixCheckReservedLock(OsFile *id){ int r = 0; unixFile *pFile = (unixFile*)id; assert( pFile ); - if( CHECK_THREADID(pFile) ) return SQLITE_MISUSE; sqlite3OsEnterMutex(); /* Because pFile->pLock is shared across threads */ /* Check if a thread in this process holds such a lock */ if( pFile->pLock->locktype>SHARED_LOCK ){ r = 1; @@ -1073,28 +1155,10 @@ TRACE3("TEST WR-LOCK %d %d\n", pFile->h, r); return r; } -#ifdef SQLITE_DEBUG -/* -** Helper function for printing out trace information from debugging -** binaries. This returns the string represetation of the supplied -** integer lock-type. -*/ -static const char *locktypeName(int locktype){ - switch( locktype ){ - case NO_LOCK: return "NONE"; - case SHARED_LOCK: return "SHARED"; - case RESERVED_LOCK: return "RESERVED"; - case PENDING_LOCK: return "PENDING"; - case EXCLUSIVE_LOCK: return "EXCLUSIVE"; - } - return "ERROR"; -} -#endif - /* ** Lock the file with the lock specified by parameter locktype - one ** of the following: ** ** (1) SHARED_LOCK @@ -1164,11 +1228,10 @@ assert( pFile ); TRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h, locktypeName(locktype), locktypeName(pFile->locktype), locktypeName(pLock->locktype), pLock->cnt , getpid()); - if( CHECK_THREADID(pFile) ) return SQLITE_MISUSE; /* If there is already a lock of this type or more restrictive on the ** OsFile, do nothing. Don't use the end_lock: exit path, as ** sqlite3OsEnterMutex() hasn't been called yet. */ @@ -1185,10 +1248,19 @@ assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); /* This mutex is needed because pFile->pLock is shared across threads */ sqlite3OsEnterMutex(); + + /* Make sure the current thread owns the pFile. + */ + rc = transferOwnership(pFile); + if( rc!=SQLITE_OK ){ + sqlite3OsLeaveMutex(); + return rc; + } + pLock = pFile->pLock; /* If some thread using this PID has a lock via a different OsFile* ** handle that precludes the requested lock, return BUSY. */ if( (pFile->locktype!=pLock->locktype && @@ -1308,14 +1380,10 @@ ** Lower the locking level on file descriptor pFile to locktype. locktype ** must be either NO_LOCK or SHARED_LOCK. ** ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. -** -** It is not possible for this routine to fail if the second argument -** is NO_LOCK. If the second argument is SHARED_LOCK, this routine -** might return SQLITE_IOERR instead of SQLITE_OK. */ static int unixUnlock(OsFile *id, int locktype){ struct lockInfo *pLock; struct flock lock; int rc = SQLITE_OK; @@ -1322,15 +1390,17 @@ unixFile *pFile = (unixFile*)id; assert( pFile ); TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype, pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); - if( CHECK_THREADID(pFile) ) return SQLITE_MISUSE; assert( locktype<=SHARED_LOCK ); if( pFile->locktype<=locktype ){ return SQLITE_OK; + } + if( CHECK_THREADID(pFile) ){ + return SQLITE_MISUSE; } sqlite3OsEnterMutex(); pLock = pFile->pLock; assert( pLock->cnt!=0 ); if( pFile->locktype>SHARED_LOCK ){ @@ -1384,11 +1454,11 @@ if( pOpen->nLock==0 && pOpen->nPending>0 ){ int i; for(i=0; inPending; i++){ close(pOpen->aPending[i]); } - sqliteFree(pOpen->aPending); + free(pOpen->aPending); pOpen->nPending = 0; pOpen->aPending = 0; } } sqlite3OsLeaveMutex(); @@ -1399,12 +1469,13 @@ /* ** Close a file. */ static int unixClose(OsFile **pId){ unixFile *id = (unixFile*)*pId; + int rc; + if( !id ) return SQLITE_OK; - if( CHECK_THREADID(id) ) return SQLITE_MISUSE; unixUnlock(*pId, NO_LOCK); if( id->dirfd>=0 ) close(id->dirfd); id->dirfd = -1; sqlite3OsEnterMutex(); @@ -1414,11 +1485,11 @@ ** descriptor to pOpen->aPending. It will be automatically closed when ** the last lock is cleared. */ int *aNew; struct openCnt *pOpen = id->pOpen; - aNew = sqliteRealloc( pOpen->aPending, (pOpen->nPending+1)*sizeof(int) ); + aNew = realloc( pOpen->aPending, (pOpen->nPending+1)*sizeof(int) ); if( aNew==0 ){ /* If a malloc fails, just leak the file descriptor */ }else{ pOpen->aPending = aNew; pOpen->aPending[pOpen->nPending] = id->h; @@ -1435,11 +1506,11 @@ id->isOpen = 0; TRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); sqliteFree(id); *pId = 0; - return SQLITE_OK; + return rc; } /* ** Turn a relative pathname into a full pathname. Return a pointer ** to the full pathname stored in space obtained from sqliteMalloc(). @@ -1514,12 +1585,14 @@ static int allocateUnixFile(unixFile *pInit, OsFile **pId){ unixFile *pNew; pNew = sqliteMalloc( sizeof(unixFile) ); if( pNew==0 ){ close(pInit->h); + sqlite3OsEnterMutex(); releaseLockInfo(pInit->pLock); releaseOpenCnt(pInit->pOpen); + sqlite3OsLeaveMutex(); *pId = 0; return SQLITE_NOMEM; }else{ *pNew = *pInit; pNew->pMethod = &sqlite3UnixIoMethod; @@ -1550,11 +1623,11 @@ ** some users. Rather than argue, it seems easier just to initialize ** the whole array and silence valgrind, even if that means less randomness ** in the random seed. ** ** When testing, initializing zBuf[] to zero is all we do. That means - ** that we always use the same random number sequence.* This makes the + ** that we always use the same random number sequence. This makes the ** tests repeatable. */ memset(zBuf, 0, 256); #if !defined(SQLITE_TEST) { @@ -1575,10 +1648,11 @@ return SQLITE_OK; } /* ** Sleep for a little while. Return the amount of time slept. +** The argument is the number of milliseconds we want to sleep. */ int sqlite3UnixSleep(int ms){ #if defined(HAVE_USLEEP) && HAVE_USLEEP usleep(ms*1000); return ms; @@ -1601,10 +1675,12 @@ ** multi-threaded processes. Only a single thread is allowed to ** executed code that is surrounded by EnterMutex() and LeaveMutex(). ** ** SQLite uses only a single Mutex. There is not much critical ** code and what little there is executes quickly and without blocking. +** +** This mutex is not recursive. */ void sqlite3UnixEnterMutex(){ #ifdef SQLITE_UNIX_THREADS pthread_mutex_lock(&mutex); #endif @@ -1646,13 +1722,13 @@ # define TSD_COUNTER(N) /* no-op */ #endif /* -** If called with allocateFlag>1, then return a pointer to thread +** If called with allocateFlag>0, then return a pointer to thread ** specific data for the current thread. Allocate and zero the -** thread-specific data if it does not already exist necessary. +** thread-specific data if it does not already exist. ** ** If called with allocateFlag==0, then check the current thread ** specific data. Return it if it exists. If it does not exist, ** then return NULL. ** Index: SQLite.Interop/src/os_win.c ================================================================== --- SQLite.Interop/src/os_win.c +++ SQLite.Interop/src/os_win.c @@ -1220,11 +1220,11 @@ zFull = sqliteMalloc( nByte ); if( zFull==0 ) return 0; if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0; #elif OS_WINCE /* WinCE has no concept of a relative pathname, or so I am told. */ - zFull = sqlite3StrDup(zRelative); + zFull = sqliteStrDup(zRelative); #else char *zNotUsed; WCHAR *zWide; int nByte; zWide = utf8ToUnicode(zRelative); Index: SQLite.Interop/src/pager.c ================================================================== --- SQLite.Interop/src/pager.c +++ SQLite.Interop/src/pager.c @@ -16,11 +16,11 @@ ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.16 2006/01/13 03:36:39 rmsimpson Exp $ +** @(#) $Id: pager.c,v 1.17 2006/01/16 15:51:47 rmsimpson Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" #include "os.h" #include "pager.h" @@ -223,10 +223,18 @@ */ #define pager_hash(PN) ((PN)&(N_PG_HASH-1)) /* ** A open page cache is an instance of the following structure. +** +** Pager.errCode may be set to SQLITE_IOERR, SQLITE_CORRUPT, SQLITE_PROTOCOL +** or SQLITE_FULL. Once one of the first three errors occurs, it persists +** and is returned as the result of every major pager API call. The +** SQLITE_FULL return code is slightly different. It persists only until the +** next successful rollback is performed on the pager cache. Also, +** SQLITE_FULL does not affect the sqlite3pager_get() and sqlite3pager_lookup() +** APIs, they may still be used successfully. */ struct Pager { u8 journalOpen; /* True if journal file descriptors is valid */ u8 journalStarted; /* True if header of journal is synced */ u8 useJournal; /* Use a rollback journal on this file */ @@ -235,11 +243,11 @@ u8 stmtInUse; /* True we are in a statement subtransaction */ u8 stmtAutoopen; /* Open stmt journal when main journal is opened*/ u8 noSync; /* Do not sync the journal if true */ u8 fullSync; /* Do extra syncs of the journal for robustness */ u8 state; /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */ - u8 errMask; /* One of several kinds of errors */ + u8 errCode; /* One of several kinds of errors */ u8 tempFile; /* zFilename is a temporary file */ u8 readOnly; /* True for a read-only database */ u8 needSync; /* True if an fsync() is needed on the journal */ u8 dirtyCache; /* True if cached pages have changed */ u8 alwaysRollback; /* Disable dont_rollback() for all pages */ @@ -297,43 +305,10 @@ # define TEST_INCR(x) x++ #else # define TEST_INCR(x) #endif -/* -** These are bits that can be set in Pager.errMask. -** -** TODO: Maybe we just want a variable - Pager.errCode. Can we really -** have two simultaneous error conditions? -** -** Recovering from an SQLITE_FULL, SQLITE_LOCK, SQLITE_CORRUPT or -** SQLITE_IOERR error is not a simple matter, particularly if the pager -** cache is shared between multiple connections. -** -** SQLITE_FULL (PAGER_ERR_FULL): -** Cleared when the transaction is rolled back. -** -** SQLITE_CORRUPT (PAGER_ERR_CORRUPT): -** Cannot be cleared. The upper layer must close the current pager -** and open a new one on the same file to continue. -** -** SQLITE_PROTOCOL (PAGER_ERR_LOCK): -** This error only occurs if an internal error occurs or another process -** is not following the sqlite locking protocol (i.e. someone is -** manipulating the database file using something other than sqlite). -** This is handled in the same way as database corruption - the error -** cannot be cleared except by closing the current pager and opening -** a brand new one on the same file. -** -** SQLITE_IOERR (PAGER_ERR_DISK): -** Cleared when the transaction is rolled back. -*/ -#define PAGER_ERR_FULL 0x01 /* a write() failed */ -#define PAGER_ERR_LOCK 0x02 /* error in the locking protocol */ -#define PAGER_ERR_CORRUPT 0x04 /* database or journal corruption */ -#define PAGER_ERR_DISK 0x08 /* general disk I/O error - bad hard drive? */ - /* ** Journal files begin with the following magic string. The data ** was obtained from /dev/random. It is used only as a sanity check. ** ** Since version 2.8.0, the journal format contains additional sanity @@ -429,19 +404,15 @@ ** error code is something goes wrong. ** ** All values are stored on disk as big-endian. */ static int read32bits(OsFile *fd, u32 *pRes){ - u32 res; - int rc; - rc = sqlite3OsRead(fd, &res, sizeof(res)); + unsigned char ac[4]; + int rc = sqlite3OsRead(fd, ac, sizeof(ac)); if( rc==SQLITE_OK ){ - unsigned char ac[4]; - memcpy(ac, &res, 4); - res = (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3]; + *pRes = (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3]; } - *pRes = res; return rc; } /* ** Write a 32-bit integer into a string buffer in big-endian byte order. @@ -482,41 +453,29 @@ ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset]; return (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3]; } -/* -** Convert the bits in the pPager->errMask into an approprate -** return code. -*/ -static int pager_errcode(Pager *pPager){ - int rc = SQLITE_OK; - if( pPager->errMask & PAGER_ERR_LOCK ) rc = SQLITE_PROTOCOL; - if( pPager->errMask & PAGER_ERR_DISK ) rc = SQLITE_IOERR; - if( pPager->errMask & PAGER_ERR_FULL ) rc = SQLITE_FULL; - if( pPager->errMask & PAGER_ERR_CORRUPT ) rc = SQLITE_CORRUPT; - return rc; -} - /* ** This function should be called when an error occurs within the pager -** code to set the appropriate bits in Pager.errMask. +** code. The first argument is a pointer to the pager structure, the +** second the error-code about to be returned by a pager API function. +** The value returned is a copy of the second argument to this function. +** +** If the second argument is SQLITE_IOERR, SQLITE_CORRUPT or SQLITE_PROTOCOL, +** the error becomes persistent. All subsequent API calls on this Pager +** will immediately return the same error code. */ static int pager_error(Pager *pPager, int rc){ - switch( rc ){ - case SQLITE_PROTOCOL: - pPager->errMask |= PAGER_ERR_LOCK; - break; - case SQLITE_IOERR: - pPager->errMask |= PAGER_ERR_DISK; - break; - case SQLITE_FULL: - pPager->errMask |= PAGER_ERR_FULL; - break; - case SQLITE_CORRUPT: - pPager->errMask |= PAGER_ERR_CORRUPT; - break; + assert( pPager->errCode==SQLITE_FULL || pPager->errCode==SQLITE_OK ); + if( + rc==SQLITE_FULL || + rc==SQLITE_IOERR || + rc==SQLITE_CORRUPT || + rc==SQLITE_PROTOCOL + ){ + pPager->errCode = rc; } return rc; } #ifdef SQLITE_CHECK_PAGES @@ -539,11 +498,11 @@ ** that the page is either dirty or still matches the calculated page-hash. */ #define CHECK_PAGE(x) checkPage(x) static void checkPage(PgHdr *pPg){ Pager *pPager = pPg->pPager; - assert( !pPg->pageHash || pPager->errMask || MEMDB || pPg->dirty || + assert( !pPg->pageHash || pPager->errCode || MEMDB || pPg->dirty || pPg->pageHash==pager_pagehash(pPg) ); } #else #define CHECK_PAGE(x) @@ -881,11 +840,11 @@ ** opened. Any outstanding pages are invalidated and subsequent attempts ** to access those pages will likely result in a coredump. */ static void pager_reset(Pager *pPager){ PgHdr *pPg, *pNext; - if( pPager->errMask ) return; + if( pPager->errCode ) return; for(pPg=pPager->pAll; pPg; pPg=pNext){ pNext = pPg->pNextAll; sqliteFree(pPg); } pPager->pFirst = 0; @@ -1502,12 +1461,11 @@ pPager->journalOff = szJ; end_stmt_playback: if( rc!=SQLITE_OK ){ - pPager->errMask |= PAGER_ERR_CORRUPT; - rc = SQLITE_CORRUPT; + rc = pager_error(pPager, SQLITE_CORRUPT); }else{ pPager->journalOff = szJ; /* pager_reload_cache(pPager); */ } return rc; @@ -1689,38 +1647,39 @@ if( i>0 ) pPager->zDirectory[i-1] = 0; strcpy(pPager->zJournal, zFullPathname); sqliteFree(zFullPathname); strcpy(&pPager->zJournal[nameLen], "-journal"); pPager->fd = fd; - pPager->journalOpen = 0; + /* pPager->journalOpen = 0; */ pPager->useJournal = useJournal && !memDb; pPager->noReadlock = noReadlock && readOnly; - pPager->stmtOpen = 0; - pPager->stmtInUse = 0; - pPager->nRef = 0; + /* pPager->stmtOpen = 0; */ + /* pPager->stmtInUse = 0; */ + /* pPager->nRef = 0; */ pPager->dbSize = memDb-1; pPager->pageSize = SQLITE_DEFAULT_PAGE_SIZE; - pPager->stmtSize = 0; - pPager->stmtJSize = 0; - pPager->nPage = 0; - pPager->nMaxPage = 0; + /* pPager->stmtSize = 0; */ + /* pPager->stmtJSize = 0; */ + /* pPager->nPage = 0; */ + /* pPager->nMaxPage = 0; */ pPager->mxPage = 100; - pPager->state = PAGER_UNLOCK; - pPager->errMask = 0; + assert( PAGER_UNLOCK==0 ); + /* pPager->state = PAGER_UNLOCK; */ + /* pPager->errMask = 0; */ pPager->tempFile = tempFile; pPager->memDb = memDb; pPager->readOnly = readOnly; - pPager->needSync = 0; + /* pPager->needSync = 0; */ pPager->noSync = pPager->tempFile || !useJournal; pPager->fullSync = (pPager->noSync?0:1); - pPager->pFirst = 0; - pPager->pFirstSynced = 0; - pPager->pLast = 0; + /* pPager->pFirst = 0; */ + /* pPager->pFirstSynced = 0; */ + /* pPager->pLast = 0; */ pPager->nExtra = FORCE_ALIGNMENT(nExtra); pPager->sectorSize = PAGER_SECTOR_SIZE; - pPager->pBusyHandler = 0; - memset(pPager->aHash, 0, sizeof(pPager->aHash)); + /* pPager->pBusyHandler = 0; */ + /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ *ppPager = pPager; #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT if( pTsdro->useMemoryManagement ){ ThreadData *pTsd = sqlite3ThreadData(); pPager->pNext = pTsd->pPager; @@ -1834,11 +1793,11 @@ assert( pPager!=0 ); if( pPager->dbSize>=0 ){ n = pPager->dbSize; } else { if( sqlite3OsFileSize(pPager->fd, &n)!=SQLITE_OK ){ - pPager->errMask |= PAGER_ERR_DISK; + pager_error(pPager, SQLITE_IOERR); return 0; } if( n>0 && npageSize ){ n = 1; }else{ @@ -1980,12 +1939,12 @@ ** Truncate the file to the number of pages specified. */ int sqlite3pager_truncate(Pager *pPager, Pgno nPage){ int rc; sqlite3pager_pagecount(pPager); - if( pPager->errMask!=0 ){ - rc = pager_errcode(pPager); + if( pPager->errCode ){ + rc = pPager->errCode; return rc; } if( nPage>=(unsigned)pPager->dbSize ){ return SQLITE_OK; } @@ -2044,11 +2003,11 @@ sqlite3pager_rollback(pPager); enable_simulated_io_errors(); if( !MEMDB ){ sqlite3OsUnlock(pPager->fd, NO_LOCK); } - assert( pPager->errMask || pPager->journalOpen==0 ); + assert( pPager->errCode || pPager->journalOpen==0 ); break; } case PAGER_SHARED: { if( !MEMDB ){ sqlite3OsUnlock(pPager->fd, NO_LOCK); @@ -2071,11 +2030,11 @@ #endif pNext = pPg->pNextAll; sqliteFree(pPg); } TRACE2("CLOSE %d\n", PAGERID(pPager)); - assert( pPager->errMask || (pPager->journalOpen==0 && pPager->stmtOpen==0) ); + assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) ); if( pPager->journalOpen ){ sqlite3OsClose(&pPager->jfd); } sqliteFree(pPager->aInJournal); if( pPager->stmtOpen ){ @@ -2371,11 +2330,11 @@ /* ** Try to find a page in the cache that can be recycled. ** ** This routine may return SQLITE_IOERR, SQLITE_FULL or SQLITE_OK. It -** does not set the pPager->errMask variable. +** does not set the pPager->errCode variable. */ static int pager_recycle(Pager *pPager, int syncOk, PgHdr **ppPg){ PgHdr *pPg; *ppPg = 0; @@ -2516,11 +2475,11 @@ } if( rc!=SQLITE_OK ){ /* An error occured whilst writing to the database file or ** journal in pager_recycle(). The error is not returned to the - ** caller of this function. Instead, set the Pager.errMask variable. + ** caller of this function. Instead, set the Pager.errCode variable. ** The error will be returned to the user (or users, in the case ** of a shared pager cache) of the pager for which the error occured. */ assert( rc==SQLITE_IOERR || rc==SQLITE_FULL ); assert( p->state>=PAGER_RESERVED ); @@ -2569,12 +2528,12 @@ /* Make sure we have not hit any critical errors. */ assert( pPager!=0 ); *ppPage = 0; - if( pPager->errMask & ~(PAGER_ERR_FULL) ){ - return pager_errcode(pPager); + if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ + return pPager->errCode; } /* If this is the first page accessed, then get a SHARED lock ** on the database file. */ @@ -2706,13 +2665,13 @@ pPg->pNextHash->pPrevHash = pPg; } if( pPager->nExtra>0 ){ memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra); } - if( pPager->errMask!=0 ){ + if( pPager->errCode ){ sqlite3pager_unref(PGHDR_TO_DATA(pPg)); - rc = pager_errcode(pPager); + rc = pPager->errCode; return rc; } if( sqlite3pager_pagecount(pPager)<(int)pgno ){ memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); }else{ @@ -2765,11 +2724,11 @@ void *sqlite3pager_lookup(Pager *pPager, Pgno pgno){ PgHdr *pPg; assert( pPager!=0 ); assert( pgno!=0 ); - if( pPager->errMask & ~(PAGER_ERR_FULL) ){ + if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ return 0; } pPg = pager_lookup(pPager, pgno); if( pPg==0 ) return 0; page_ref(pPg); @@ -2863,12 +2822,12 @@ pPager->journalOpen = 1; pPager->journalStarted = 0; pPager->needSync = 0; pPager->alwaysRollback = 0; pPager->nRec = 0; - if( pPager->errMask!=0 ){ - rc = pager_errcode(pPager); + if( pPager->errCode ){ + rc = pPager->errCode; goto failed_to_open_journal; } pPager->origDbSize = pPager->dbSize; rc = writeJournalHdr(pPager); @@ -2982,12 +2941,12 @@ Pager *pPager = pPg->pPager; int rc = SQLITE_OK; /* Check for errors */ - if( pPager->errMask ){ - return pager_errcode(pPager); + if( pPager->errCode ){ + return pPager->errCode; } if( pPager->readOnly ){ return SQLITE_PERM; } @@ -3057,11 +3016,13 @@ PAGERID(pPager), pPg->pgno, pPg->needSync); CODEC(pPager, pData, pPg->pgno, 0); *(u32*)PGHDR_TO_EXTRA(pPg, pPager) = saved; if( rc!=SQLITE_OK ){ sqlite3pager_rollback(pPager); - pPager->errMask |= PAGER_ERR_FULL; + if( !pPager->errCode ){ + pager_error(pPager, SQLITE_FULL); + } return rc; } pPager->nRec++; assert( pPager->aInJournal!=0 ); pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7); @@ -3104,11 +3065,13 @@ pPager->pageSize+4); TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); CODEC(pPager, pData, pPg->pgno, 0); if( rc!=SQLITE_OK ){ sqlite3pager_rollback(pPager); - pPager->errMask |= PAGER_ERR_FULL; + if( !pPager->errCode ){ + pager_error(pPager, SQLITE_FULL); + } return rc; } pPager->stmtNRec++; assert( pPager->aInStmt!=0 ); pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); @@ -3264,19 +3227,19 @@ */ int sqlite3pager_commit(Pager *pPager){ int rc; PgHdr *pPg; - if( pPager->errMask==PAGER_ERR_FULL ){ + if( pPager->errCode==SQLITE_FULL ){ rc = sqlite3pager_rollback(pPager); if( rc==SQLITE_OK ){ rc = SQLITE_FULL; } return rc; } - if( pPager->errMask!=0 ){ - rc = pager_errcode(pPager); + if( pPager->errCode ){ + rc = pPager->errCode; return rc; } if( pPager->statedbSize = -1; return rc; } - if( pPager->errMask!=0 && pPager->errMask!=PAGER_ERR_FULL ){ + if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ if( pPager->state>=PAGER_EXCLUSIVE ){ pager_playback(pPager); } - return pager_errcode(pPager); + return pPager->errCode; } if( pPager->state==PAGER_RESERVED ){ int rc2; rc = pager_reload_cache(pPager); rc2 = pager_unwritelock(pPager); @@ -3401,11 +3364,11 @@ }else{ rc = pager_playback(pPager); } if( rc!=SQLITE_OK ){ rc = SQLITE_CORRUPT_BKPT; - pPager->errMask |= PAGER_ERR_CORRUPT; + pager_error(pPager, SQLITE_CORRUPT); } pPager->dbSize = -1; return rc; } @@ -3425,11 +3388,11 @@ a[0] = pPager->nRef; a[1] = pPager->nPage; a[2] = pPager->mxPage; a[3] = pPager->dbSize; a[4] = pPager->state; - a[5] = pPager->errMask; + a[5] = pPager->errCode; #ifdef SQLITE_TEST a[6] = pPager->nHit; a[7] = pPager->nMiss; a[8] = pPager->nOvfl; a[9] = pPager->nRead; Index: SQLite.Interop/src/pager.h ================================================================== --- SQLite.Interop/src/pager.h +++ SQLite.Interop/src/pager.h @@ -11,11 +11,11 @@ ************************************************************************* ** This header file defines the interface that the sqlite page cache ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** -** @(#) $Id: pager.h,v 1.15 2006/01/12 20:54:07 rmsimpson Exp $ +** @(#) $Id: pager.h,v 1.16 2006/01/16 15:51:47 rmsimpson Exp $ */ #ifndef _PAGER_H_ #define _PAGER_H_ Index: SQLite.Interop/src/pragma.c ================================================================== --- SQLite.Interop/src/pragma.c +++ SQLite.Interop/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.14 2006/01/12 20:54:07 rmsimpson Exp $ +** $Id: pragma.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include Index: SQLite.Interop/src/prepare.c ================================================================== --- SQLite.Interop/src/prepare.c +++ SQLite.Interop/src/prepare.c @@ -11,11 +11,11 @@ ************************************************************************* ** This file contains the implementation of the sqlite3_prepare() ** interface, and routines that contribute to loading the database schema ** from disk. ** -** $Id: prepare.c,v 1.10 2006/01/12 20:54:07 rmsimpson Exp $ +** $Id: prepare.c,v 1.11 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include @@ -320,12 +320,13 @@ ** Initialize all database files - the main database file, the file ** used to store temporary tables, and any additional database files ** created using ATTACH statements. Return a success code. If an ** error occurs, write an error message into *pzErrMsg. ** -** After the database is initialized, the SQLITE_Initialized -** bit is set in the flags field of the sqlite structure. +** After a database is initialized, the DB_SchemaLoaded bit is set +** bit is set in the flags field of the Db structure. If the database +** file was of zero-length, then the DB_Empty flag is also set. */ int sqlite3Init(sqlite3 *db, char **pzErrMsg){ int i, rc; int called_initone = 0; @@ -492,10 +493,11 @@ Parse sParse; char *zErrMsg = 0; int rc = SQLITE_OK; int i; + /* Assert that malloc() has not failed */ assert( !sqlite3ThreadDataReadOnly()->mallocFailed ); assert( ppStmt ); *ppStmt = 0; if( sqlite3SafetyOn(db) ){ Index: SQLite.Interop/src/random.c ================================================================== --- SQLite.Interop/src/random.c +++ SQLite.Interop/src/random.c @@ -13,11 +13,11 @@ ** generator (PRNG) for SQLite. ** ** Random numbers are used by some of the database backends in order ** to generate random integer keys for tables or random filenames. ** -** $Id: random.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ +** $Id: random.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" Index: SQLite.Interop/src/select.c ================================================================== --- SQLite.Interop/src/select.c +++ SQLite.Interop/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.15 2006/01/13 03:36:39 rmsimpson Exp $ +** $Id: select.c,v 1.16 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" /* @@ -1032,11 +1032,11 @@ zType = sqliteStrDup(columnType(&sNC, p)); pCol->zType = zType; pCol->affinity = sqlite3ExprAffinity(p); pColl = sqlite3ExprCollSeq(pParse, p); if( pColl ){ - pCol->zColl = sqlite3StrDup(pColl->zName); + pCol->zColl = sqliteStrDup(pColl->zName); } } pTab->iPKey = -1; return pTab; } Index: SQLite.Interop/src/server.c ================================================================== --- SQLite.Interop/src/server.c +++ SQLite.Interop/src/server.c @@ -16,11 +16,11 @@ ** -DSQLITE_SERVER=1 ** ** The configure script will never generate a Makefile with the option ** above. You will need to manually modify the Makefile if you want to ** include any of the code from this file in your project. Or, at your -** option, you may want to copy and paste the code from this file and +** option, you may copy and paste the code from this file and ** thereby avoiding a recompile of SQLite. ** ** ** This source file demonstrates how to use SQLite to create an SQL database ** server thread in a multiple-threaded program. One or more client threads @@ -38,12 +38,13 @@ ** and used within the server thread. Client calls to the database ** can be made from multiple threads (though not at the same time!) ** ** (2) Beginning with SQLite version 3.3.0, when two or more ** connections to the same database occur within the same thread, -** they will share their database cache. This reduces I/O -** and memory requirements. +** they can optionally share their database cache. This reduces +** I/O and memory requirements. Cache shared is controlled using +** the sqlite3_enable_shared_cache() API. ** ** (3) Database connections on a shared cache use table-level locking ** instead of file-level locking for improved concurrency. ** ** (4) Database connections on a shared cache can by optionally @@ -94,11 +95,12 @@ ** sqlite3_client_close ** ** These interfaces work exactly like the standard core SQLite interfaces ** having the same names without the "_client_" infix. Many other SQLite ** interfaces can be used directly without having to send messages to the -** server. The following interfaces fall into this second category: +** server as long as SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined. +** The following interfaces fall into this second category: ** ** sqlite3_bind_* ** sqlite3_changes ** sqlite3_clear_bindings ** sqlite3_column_* @@ -108,20 +110,21 @@ ** sqlite3_data_count ** sqlite3_db_handle ** sqlite3_errcode ** sqlite3_errmsg ** sqlite3_last_insert_rowid -** sqlite3_libversion -** sqlite3_mprintf ** sqlite3_total_changes ** sqlite3_transfer_bindings -** sqlite3_vmprintf ** ** A single SQLite connection (an sqlite3* object) or an SQLite statement ** (an sqlite3_stmt* object) should only be passed to a single interface -** function at a time. The connections and statements can be freely used -** by any thread as long as only one thread is using them at a time. +** function at a time. The connections and statements can be passed from +** any thread to any of the functions listed in the second group above as +** long as the same connection is not in use by two threads at once and +** as long as SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined. Additional +** information about the SQLITE_ENABLE_MEMORY_MANAGEMENT constraint is +** below. ** ** The busy handler for all database connections should remain turned ** off. That means that any lock contention will cause the associated ** sqlite3_client_step() call to return immediately with an SQLITE_BUSY ** error code. If a busy handler is enabled and lock contention occurs, @@ -130,16 +133,69 @@ ** well. It is possible to enhance the code below so that lock ** contention will cause the message to be placed back on the top of ** the queue to be tried again later. But such enhanced processing is ** not included here, in order to keep the example simple. ** -** This code assumes the use of pthreads. Pthreads implementations -** are available for windows. (See, for example +** This example code assumes the use of pthreads. Pthreads +** implementations are available for windows. (See, for example ** http://sourceware.org/pthreads-win32/announcement.html.) Or, you ** can translate the locking and thread synchronization code to use ** windows primitives easily enough. The details are left as an ** exercise to the reader. +** +**** Restrictions Associated With SQLITE_ENABLE_MEMORY_MANAGEMENT **** +** +** If you compile with SQLITE_ENABLE_MEMORY_MANAGEMENT defined, then +** SQLite includes code that tracks how much memory is being used by +** each thread. These memory counts can become confused if memory +** is allocated by one thread and then freed by another. For that +** reason, when SQLITE_ENABLE_MEMORY_MANAGEMENT is used, all operations +** that might allocate or free memory should be performanced in the same +** thread that originally created the database connection. In that case, +** many of the operations that are listed above as safe to be performed +** in separate threads would need to be sent over to the server to be +** done there. If SQLITE_ENABLE_MEMORY_MANAGEMENT is defined, then +** the following functions can be used safely from different threads +** without messing up the allocation counts: +** +** sqlite3_bind_parameter_name +** sqlite3_bind_parameter_index +** sqlite3_changes +** sqlite3_column_blob +** sqlite3_column_count +** sqlite3_complete +** sqlite3_data_count +** sqlite3_db_handle +** sqlite3_errcode +** sqlite3_errmsg +** sqlite3_last_insert_rowid +** sqlite3_total_changes +** +** The remaining functions are not thread-safe when memory management +** is enabled. So one would have to define some new interface routines +** along the following lines: +** +** sqlite3_client_bind_* +** sqlite3_client_clear_bindings +** sqlite3_client_column_* +** sqlite3_client_create_collation +** sqlite3_client_create_function +** sqlite3_client_transfer_bindings +** +** The example code in this file is intended for use with memory +** management turned off. So the implementation of these additional +** client interfaces is left as an exercise to the reader. +** +** It may seem surprising to the reader that the list of safe functions +** above does not include things like sqlite3_bind_int() or +** sqlite3_column_int(). But those routines might, in fact, allocate +** or deallocate memory. In the case of sqlite3_bind_int(), if the +** parameter was previously bound to a string that string might need +** to be deallocated before the new integer value is inserted. In +** the case of sqlite3_column_int(), the value of the column might be +** a UTF-16 string which will need to be converted to UTF-8 then into +** an integer. */ /* ** Only compile the code in this file on UNIX with a THREADSAFE build ** and only if the SQLITE_SERVER macro is defined. Index: SQLite.Interop/src/shell.c ================================================================== --- SQLite.Interop/src/shell.c +++ SQLite.Interop/src/shell.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains code to implement the "sqlite" command line ** utility for accessing SQLite databases. ** -** $Id: shell.c,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ +** $Id: shell.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include #include #include #include Index: SQLite.Interop/src/sqlite3.h ================================================================== --- SQLite.Interop/src/sqlite3.h +++ SQLite.Interop/src/sqlite3.h @@ -10,11 +10,11 @@ ** ************************************************************************* ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite3.h,v 1.15 2006/01/12 20:54:07 rmsimpson Exp $ +** @(#) $Id: sqlite3.h,v 1.16 2006/01/16 15:51:47 rmsimpson Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ #include /* Needed for the definition of va_list */ @@ -29,11 +29,11 @@ ** The version of the SQLite library. */ #ifdef SQLITE_VERSION # undef SQLITE_VERSION #endif -#define SQLITE_VERSION "3.3.0" +#define SQLITE_VERSION "3.3.1" /* ** The format of the version string is "X.Y.Z", where ** X is the major version number, Y is the minor version number and Z ** is the release number. The trailing string is often "alpha" or "beta". @@ -46,11 +46,11 @@ ** (SQLITE_VERSION_NUMBER>=3001001). */ #ifdef SQLITE_VERSION_NUMBER # undef SQLITE_VERSION_NUMBER #endif -#define SQLITE_VERSION_NUMBER 3003000 +#define SQLITE_VERSION_NUMBER 3003001 /* ** The version string is also compiled into the library so that a program ** can check to make sure that the lib*.a file and the *.h file are from ** the same version. The sqlite3_libversion() function returns a pointer Index: SQLite.Interop/src/sqliteInt.h ================================================================== --- SQLite.Interop/src/sqliteInt.h +++ SQLite.Interop/src/sqliteInt.h @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.14 2006/01/12 20:54:07 rmsimpson Exp $ +** @(#) $Id: sqliteInt.h,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* @@ -282,10 +282,11 @@ #endif #define sqliteFree(x) sqlite3FreeX(x) #define sqliteAllocSize(x) sqlite3AllocSize(x) + /* ** An instance of this structure might be allocated to store information ** specific to a single thread. ** @@ -1751,11 +1752,11 @@ #else #define sqlite3TableLock(v,w,x,y,z) #endif void sqlite3MallocClearFailed(); -#ifdef NDEBUG +#ifndef SQLITE_MEMDEBUG #define sqlite3MallocDisallow() #define sqlite3MallocAllow() #else void sqlite3MallocDisallow(); void sqlite3MallocAllow(); Index: SQLite.Interop/src/tclsqlite.c ================================================================== --- SQLite.Interop/src/tclsqlite.c +++ SQLite.Interop/src/tclsqlite.c @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** A TCL Interface to SQLite ** -** $Id: tclsqlite.c,v 1.14 2006/01/12 20:54:08 rmsimpson Exp $ +** $Id: tclsqlite.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #ifndef NO_TCL /* Omit this whole file if TCL is unavailable */ #include "sqliteInt.h" #include "hash.h" Index: SQLite.Interop/src/tokenize.c ================================================================== --- SQLite.Interop/src/tokenize.c +++ SQLite.Interop/src/tokenize.c @@ -13,11 +13,11 @@ ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** -** $Id: tokenize.c,v 1.18 2006/01/13 03:36:39 rmsimpson Exp $ +** $Id: tokenize.c,v 1.19 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include #include Index: SQLite.Interop/src/update.c ================================================================== --- SQLite.Interop/src/update.c +++ SQLite.Interop/src/update.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** -** $Id: update.c,v 1.14 2006/01/12 20:54:08 rmsimpson Exp $ +** $Id: update.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** The most recently coded instruction was an OP_Column to retrieve the Index: SQLite.Interop/src/utf.c ================================================================== --- SQLite.Interop/src/utf.c +++ SQLite.Interop/src/utf.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains routines used to translate between UTF-8, ** UTF-16, UTF-16BE, and UTF-16LE. ** -** $Id: utf.c,v 1.14 2006/01/12 20:54:08 rmsimpson Exp $ +** $Id: utf.c,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ ** ** Notes on UTF-8: ** ** Byte-0 Byte-1 Byte-2 Byte-3 Value ** 0xxxxxxx 00000000 00000000 0xxxxxxx @@ -462,11 +462,11 @@ memset(&m, 0, sizeof(m)); sqlite3VdbeMemSetStr(&m, z, nByte, SQLITE_UTF16NATIVE, SQLITE_STATIC); sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8); assert( m.flags & MEM_Term ); assert( m.flags & MEM_Str ); - return (m.flags & MEM_Dyn)!=0 ? m.z : sqlite3StrDup(m.z); + return (m.flags & MEM_Dyn)!=0 ? m.z : sqliteStrDup(m.z); } /* ** pZ is a UTF-16 encoded unicode string. If nChar is less than zero, ** return the number of bytes up to (but not including), the first pair Index: SQLite.Interop/src/util.c ================================================================== --- SQLite.Interop/src/util.c +++ SQLite.Interop/src/util.c @@ -12,11 +12,11 @@ ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.15 2006/01/12 20:54:08 rmsimpson Exp $ +** $Id: util.c,v 1.16 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include #include @@ -645,13 +645,15 @@ ** The number of bytes allocated does not include any overhead inserted by ** any malloc() wrapper functions that may be called. So the value returned ** is the number of bytes that were available to SQLite using pointer p, ** regardless of how much memory was actually allocated. */ +#if 0 /* This is never actually used */ int sqlite3AllocSize(void *p){ return OSSIZEOF(p); } +#endif /* ** Make a copy of a string in memory obtained from sqliteMalloc(). These ** functions call sqlite3MallocRaw() directly instead of sqliteMalloc(). This ** is because when memory debugging is turned on, these two functions are @@ -1351,18 +1353,18 @@ /* ** This function sets a flag in the thread-specific-data structure that will ** cause an assert to fail if sqliteMalloc() or sqliteRealloc() is called. */ void sqlite3MallocDisallow(){ - assert(!sqlite3ThreadData()->mallocDisallowed); - sqlite3ThreadData()->mallocDisallowed = 1; + assert( sqlite3ThreadData()->mallocDisallowed>=0 ); + sqlite3ThreadData()->mallocDisallowed++; } /* ** This function clears the flag set in the thread-specific-data structure set ** by sqlite3MallocDisallow(). */ void sqlite3MallocAllow(){ - assert(sqlite3ThreadData()->mallocDisallowed); - sqlite3ThreadData()->mallocDisallowed = 0; + assert( sqlite3ThreadData()->mallocDisallowed>0 ); + sqlite3ThreadData()->mallocDisallowed--; } #endif Index: SQLite.Interop/src/vacuum.c ================================================================== --- SQLite.Interop/src/vacuum.c +++ SQLite.Interop/src/vacuum.c @@ -12,11 +12,11 @@ ** This file contains code used to implement the VACUUM command. ** ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. ** -** $Id: vacuum.c,v 1.15 2006/01/13 03:36:39 rmsimpson Exp $ +** $Id: vacuum.c,v 1.16 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" #include "os.h" Index: SQLite.Interop/src/vdbe.c ================================================================== --- SQLite.Interop/src/vdbe.c +++ SQLite.Interop/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.15 2006/01/13 03:36:39 rmsimpson Exp $ +** $Id: vdbe.c,v 1.16 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" #include "os.h" #include #include "vdbeInt.h" @@ -663,12 +663,11 @@ break; } /* Opcode: String8 * * P3 ** -** P3 points to a nul terminated UTF-8 string that is P1 character long -** (not counting the nul terminator). This opcode is transformed +** P3 points to a nul terminated UTF-8 string. This opcode is transformed ** into an OP_String before it is executed for the first time. */ case OP_String8: { /* same as TK_STRING */ assert( pOp->p3!=0 ); pOp->opcode = OP_String; @@ -685,20 +684,20 @@ if( pOp->p3type==P3_DYNAMIC ){ sqliteFree(pOp->p3); } pOp->p3type = P3_DYNAMIC; pOp->p3 = pTos->z; - pOp->p1 *= 2; + pOp->p1 = pTos->n; break; } #endif /* Otherwise fall through to the next case, OP_String */ } /* Opcode: String P1 * P3 ** -** The string value P3 of length P1 is pushed onto the stack. +** The string value P3 of length P1 (bytes) is pushed onto the stack. */ case OP_String: { pTos++; assert( pOp->p3!=0 ); pTos->flags = MEM_Str|MEM_Static|MEM_Term; @@ -1881,14 +1880,11 @@ char *zRec; /* Pointer to complete record-data */ BtCursor *pCrsr; /* The BTree cursor */ u32 *aType; /* aType[i] holds the numeric type of the i-th column */ u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */ u32 nField; /* number of fields in the record */ - u32 szHdr; /* Number of bytes in the record header */ int len; /* The length of the serialized data for the column */ - int offset = 0; /* Offset into the data */ - int idx; /* Index into the header */ int i; /* Loop counter */ char *zData; /* Part of the record being decoded */ Mem sMem; /* For storing the record being decoded */ sMem.flags = 0; @@ -1960,11 +1956,11 @@ nField = 0; } /* If payloadSize is 0, then just push a NULL onto the stack. */ if( payloadSize==0 ){ - pTos->flags = MEM_Null; + assert( pTos->flags==MEM_Null ); break; } assert( p2cacheStatus==p->cacheCtr ){ aType = pC->aType; aOffset = pC->aOffset; }else{ - int avail; /* Number of bytes of available data */ + u8 *zIdx; /* Index into header */ + u8 *zEndHdr; /* Pointer to first byte after the header */ + u32 offset; /* Offset into the data */ + int avail; /* Number of bytes of available data */ if( pC && pC->aType ){ aType = pC->aType; }else{ aType = sqliteMallocRaw( 2*nField*sizeof(aType) ); } @@ -2005,59 +2004,56 @@ pC->aRow = (u8*)zData; }else{ pC->aRow = 0; } } - idx = GetVarint((u8*)zData, szHdr); - + zIdx = (u8 *)GetVarint((u8*)zData, offset); /* The KeyFetch() or DataFetch() above are fast and will get the entire ** record header in most cases. But they will fail to get the complete ** record header if the record header does not fit on a single page ** in the B-Tree. When that happens, use sqlite3VdbeMemFromBtree() to ** acquire the complete header text. */ - if( !zRec && availisIndex, &sMem); + if( !zRec && availisIndex, &sMem); if( rc!=SQLITE_OK ){ goto op_column_out; } zData = sMem.z; } + zEndHdr = (u8 *)zData + offset; + zIdx = zData + (int)zIdx; /* Scan the header and use it to fill in the aType[] and aOffset[] ** arrays. aType[i] will contain the type integer for the i-th ** column and aOffset[i] will contain the offset from the beginning ** of the record to the start of the data for the i-th column */ - offset = szHdr; - assert( offset>0 ); - i = 0; - while( idxzEndHdr || offset>payloadSize ){ rc = SQLITE_CORRUPT_BKPT; goto op_column_out; } /* Remember all aType and aColumn information if we have a cursor @@ -4208,11 +4204,11 @@ assert( i>=0 ); /* FIX ME: This should be allocated as part of the vdbe at compile-time */ if( i>=p->contextStackDepth ){ p->contextStackDepth = i+1; - sqlite3ReallocOrFree((void**)&p->contextStack, sizeof(Context)*(i+1)); + sqliteReallocOrFree((void**)&p->contextStack, sizeof(Context)*(i+1)); if( p->contextStack==0 ) goto no_mem; } pContext = &p->contextStack[i]; pContext->lastRowid = db->lastRowid; pContext->nChange = p->nChange; Index: SQLite.Interop/src/vdbe.h ================================================================== --- SQLite.Interop/src/vdbe.h +++ SQLite.Interop/src/vdbe.h @@ -13,11 +13,11 @@ ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** -** $Id: vdbe.h,v 1.14 2006/01/12 20:54:08 rmsimpson Exp $ +** $Id: vdbe.h,v 1.15 2006/01/16 15:51:47 rmsimpson Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ #include Index: SQLite.Interop/src/vdbeapi.c ================================================================== --- SQLite.Interop/src/vdbeapi.c +++ SQLite.Interop/src/vdbeapi.c @@ -154,11 +154,12 @@ int sqlite3_step(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; sqlite3 *db; int rc; - assert(!sqlite3ThreadDataReadOnly()->mallocFailed); + /* Assert that malloc() has not failed */ + assert( !sqlite3ThreadDataReadOnly()->mallocFailed ); if( p==0 || p->magic!=VDBE_MAGIC_RUN ){ return SQLITE_MISUSE; } if( p->aborted ){ Index: SQLite.Interop/src/vdbeaux.c ================================================================== --- SQLite.Interop/src/vdbeaux.c +++ SQLite.Interop/src/vdbeaux.c @@ -100,11 +100,11 @@ i = p->nOp; p->nOp++; assert( p->magic==VDBE_MAGIC_INIT ); resizeOpArray(p, i+1); - if( p->aOp==0 || p->nOp<=i ){ + if( p->aOp==0 || p->nOpAlloc<=i ){ return 0; } pOp = &p->aOp[i]; pOp->opcode = op; pOp->p1 = p1; @@ -145,11 +145,11 @@ int i; i = p->nLabel++; assert( p->magic==VDBE_MAGIC_INIT ); if( i>=p->nLabelAlloc ){ p->nLabelAlloc = p->nLabelAlloc*2 + 10; - sqlite3ReallocOrFree((void**)&p->aLabel, + sqliteReallocOrFree((void**)&p->aLabel, p->nLabelAlloc*sizeof(p->aLabel[0])); } if( p->aLabel ){ p->aLabel[i] = -1; } Index: SQLite.Interop/src/where.c ================================================================== --- SQLite.Interop/src/where.c +++ SQLite.Interop/src/where.c @@ -14,11 +14,11 @@ ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** -** $Id: where.c,v 1.16 2006/01/12 20:54:08 rmsimpson Exp $ +** $Id: where.c,v 1.17 2006/01/16 15:51:47 rmsimpson Exp $ */ #include "sqliteInt.h" /* ** The number of bits in a Bitmask. "BMS" means "BitMask Size". @@ -641,19 +641,22 @@ } pTerm->nChild = 2; } #endif /* SQLITE_OMIT_BETWEEN_OPTIMIZATION */ -#ifndef SQLITE_OMIT_OR_OPTIMIZATION +#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY) /* Attempt to convert OR-connected terms into an IN operator so that ** they can make use of indices. Example: ** ** x = expr1 OR expr2 = x OR x = expr3 ** ** is converted into ** ** x IN (expr1,expr2,expr3) + ** + ** This optimization must be omitted if OMIT_SUBQUERY is defined because + ** the compiler for the the IN operator is part of sub-queries. */ else if( pExpr->op==TK_OR ){ int ok; int i, j; int iColumn, iCursor; @@ -1162,18 +1165,28 @@ ** Generate code that builds a probe for an index. Details: ** ** * Check the top nColumn entries on the stack. If any ** of those entries are NULL, jump immediately to brk, ** which is the loop exit, since no index entry will match -** if any part of the key is NULL. +** if any part of the key is NULL. Pop (nColumn+nExtra) +** elements from the stack. ** ** * Construct a probe entry from the top nColumn entries in -** the stack with affinities appropriate for index pIdx. +** the stack with affinities appropriate for index pIdx. +** Only nColumn elements are popped from the stack in this case +** (by OP_MakeRecord). +** */ -static void buildIndexProbe(Vdbe *v, int nColumn, int brk, Index *pIdx){ +static void buildIndexProbe( + Vdbe *v, + int nColumn, + int nExtra, + int brk, + Index *pIdx +){ sqlite3VdbeAddOp(v, OP_NotNull, -nColumn, sqlite3VdbeCurrentAddr(v)+3); - sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0); + sqlite3VdbeAddOp(v, OP_Pop, nColumn+nExtra, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, brk); sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); sqlite3IndexAffinityStr(v, pIdx); } @@ -1208,11 +1221,11 @@ sqlite3CodeSubselect(pParse, pX); iTab = pX->iTable; sqlite3VdbeAddOp(v, OP_Rewind, iTab, brk); VdbeComment((v, "# %.*s", pX->span.n, pX->span.z)); pLevel->nIn++; - sqlite3ReallocOrFree((void**)&pLevel->aInLoop, + sqliteReallocOrFree((void**)&pLevel->aInLoop, sizeof(pLevel->aInLoop[0])*3*pLevel->nIn); aIn = pLevel->aInLoop; if( aIn ){ aIn += pLevel->nIn*3 - 3; aIn[0] = OP_Next; @@ -1580,10 +1593,17 @@ pTab = pTabItem->pTab; iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); if( pTab->isTransient || pTab->pSelect ) continue; if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){ sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, OP_OpenRead); + if( pTab->nCol<(sizeof(Bitmask)*8) ){ + Bitmask b = pTabItem->colUsed; + int n = 0; + for(; b; b=b>>1, n++); + sqlite3VdbeChangeP2(v, sqlite3VdbeCurrentAddr(v)-1, n); + assert( n<=pTab->nCol ); + } }else{ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); } pLevel->iTabCur = pTabItem->iCursor; if( (pIx = pLevel->pIdx)!=0 ){ @@ -1781,11 +1801,11 @@ topEq = 1; } if( testOp!=OP_Noop ){ int nCol = nEq + topLimit; pLevel->iMem = pParse->nMem++; - buildIndexProbe(v, nCol, brk, pIdx); + buildIndexProbe(v, nCol, nEq, brk, pIdx); if( bRev ){ int op = topEq ? OP_MoveLe : OP_MoveLt; sqlite3VdbeAddOp(v, op, iIdxCur, brk); }else{ sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1); @@ -1816,11 +1836,11 @@ }else{ btmEq = 1; } if( nEq>0 || btmLimit ){ int nCol = nEq + btmLimit; - buildIndexProbe(v, nCol, brk, pIdx); + buildIndexProbe(v, nCol, 0, brk, pIdx); if( bRev ){ pLevel->iMem = pParse->nMem++; sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1); testOp = OP_IdxLT; }else{ @@ -1870,11 +1890,11 @@ codeAllEqualityTerms(pParse, pLevel, &wc, notReady, brk); /* Generate a single key that will be used to both start and terminate ** the search */ - buildIndexProbe(v, nEq, brk, pIdx); + buildIndexProbe(v, nEq, 0, brk, pIdx); sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 0); /* Generate code (1) to move to the first matching element of the table. ** Then generate code (2) that jumps to "brk" after the cursor is past ** the last matching element of the table. The code (1) is executed