# # # patch "sqlite/analyze.c" # from [7d2b7ab9a9c2fd6e55700f69064dfdd3e36d7a8a] # to [4bbf5ddf9680587c6d4917e02e378b6037be3651] # # patch "sqlite/attach.c" # from [b11eb4d5d3fb99a10a626956bccc7215f6b68b16] # to [a16ada4a4654a0d126b8223ec9494ebb81bc5c3c] # # patch "sqlite/btree.c" # from [4d4bef16fbf4f53ec3b161cfe5bb19bbc27a281d] # to [7adc16a10b42d3a3c39e64af85b748c68156f6b2] # # patch "sqlite/btree.h" # from [066444ee25bd6e6accb997bfd2cf5ace14dbcd00] # to [9b2cc0d113c0bc2d37d244b9a394d56948c9acbf] # # patch "sqlite/build.c" # from [6bd68dc730b01c1727738f8e4b5c730eb0ddb421] # to [7c2efa468f0c404ef5aa648d43c383318390937f] # # patch "sqlite/date.c" # from [393c73fc027597e008dcd81454544659e978b05c] # to [74b76691bddf58b634f6bf4a77c8c58234268c6e] # # patch "sqlite/expr.c" # from [dfd25ae8f8f2ebf3d8dea605a5cea959946aabb7] # to [a8740c24af3f39f2d502be1a1c640c96435eaac0] # # patch "sqlite/func.c" # from [b7e1e220a6795ecae7649815145ea5f8644dfa5f] # to [94372fe3cf26b81d4dcdc15f98ff240c37c8c708] # # patch "sqlite/hash.c" # from [449f3d6620193aa557f5d86cbc5cc6b87702b185] # to [67b23e14f0257b69a3e8aa663e4eeadc1a2b6fd5] # # patch "sqlite/insert.c" # from [e9526ced19978a55687b55faea969b6ff2a53fb4] # to [967be8c143d64c904ba4e6f66760824898a75e3c] # # patch "sqlite/keywordhash.h" # from [abfcf4e03418b130f420f2d8c4a733d137bd2912] # to [65fe072d2fa7cf2cfece3c7550f9085ec2988717] # # patch "sqlite/loadext.c" # from [bbfdbf452c71b6f2723375478a365788498ec3cd] # to [146fb9b9dc6133e763888d710205c32ebf8eeca2] # # patch "sqlite/main.c" # from [33c32014da3a1471e8869d2eba32b2c4314c39ce] # to [c8915777ae8e50823d01eefe2b674ef68c32bf61] # # patch "sqlite/opcodes.c" # from [89763333d47d401e5b32d2a5fe456a49414b4544] # to [d21a21fc60da3874a0970a6e67c81c56ec507d6c] # # patch "sqlite/opcodes.h" # from [2a03d6171b53b07d4b9db8a68943cb44da8191e7] # to [a58b9a527965930bd27502dd8b1f101d326aa08f] # # patch "sqlite/os.c" # from [59f05de8c5777c34876607114a2fbe55ae578235] # to [4650e98aadd27abfe1698ff58edf6893c58d4881] # # patch "sqlite/os.h" # from [17fc73165cb7436aa79492d2dff754baec74fcb9] # to [9240adf088fd55732f8926f9017601ba3430ead8] # # patch "sqlite/os_common.h" # from [545426356f0868a6765e70cb59e319d3acad0ed6] # to [0969285cc1e0b1ccc7a2cd7ce8eb144176ce3369] # # patch "sqlite/os_os2.c" # from [8ee8207fe218a1acf3a31d59753e165e5c23bb95] # to [2ce97909b926a598823f97338027dbec1dcf4165] # # patch "sqlite/os_unix.c" # from [2f7f7dbb95bbfa109f951c828b248102ab75b621] # to [426b4c03c304ad78746d65d9ba101e0b72e18e23] # # patch "sqlite/os_win.c" # from [8736cf3a49fd651a6538857480f302807d57814c] # to [c9a99524d6b2bdec636264cad1b67553925e3309] # # patch "sqlite/pager.c" # from [d6ad66eb119602cb2e6a097f8f635372ba677d23] # to [655073dd7b32eade2f10f69e1d51fece380d45e1] # # patch "sqlite/pager.h" # from [2e6d42f4ae004ae748a037b8468112b851c447a7] # to [e79a24cf200b8771366217f5bca414f5b7823f42] # # patch "sqlite/parse.c" # from [c0428566a80239da0b429390988f0fec4351e148] # to [b29e3203362be291200999d2e91d01187473f551] # # patch "sqlite/parse.h" # from [6f6a83f5cf2575172e44744ed9ffeacbbe812531] # to [10959ac7d8e432bad0301c318fe8ff29d464d533] # # patch "sqlite/pragma.c" # from [5091300911670ddaa552bfa12c45cbca1bb7e7d6] # to [3b992b5b2640d6ae25cef05aa6a42cd1d6c43234] # # patch "sqlite/prepare.c" # from [484389c6811415b8f23d259ac9c029613e1c72c3] # to [37207b2b2ccb41d379b01dd62231686bcc48ef1f] # # patch "sqlite/printf.c" # from [aade23a789d7cc88b397ec0d33a0a01a33a7a9c1] # to [0c6f40648770831341ac45ab32423a80b4c87f05] # # patch "sqlite/select.c" # from [63b2163f35fd2570a02dab5759979644c4405f1c] # to [6d6e7c992fb0f170e60e6c1f53fe87f52e73aeba] # # patch "sqlite/sqlite3.h" # from [c17a4ef52a78c0ca61df95965c1ce3c2192b98de] # to [9cbbd1bfa4521bee3ec1584f5b4356888c9bb688] # # patch "sqlite/sqlite3ext.h" # from [011c75fd6459a61454514af07c7a4f1f5c767f27] # to [7d0d363ea7327e817ef0dfe1b7eee1f171b72890] # # patch "sqlite/sqliteInt.h" # from [409dfff7f08135017aa2dfb65245dfc7b1db7099] # to [347160d30eb61210417f1086aeb57d7d3e2a8191] # # patch "sqlite/trigger.c" # from [8c55d31876013ed4e97ee7ce24478fbe00db49bb] # to [420192efe3e6f03addf7897c60c3c8bf913d3493] # # patch "sqlite/update.c" # from [bdfcf3600f129bd5f06094781ab41cd7b7f5ab25] # to [3359041db390a8f856d67272f299600e2104f350] # # patch "sqlite/utf.c" # from [67ecb1032bc0b42c105e88d65ef9d9f626eb0e1f] # to [e64a48bc21aa973eb622dd47da87d56a4cdcf528] # # patch "sqlite/util.c" # from [91d4cb189476906639ae611927d939691d1365f6] # to [b6344325378e75b9e18175d8b6aed1723d73dad9] # # patch "sqlite/vacuum.c" # from [b4569b08aaa5afb141af3f76d0315745db4e9e4b] # to [8bd895d29e7074e78d4e80f948e35ddc9cf2beef] # # patch "sqlite/vdbe.c" # from [b5a2ad31c177b6c2d5fedb2ed180b9b57058398b] # to [87e31f0790ac8a5aad7b7fcd5b97948943fccba3] # # patch "sqlite/vdbeInt.h" # from [13ba07121cf534d5b80130d2f5eb0a4937a36bba] # to [4b19fd8febad3fd14c4c97adaefc06754d323132] # # patch "sqlite/vdbeapi.c" # from [2d1e6843af8705a1172e54a418d2a3d5febd1dd7] # to [1fca7ff056d03f131caa6b1296bb221da65ed7f4] # # patch "sqlite/vdbeaux.c" # from [c5324d62f51529bccc5be3b04bac2e4eeae1569a] # to [0bae26de1ba1683de80c89ba1d4081b4c809d05b] # # patch "sqlite/vdbefifo.c" # from [9efb94c8c3f4c979ebd0028219483f88e57584f5] # to [3ca8049c561d5d67cbcb94dc909ae9bb68c0bf8f] # # patch "sqlite/vdbemem.c" # from [ff2424bee9eaf7c61d1f28bc0e711bebddebd653] # to [981a113405bd9b80aeb71fe246a2f01708e8a8f7] # # patch "sqlite/where.c" # from [2a919a3fbaff2e55604119f7c60133db459b404c] # to [fce0dad6b230eb7ea844e8b8667c074d07e3fdd5] # ============================================================ --- sqlite/analyze.c 7d2b7ab9a9c2fd6e55700f69064dfdd3e36d7a8a +++ sqlite/analyze.c 4bbf5ddf9680587c6d4917e02e378b6037be3651 @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code associated with the ANALYZE command. ** -** @(#) $Id: analyze.c,v 1.16 2006/01/10 17:58:23 danielk1977 Exp $ +** @(#) $Id: analyze.c,v 1.17 2007/03/29 05:51:49 drh Exp $ */ #ifndef SQLITE_OMIT_ANALYZE #include "sqliteInt.h" @@ -211,7 +211,7 @@ static void analyzeOneTable( } } sqlite3VdbeOp3(v, OP_MakeRecord, 3, 0, "aaa", 0); - sqlite3VdbeAddOp(v, OP_Insert, iStatCur, 0); + sqlite3VdbeAddOp(v, OP_Insert, iStatCur, OPFLAG_APPEND); sqlite3VdbeJumpHere(v, addr); } } ============================================================ --- sqlite/attach.c b11eb4d5d3fb99a10a626956bccc7215f6b68b16 +++ sqlite/attach.c a16ada4a4654a0d126b8223ec9494ebb81bc5c3c @@ -11,10 +11,11 @@ ************************************************************************* ** This file contains code used to implement the ATTACH and DETACH commands. ** -** $Id: attach.c,v 1.53 2006/06/27 16:34:57 danielk1977 Exp $ +** $Id: attach.c,v 1.57 2007/03/27 21:47:07 drh Exp $ */ #include "sqliteInt.h" +#ifndef SQLITE_OMIT_ATTACH /* ** Resolve an expression that was part of an ATTACH or DETACH statement. This ** is slightly different from resolving a normal SQL expression, because simple @@ -133,13 +134,14 @@ static void attachFunc( "attached databases must use the same text encoding as main database"); goto attach_error; } + sqlite3PagerLockingMode(sqlite3BtreePager(aNew->pBt), db->dfltLockMode); } aNew->zName = sqliteStrDup(zName); aNew->safety_level = 3; #if SQLITE_HAS_CODEC { - extern int sqlite3CodecAttach(sqlite3*, int, void*, int); + extern int sqlite3CodecAttach(sqlite3*, int, const void*, int); extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); int nKey; char *zKey; @@ -188,7 +190,7 @@ static void attachFunc( sqlite3ResetInternalSchema(db, 0); db->nDb = iDb; if( rc==SQLITE_NOMEM ){ - if( !sqlite3MallocFailed() ) sqlite3FailedMalloc(); + sqlite3FailedMalloc(); sqlite3_snprintf(sizeof(zErr),zErr, "out of memory"); }else{ sqlite3_snprintf(sizeof(zErr),zErr, "unable to open database: %s", zFile); @@ -350,14 +352,17 @@ void sqlite3Attach(Parse *pParse, Expr * void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){ codeAttach(pParse, SQLITE_ATTACH, "sqlite_attach", 3, p, p, pDbname, pKey); } +#endif /* SQLITE_OMIT_ATTACH */ /* ** Register the functions sqlite_attach and sqlite_detach. */ void sqlite3AttachFunctions(sqlite3 *db){ +#ifndef SQLITE_OMIT_ATTACH static const int enc = SQLITE_UTF8; sqlite3CreateFunc(db, "sqlite_attach", 3, enc, db, attachFunc, 0, 0); sqlite3CreateFunc(db, "sqlite_detach", 1, enc, db, detachFunc, 0, 0); +#endif } /* ============================================================ --- sqlite/btree.c 4d4bef16fbf4f53ec3b161cfe5bb19bbc27a281d +++ sqlite/btree.c 7adc16a10b42d3a3c39e64af85b748c68156f6b2 @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.335 2007/02/10 19:22:36 drh Exp $ +** $Id: btree.c,v 1.354 2007/04/09 12:45:03 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -22,13 +22,13 @@ ** entries and N+1 pointers to subpages. ** ** ---------------------------------------------------------------- -** | Ptr(0) | Key(0) | Ptr(1) | Key(1) | ... | Key(N) | Ptr(N+1) | +** | Ptr(0) | Key(0) | Ptr(1) | Key(1) | ... | Key(N-1) | Ptr(N) | ** ---------------------------------------------------------------- ** ** All of the keys on the page that Ptr(0) points to have values less ** than Key(0). All of the keys on page Ptr(1) and its subpages have ** values greater than Key(0) and less than Key(1). All of the keys -** on Ptr(N+1) and its subpages have values greater than Key(N). And +** on Ptr(N) and its subpages have values greater than Key(N-1). And ** so forth. ** ** Finding a particular key requires reading O(log(M)) pages from the @@ -41,7 +41,7 @@ ** page. If the payload is larger than the preset amount then surplus ** bytes are stored on overflow pages. The payload for an entry ** and the preceding pointer are combined to form a "Cell". Each -** page has a small header which contains the Ptr(N+1) pointer and other +** page has a small header which contains the Ptr(N) pointer and other ** information such as the size of key and data. ** ** FORMAT DETAILS @@ -123,7 +123,7 @@ ** 3 2 number of cells on this page ** 5 2 first byte of the cell content area ** 7 1 number of fragmented free bytes -** 8 4 Right child (the Ptr(N+1) value). Omitted on leaves. +** 8 4 Right child (the Ptr(N) value). Omitted on leaves. ** ** The flags define the format of this btree page. The leaf flag means that ** this page has no children. The zerodata flag means that this page carries @@ -291,6 +291,7 @@ struct MemPage { } aOvfl[5]; BtShared *pBt; /* Pointer back to BTree structure */ u8 *aData; /* Pointer back to the start of the page */ + DbPage *pDbPage; /* Pager page handle */ Pgno pgno; /* Page number for this page */ MemPage *pParent; /* The parent of this page. NULL for root */ }; @@ -365,6 +366,7 @@ struct CellInfo { u8 *pCell; /* Pointer to the start of cell content */ i64 nKey; /* The key for INTKEY tables, or number of bytes in key */ u32 nData; /* Number of bytes of data */ + u32 nPayload; /* Total amount of payload */ u16 nHeader; /* Size of the cell content header in bytes */ u16 nLocal; /* Amount of payload held locally */ u16 iOverflow; /* Offset to overflow page number. Zero if no overflow */ @@ -711,6 +713,15 @@ static int saveAllCursors(BtShared *pBt, } /* +** Clear the current cursor position. +*/ +static void clearCursorPosition(BtCursor *pCur){ + sqliteFree(pCur->pKey); + pCur->pKey = 0; + pCur->eState = CURSOR_INVALID; +} + +/* ** 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 @@ -721,23 +732,21 @@ static int saveAllCursors(BtShared *pBt, ** returning the cursor to it's saved position, any saved position is deleted ** and the cursor state set to CURSOR_INVALID. */ -static int restoreOrClearCursorPositionX(BtCursor *pCur, int doSeek){ - int rc = SQLITE_OK; +static int restoreOrClearCursorPositionX(BtCursor *pCur){ + int rc; assert( pCur->eState==CURSOR_REQUIRESEEK ); pCur->eState = CURSOR_INVALID; - if( doSeek ){ - rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, &pCur->skip); - } + rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skip); if( rc==SQLITE_OK ){ sqliteFree(pCur->pKey); pCur->pKey = 0; - assert( CURSOR_VALID==pCur->eState || CURSOR_INVALID==pCur->eState ); + assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID ); } return rc; } -#define restoreOrClearCursorPosition(p,x) \ - (p->eState==CURSOR_REQUIRESEEK?restoreOrClearCursorPositionX(p,x):SQLITE_OK) +#define restoreOrClearCursorPosition(p) \ + (p->eState==CURSOR_REQUIRESEEK?restoreOrClearCursorPositionX(p):SQLITE_OK) #ifndef SQLITE_OMIT_AUTOVACUUM /* @@ -814,9 +823,10 @@ static int ptrmapPut(BtShared *pBt, Pgno ** An error code is returned if something goes wrong, otherwise SQLITE_OK. */ static int ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent){ - u8 *pPtrmap; /* The pointer map page */ - Pgno iPtrmap; /* The pointer map page number */ - int offset; /* Offset in pointer map page */ + DbPage *pDbPage; /* The pointer map page */ + u8 *pPtrmap; /* The pointer map data */ + Pgno iPtrmap; /* The pointer map page number */ + int offset; /* Offset in pointer map page */ int rc; /* The master-journal page number must never be used as a pointer map page */ @@ -827,22 +837,23 @@ static int ptrmapPut(BtShared *pBt, Pgno return SQLITE_CORRUPT_BKPT; } iPtrmap = PTRMAP_PAGENO(pBt, key); - rc = sqlite3pager_get(pBt->pPager, iPtrmap, (void **)&pPtrmap); + rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage); if( rc!=SQLITE_OK ){ return rc; } offset = PTRMAP_PTROFFSET(pBt, key); + pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){ TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent)); - rc = sqlite3pager_write(pPtrmap); + rc = sqlite3PagerWrite(pDbPage); if( rc==SQLITE_OK ){ pPtrmap[offset] = eType; put4byte(&pPtrmap[offset+1], parent); } } - sqlite3pager_unref(pPtrmap); + sqlite3PagerUnref(pDbPage); return rc; } @@ -854,23 +865,25 @@ static int ptrmapGet(BtShared *pBt, Pgno ** An error code is returned if something goes wrong, otherwise SQLITE_OK. */ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ + DbPage *pDbPage; /* The pointer map page */ int iPtrmap; /* Pointer map page index */ u8 *pPtrmap; /* Pointer map page data */ int offset; /* Offset of entry in pointer map */ int rc; iPtrmap = PTRMAP_PAGENO(pBt, key); - rc = sqlite3pager_get(pBt->pPager, iPtrmap, (void **)&pPtrmap); + rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage); if( rc!=0 ){ return rc; } + pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); offset = PTRMAP_PTROFFSET(pBt, key); assert( pEType!=0 ); *pEType = pPtrmap[offset]; if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]); - sqlite3pager_unref(pPtrmap); + sqlite3PagerUnref(pDbPage); if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_BKPT; return SQLITE_OK; } @@ -944,6 +957,7 @@ static void parseCellPtr( pInfo->nKey = x; nPayload += x; } + pInfo->nPayload = nPayload; pInfo->nHeader = n; if( nPayload<=pPage->maxLocal ){ /* This is the (easy) common case where the entire payload fits @@ -1020,6 +1034,7 @@ static int ptrmapPutOvflPtr(MemPage *pPa if( pCell ){ CellInfo info; parseCellPtr(pPage, pCell, &info); + assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload ); if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){ Pgno ovfl = get4byte(&pCell[info.iOverflow]); return ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno); @@ -1068,7 +1083,7 @@ static int defragmentPage(MemPage *pPage unsigned char *data; /* The page data */ unsigned char *temp; /* Temp area for cell content */ - assert( sqlite3pager_iswriteable(pPage->aData) ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( pPage->pBt!=0 ); assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); assert( pPage->nOverflow==0 ); @@ -1126,7 +1141,7 @@ static int allocateSpace(MemPage *pPage, unsigned char *data; data = pPage->aData; - assert( sqlite3pager_iswriteable(data) ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( pPage->pBt ); if( nByte<4 ) nByte = 4; if( pPage->nFreenOverflow>0 ) return 0; @@ -1183,7 +1198,7 @@ static void freeSpace(MemPage *pPage, in unsigned char *data = pPage->aData; assert( pPage->pBt!=0 ); - assert( sqlite3pager_iswriteable(data) ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( start>=pPage->hdrOffset+6+(pPage->leaf?0:4) ); assert( (start + size)<=pPage->pBt->usableSize ); if( size<4 ) size = 4; @@ -1292,7 +1307,7 @@ static int initPage( pBt = pPage->pBt; assert( pBt!=0 ); assert( pParent==0 || pParent->pBt==pBt ); - assert( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) ); + assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); assert( pPage->aData == &((unsigned char*)pPage)[-pBt->pageSize] ); if( pPage->pParent!=pParent && (pPage->pParent!=0 || pPage->isInit) ){ /* The parent page should never change unless the file is corrupt */ @@ -1301,7 +1316,7 @@ static int initPage( if( pPage->isInit ) return SQLITE_OK; if( pPage->pParent==0 && pParent!=0 ){ pPage->pParent = pParent; - sqlite3pager_ref(pParent->aData); + sqlite3PagerRef(pParent->pDbPage); } hdr = pPage->hdrOffset; data = pPage->aData; @@ -1359,9 +1374,9 @@ static void zeroPage(MemPage *pPage, int int hdr = pPage->hdrOffset; int first; - assert( sqlite3pager_pagenumber(data)==pPage->pgno ); + assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno ); assert( &data[pBt->pageSize] == (unsigned char*)pPage ); - assert( sqlite3pager_iswriteable(data) ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); memset(&data[hdr], 0, pBt->usableSize - hdr); data[hdr] = flags; first = hdr + 8 + 4*((flags&PTF_LEAF)==0); @@ -1382,18 +1397,23 @@ static void zeroPage(MemPage *pPage, int ** Get a page from the pager. Initialize the MemPage.pBt and ** MemPage.aData elements if needed. */ -static int getPage(BtShared *pBt, Pgno pgno, MemPage **ppPage){ +static int getPage(BtShared *pBt, Pgno pgno, MemPage **ppPage, int clrFlag){ int rc; - unsigned char *aData; MemPage *pPage; - rc = sqlite3pager_get(pBt->pPager, pgno, (void**)&aData); + DbPage *pDbPage; + + rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, clrFlag); if( rc ) return rc; - pPage = (MemPage*)&aData[pBt->pageSize]; - pPage->aData = aData; + pPage = (MemPage *)sqlite3PagerGetExtra(pDbPage); + pPage->aData = sqlite3PagerGetData(pDbPage); + pPage->pDbPage = pDbPage; pPage->pBt = pBt; pPage->pgno = pgno; pPage->hdrOffset = pPage->pgno==1 ? 100 : 0; *ppPage = pPage; + if( clrFlag ){ + sqlite3PagerDontRollback(pPage->pDbPage); + } return SQLITE_OK; } @@ -1412,7 +1432,7 @@ static int getAndInitPage( if( pgno==0 ){ return SQLITE_CORRUPT_BKPT; } - rc = getPage(pBt, pgno, ppPage); + rc = getPage(pBt, pgno, ppPage, 0); if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){ rc = initPage(*ppPage, pParent); } @@ -1428,7 +1448,7 @@ static void releasePage(MemPage *pPage){ assert( pPage->aData ); assert( pPage->pBt ); assert( &pPage->aData[pPage->pBt->pageSize]==(unsigned char*)pPage ); - sqlite3pager_unref(pPage->aData); + sqlite3PagerUnref(pPage->pDbPage); } } @@ -1437,10 +1457,10 @@ static void releasePage(MemPage *pPage){ ** reaches zero. We need to unref the pParent pointer when that ** happens. */ -static void pageDestructor(void *pData, int pageSize){ +static void pageDestructor(DbPage *pData, int pageSize){ MemPage *pPage; assert( (pageSize & 7)==0 ); - pPage = (MemPage*)&((char*)pData)[pageSize]; + pPage = (MemPage *)sqlite3PagerGetExtra(pData); if( pPage->pParent ){ MemPage *pParent = pPage->pParent; pPage->pParent = 0; @@ -1457,10 +1477,10 @@ static void pageDestructor(void *pData, ** This routine needs to reset the extra data section at the end of the ** page to agree with the restored data. */ -static void pageReinit(void *pData, int pageSize){ +static void pageReinit(DbPage *pData, int pageSize){ MemPage *pPage; assert( (pageSize & 7)==0 ); - pPage = (MemPage*)&((char*)pData)[pageSize]; + pPage = (MemPage *)sqlite3PagerGetExtra(pData); if( pPage->isInit ){ pPage->isInit = 0; initPage(pPage, pPage->pParent); @@ -1520,7 +1540,7 @@ int sqlite3BtreeOpen( } for(pBt=pTsdro->pBtree; pBt; pBt=pBt->pNext){ assert( pBt->nRef>0 ); - if( 0==strcmp(zFullPathname, sqlite3pager_filename(pBt->pPager)) ){ + if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager)) ){ p->pBt = pBt; *ppBtree = p; pBt->nRef++; @@ -1549,13 +1569,13 @@ int sqlite3BtreeOpen( sqliteFree(p); return SQLITE_NOMEM; } - rc = sqlite3pager_open(&pBt->pPager, zFilename, EXTRA_SIZE, flags); + rc = sqlite3PagerOpen(&pBt->pPager, zFilename, EXTRA_SIZE, flags); if( rc==SQLITE_OK ){ - rc = sqlite3pager_read_fileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); + rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); } if( rc!=SQLITE_OK ){ if( pBt->pPager ){ - sqlite3pager_close(pBt->pPager); + sqlite3PagerClose(pBt->pPager); } sqliteFree(pBt); sqliteFree(p); @@ -1564,11 +1584,11 @@ int sqlite3BtreeOpen( } p->pBt = pBt; - sqlite3pager_set_destructor(pBt->pPager, pageDestructor); - sqlite3pager_set_reiniter(pBt->pPager, pageReinit); + sqlite3PagerSetDestructor(pBt->pPager, pageDestructor); + sqlite3PagerSetReiniter(pBt->pPager, pageReinit); pBt->pCursor = 0; pBt->pPage1 = 0; - pBt->readOnly = sqlite3pager_isreadonly(pBt->pPager); + pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager); pBt->pageSize = get2byte(&zDbHeader[16]); if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){ @@ -1600,7 +1620,7 @@ int sqlite3BtreeOpen( } pBt->usableSize = pBt->pageSize - nReserve; assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */ - sqlite3pager_set_pagesize(pBt->pPager, pBt->pageSize); + sqlite3PagerSetPagesize(pBt->pPager, pBt->pageSize); #if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) /* Add the new btree to the linked list starting at ThreadData.pBtree. @@ -1677,7 +1697,7 @@ int sqlite3BtreeClose(Btree *p){ /* Close the pager and free the shared-btree structure */ assert( !pBt->pCursor ); - sqlite3pager_close(pBt->pPager); + sqlite3PagerClose(pBt->pPager); if( pBt->xFreeSchema && pBt->pSchema ){ pBt->xFreeSchema(pBt->pSchema); } @@ -1692,7 +1712,7 @@ int sqlite3BtreeSetBusyHandler(Btree *p, int sqlite3BtreeSetBusyHandler(Btree *p, BusyHandler *pHandler){ BtShared *pBt = p->pBt; pBt->pBusyHandler = pHandler; - sqlite3pager_set_busyhandler(pBt->pPager, pHandler); + sqlite3PagerSetBusyhandler(pBt->pPager, pHandler); return SQLITE_OK; } @@ -1713,7 +1733,7 @@ int sqlite3BtreeSetCacheSize(Btree *p, i */ int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){ BtShared *pBt = p->pBt; - sqlite3pager_set_cachesize(pBt->pPager, mxPage); + sqlite3PagerSetCachesize(pBt->pPager, mxPage); return SQLITE_OK; } @@ -1728,7 +1748,7 @@ int sqlite3BtreeSetSafetyLevel(Btree *p, #ifndef SQLITE_OMIT_PAGER_PRAGMAS int sqlite3BtreeSetSafetyLevel(Btree *p, int level, int fullSync){ BtShared *pBt = p->pBt; - sqlite3pager_set_safety_level(pBt->pPager, level, fullSync); + sqlite3PagerSetSafetyLevel(pBt->pPager, level, fullSync); return SQLITE_OK; } #endif @@ -1740,7 +1760,7 @@ int sqlite3BtreeSyncDisabled(Btree *p){ int sqlite3BtreeSyncDisabled(Btree *p){ BtShared *pBt = p->pBt; assert( pBt && pBt->pPager ); - return sqlite3pager_nosync(pBt->pPager); + return sqlite3PagerNosync(pBt->pPager); } #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) @@ -1771,7 +1791,7 @@ int sqlite3BtreeSetPageSize(Btree *p, in ((pageSize-1)&pageSize)==0 ){ assert( (pageSize & 7)==0 ); assert( !pBt->pPage1 && !pBt->pCursor ); - pBt->pageSize = sqlite3pager_set_pagesize(pBt->pPager, pageSize); + pBt->pageSize = sqlite3PagerSetPagesize(pBt->pPager, pageSize); } pBt->usableSize = pBt->pageSize - nReserve; return SQLITE_OK; @@ -1827,14 +1847,13 @@ int sqlite3BtreeGetAutoVacuum(Btree *p){ ** SQLITE_OK is returned on success. If the file is not a ** well-formed database file, then SQLITE_CORRUPT is returned. ** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM -** is returned if we run out of memory. SQLITE_PROTOCOL is returned -** if there is a locking protocol violation. +** is returned if we run out of memory. */ static int lockBtree(BtShared *pBt){ int rc, pageSize; MemPage *pPage1; if( pBt->pPage1 ) return SQLITE_OK; - rc = getPage(pBt, 1, &pPage1); + rc = getPage(pBt, 1, &pPage1, 0); if( rc!=SQLITE_OK ) return rc; @@ -1842,7 +1861,7 @@ static int lockBtree(BtShared *pBt){ ** a valid database file. */ rc = SQLITE_NOTADB; - if( sqlite3pager_pagecount(pBt->pPager)>0 ){ + if( sqlite3PagerPagecount(pBt->pPager)>0 ){ u8 *page1 = pPage1->aData; if( memcmp(page1, zMagicHeader, 16)!=0 ){ goto page1_init_failed; @@ -1851,7 +1870,7 @@ static int lockBtree(BtShared *pBt){ goto page1_init_failed; } pageSize = get2byte(&page1[16]); - if( ((pageSize-1)&pageSize)!=0 ){ + if( ((pageSize-1)&pageSize)!=0 || pageSize<512 ){ goto page1_init_failed; } assert( (pageSize & 7)==0 ); @@ -1931,7 +1950,7 @@ static void unlockBtreeIfUnused(BtShared */ static void unlockBtreeIfUnused(BtShared *pBt){ if( pBt->inTransaction==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){ - if( sqlite3pager_refcount(pBt->pPager)>=1 ){ + if( sqlite3PagerRefcount(pBt->pPager)>=1 ){ if( pBt->pPage1->aData==0 ){ MemPage *pPage = pBt->pPage1; pPage->aData = &((u8*)pPage)[-pBt->pageSize]; @@ -1953,11 +1972,11 @@ static int newDatabase(BtShared *pBt){ MemPage *pP1; unsigned char *data; int rc; - if( sqlite3pager_pagecount(pBt->pPager)>0 ) return SQLITE_OK; + if( sqlite3PagerPagecount(pBt->pPager)>0 ) return SQLITE_OK; pP1 = pBt->pPage1; assert( pP1!=0 ); data = pP1->aData; - rc = sqlite3pager_write(data); + rc = sqlite3PagerWrite(pP1->pDbPage); if( rc ) return rc; memcpy(data, zMagicHeader, sizeof(zMagicHeader)); assert( sizeof(zMagicHeader)==16 ); @@ -2047,7 +2066,7 @@ int sqlite3BtreeBeginTrans(Btree *p, int } if( rc==SQLITE_OK && wrflag ){ - rc = sqlite3pager_begin(pBt->pPage1->aData, wrflag>1); + rc = sqlite3PagerBegin(pBt->pPage1->pDbPage, wrflag>1); if( rc==SQLITE_OK ){ rc = newDatabase(pBt); } @@ -2203,7 +2222,7 @@ static int relocatePage( /* Move page iDbPage from it's current location to page number iFreePage */ TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n", iDbPage, iFreePage, iPtrPage, eType)); - rc = sqlite3pager_movepage(pPager, pDbPage->aData, iFreePage); + rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage); if( rc!=SQLITE_OK ){ return rc; } @@ -2237,11 +2256,11 @@ static int relocatePage( ** iPtrPage. */ if( eType!=PTRMAP_ROOTPAGE ){ - rc = getPage(pBt, iPtrPage, &pPtrPage); + rc = getPage(pBt, iPtrPage, &pPtrPage, 0); if( rc!=SQLITE_OK ){ return rc; } - rc = sqlite3pager_write(pPtrPage->aData); + rc = sqlite3PagerWrite(pPtrPage->pDbPage); if( rc!=SQLITE_OK ){ releasePage(pPtrPage); return rc; @@ -2256,13 +2275,18 @@ static int relocatePage( } /* Forward declaration required by autoVacuumCommit(). */ -static int allocatePage(BtShared *, MemPage **, Pgno *, Pgno, u8); +static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8); /* -** This routine is called prior to sqlite3pager_commit when a transaction +** This routine is called prior to sqlite3PagerCommit when a transaction ** is commited for an auto-vacuum database. +** +** If SQLITE_OK is returned, then *pnTrunc is set to the number of pages +** the database file should be truncated to during the commit process. +** i.e. the database has been reorganized so that only the first *pnTrunc +** pages are in use. */ -static int autoVacuumCommit(BtShared *pBt, Pgno *nTrunc){ +static int autoVacuumCommit(BtShared *pBt, Pgno *pnTrunc){ Pager *pPager = pBt->pPager; Pgno nFreeList; /* Number of pages remaining on the free-list. */ int nPtrMap; /* Number of pointer-map pages deallocated */ @@ -2278,11 +2302,11 @@ static int autoVacuumCommit(BtShared *pB MemPage *pFreeMemPage = 0; /* "" */ #ifndef NDEBUG - int nRef = sqlite3pager_refcount(pPager); + int nRef = sqlite3PagerRefcount(pPager); #endif assert( pBt->autoVacuum ); - if( PTRMAP_ISPAGE(pBt, sqlite3pager_pagecount(pPager)) ){ + if( PTRMAP_ISPAGE(pBt, sqlite3PagerPagecount(pPager)) ){ return SQLITE_CORRUPT_BKPT; } @@ -2291,7 +2315,7 @@ static int autoVacuumCommit(BtShared *pB */ nFreeList = get4byte(&pBt->pPage1->aData[36]); if( nFreeList==0 ){ - *nTrunc = 0; + *pnTrunc = 0; return SQLITE_OK; } @@ -2304,7 +2328,7 @@ static int autoVacuumCommit(BtShared *pB ** be required, less 1 if the pending-byte page was part of the database ** but is not after the truncation. **/ - origSize = sqlite3pager_pagecount(pPager); + origSize = sqlite3PagerPagecount(pPager); if( origSize==PENDING_BYTE_PAGE(pBt) ){ origSize--; } @@ -2341,19 +2365,19 @@ static int autoVacuumCommit(BtShared *pB if( eType==PTRMAP_FREEPAGE ){ continue; } - rc = getPage(pBt, iDbPage, &pDbMemPage); + rc = getPage(pBt, iDbPage, &pDbMemPage, 0); if( rc!=SQLITE_OK ) goto autovacuum_out; /* Find the next page in the free-list that is not already at the end ** of the file. A page can be pulled off the free list using the - ** allocatePage() routine. + ** allocateBtreePage() routine. */ do{ if( pFreeMemPage ){ releasePage(pFreeMemPage); pFreeMemPage = 0; } - rc = allocatePage(pBt, &pFreeMemPage, &iFreePage, 0, 0); + rc = allocateBtreePage(pBt, &pFreeMemPage, &iFreePage, 0, 0); if( rc!=SQLITE_OK ){ releasePage(pDbMemPage); goto autovacuum_out; @@ -2378,29 +2402,81 @@ static int autoVacuumCommit(BtShared *pB ** truncate the database file to finSize pages and consider the ** free-list empty. */ - rc = sqlite3pager_write(pBt->pPage1->aData); + rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); if( rc!=SQLITE_OK ) goto autovacuum_out; put4byte(&pBt->pPage1->aData[32], 0); put4byte(&pBt->pPage1->aData[36], 0); - *nTrunc = finSize; + *pnTrunc = finSize; assert( finSize!=PENDING_BYTE_PAGE(pBt) ); autovacuum_out: - assert( nRef==sqlite3pager_refcount(pPager) ); + assert( nRef==sqlite3PagerRefcount(pPager) ); if( rc!=SQLITE_OK ){ - sqlite3pager_rollback(pPager); + sqlite3PagerRollback(pPager); } return rc; } #endif /* +** This routine does the first phase of a two-phase commit. This routine +** causes a rollback journal to be created (if it does not already exist) +** and populated with enough information so that if a power loss occurs +** the database can be restored to its original state by playing back +** the journal. Then the contents of the journal are flushed out to +** the disk. After the journal is safely on oxide, the changes to the +** database are written into the database file and flushed to oxide. +** At the end of this call, the rollback journal still exists on the +** disk and we are still holding all locks, so the transaction has not +** committed. See sqlite3BtreeCommit() for the second phase of the +** commit process. +** +** This call is a no-op if no write-transaction is currently active on pBt. +** +** Otherwise, sync the database file for the btree pBt. zMaster points to +** the name of a master journal file that should be written into the +** individual journal file, or is NULL, indicating no master journal file +** (single database transaction). +** +** When this is called, the master journal should already have been +** created, populated with this journal pointer and synced to disk. +** +** Once this is routine has returned, the only thing required to commit +** the write-transaction for this database file is to delete the journal. +*/ +int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){ + int rc = SQLITE_OK; + if( p->inTrans==TRANS_WRITE ){ + BtShared *pBt = p->pBt; + Pgno nTrunc = 0; +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + rc = autoVacuumCommit(pBt, &nTrunc); + if( rc!=SQLITE_OK ){ + return rc; + } + } +#endif + rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, nTrunc); + } + return rc; +} + +/* ** Commit the transaction currently in progress. ** +** This routine implements the second phase of a 2-phase commit. The +** sqlite3BtreeSync() routine does the first phase and should be invoked +** prior to calling this routine. The sqlite3BtreeSync() routine did +** all the work of writing information out to disk and flushing the +** contents so that they are written onto the disk platter. All this +** routine has to do is delete or truncate the rollback journal +** (which causes the transaction to commit) and drop locks. +** ** This will release the write lock on the database file. If there ** are no active cursors, it also releases the read lock. */ -int sqlite3BtreeCommit(Btree *p){ +int sqlite3BtreeCommitPhaseTwo(Btree *p){ BtShared *pBt = p->pBt; btreeIntegrity(p); @@ -2412,7 +2488,7 @@ int sqlite3BtreeCommit(Btree *p){ int rc; assert( pBt->inTransaction==TRANS_WRITE ); assert( pBt->nTransaction>0 ); - rc = sqlite3pager_commit(pBt->pPager); + rc = sqlite3PagerCommitPhaseTwo(pBt->pPager); if( rc!=SQLITE_OK ){ return rc; } @@ -2443,6 +2519,18 @@ int sqlite3BtreeCommit(Btree *p){ return SQLITE_OK; } +/* +** Do both phases of a commit. +*/ +int sqlite3BtreeCommit(Btree *p){ + int rc; + rc = sqlite3BtreeCommitPhaseOne(p, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3BtreeCommitPhaseTwo(p); + } + return rc; +} + #ifndef NDEBUG /* ** Return the number of write-cursors open on this handle. This is for use @@ -2517,7 +2605,7 @@ int sqlite3BtreeRollback(Btree *p){ int rc2; assert( TRANS_WRITE==pBt->inTransaction ); - rc2 = sqlite3pager_rollback(pBt->pPager); + rc2 = sqlite3PagerRollback(pBt->pPager); if( rc2!=SQLITE_OK ){ rc = rc2; } @@ -2525,7 +2613,7 @@ int sqlite3BtreeRollback(Btree *p){ /* The rollback may have destroyed the pPage1->aData value. So ** call getPage() on page 1 again to make sure pPage1->aData is ** set correctly. */ - if( getPage(pBt, 1, &pPage1)==SQLITE_OK ){ + if( getPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){ releasePage(pPage1); } assert( countWriteCursors(pBt)==0 ); @@ -2570,7 +2658,7 @@ int sqlite3BtreeBeginStmt(Btree *p){ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } assert( pBt->inTransaction==TRANS_WRITE ); - rc = pBt->readOnly ? SQLITE_OK : sqlite3pager_stmt_begin(pBt->pPager); + rc = pBt->readOnly ? SQLITE_OK : sqlite3PagerStmtBegin(pBt->pPager); pBt->inStmt = 1; return rc; } @@ -2584,7 +2672,7 @@ int sqlite3BtreeCommitStmt(Btree *p){ int rc; BtShared *pBt = p->pBt; if( pBt->inStmt && !pBt->readOnly ){ - rc = sqlite3pager_stmt_commit(pBt->pPager); + rc = sqlite3PagerStmtCommit(pBt->pPager); }else{ rc = SQLITE_OK; } @@ -2605,7 +2693,7 @@ int sqlite3BtreeRollbackStmt(Btree *p){ BtShared *pBt = p->pBt; sqlite3MallocDisallow(); if( pBt->inStmt && !pBt->readOnly ){ - rc = sqlite3pager_stmt_rollback(pBt->pPager); + rc = sqlite3PagerStmtRollback(pBt->pPager); assert( countWriteCursors(pBt)==0 ); pBt->inStmt = 0; } @@ -2643,25 +2731,16 @@ static int dfltCompare( ** ** 1: The cursor must have been opened with wrFlag==1 ** -** 2: No other cursors may be open with wrFlag==0 on the same table +** 2: Other database connections that share the same pager cache +** but which are not in the READ_UNCOMMITTED state may not have +** cursors open with wrFlag==0 on the same table. Otherwise +** the changes made by this write cursor would be visible to +** the read cursors in the other database connection. ** ** 3: The database must be writable (not on read-only media) ** ** 4: There must be an active transaction. ** -** Condition 2 warrants further discussion. If any cursor is opened -** on a table with wrFlag==0, that prevents all other cursors from -** writing to that table. This is a kind of "read-lock". When a cursor -** is opened with wrFlag==0 it is guaranteed that the table will not -** change as long as the cursor is open. This allows the cursor to -** do a sequential scan of the table without having to worry about -** entries being inserted or deleted during the scan. Cursors should -** be opened with wrFlag==0 only if this read-lock property is needed. -** That is to say, cursors should be opened with wrFlag==0 only if they -** intend to use the sqlite3BtreeNext() system call. All other cursors -** should be opened with wrFlag==1 even if they never really intend -** to write. -** ** No checking is done to make sure that page iTable really is the ** root page of a b-tree. If it is not, then the cursor acquired ** will not work correctly. @@ -2706,7 +2785,7 @@ int sqlite3BtreeCursor( goto create_cursor_exception; } pCur->pgnoRoot = (Pgno)iTable; - if( iTable==1 && sqlite3pager_pagecount(pBt->pPager)==0 ){ + if( iTable==1 && sqlite3PagerPagecount(pBt->pPager)==0 ){ rc = SQLITE_EMPTY; goto create_cursor_exception; } @@ -2761,7 +2840,7 @@ int sqlite3BtreeCloseCursor(BtCursor *pC */ int sqlite3BtreeCloseCursor(BtCursor *pCur){ BtShared *pBt = pCur->pBtree->pBt; - restoreOrClearCursorPosition(pCur, 0); + clearCursorPosition(pCur); if( pCur->pPrev ){ pCur->pPrev->pNext = pCur->pNext; }else{ @@ -2785,7 +2864,7 @@ static void getTempCursor(BtCursor *pCur pTempCur->pNext = 0; pTempCur->pPrev = 0; if( pTempCur->pPage ){ - sqlite3pager_ref(pTempCur->pPage->aData); + sqlite3PagerRef(pTempCur->pPage->pDbPage); } } @@ -2795,7 +2874,7 @@ static void releaseTempCursor(BtCursor * */ static void releaseTempCursor(BtCursor *pCur){ if( pCur->pPage ){ - sqlite3pager_unref(pCur->pPage->aData); + sqlite3PagerUnref(pCur->pPage->pDbPage); } } @@ -2828,7 +2907,7 @@ int sqlite3BtreeKeySize(BtCursor *pCur, ** itself, not the number of bytes in the key. */ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ - int rc = restoreOrClearCursorPosition(pCur, 1); + int rc = restoreOrClearCursorPosition(pCur); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); if( pCur->eState==CURSOR_INVALID ){ @@ -2849,7 +2928,7 @@ int sqlite3BtreeDataSize(BtCursor *pCur, ** the database is empty) then *pSize is set to 0. */ int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ - int rc = restoreOrClearCursorPosition(pCur, 1); + int rc = restoreOrClearCursorPosition(pCur); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); if( pCur->eState==CURSOR_INVALID ){ @@ -2925,10 +3004,12 @@ static int getPayload( if( amt>0 ){ nextPage = get4byte(&aPayload[pCur->info.nLocal]); while( amt>0 && nextPage ){ - rc = sqlite3pager_get(pBt->pPager, nextPage, (void**)&aPayload); + DbPage *pDbPage; + rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage); if( rc!=0 ){ return rc; } + aPayload = sqlite3PagerGetData(pDbPage); nextPage = get4byte(aPayload); if( offseteState==CURSOR_VALID ); assert( pCur->pPage!=0 ); @@ -2986,7 +3067,7 @@ int sqlite3BtreeData(BtCursor *pCur, u32 ** the available payload. */ int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ - int rc = restoreOrClearCursorPosition(pCur, 1); + int rc = restoreOrClearCursorPosition(pCur); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_VALID ); assert( pCur->pPage!=0 ); @@ -3139,7 +3220,7 @@ static void moveToParent(BtCursor *pCur) pParent = pPage->pParent; assert( pParent!=0 ); idxParent = pPage->idxParent; - sqlite3pager_ref(pParent->aData); + sqlite3PagerRef(pParent->pDbPage); releasePage(pPage); pCur->pPage = pParent; pCur->info.nSize = 0; @@ -3155,7 +3236,9 @@ static int moveToRoot(BtCursor *pCur){ int rc = SQLITE_OK; BtShared *pBt = pCur->pBtree->pBt; - restoreOrClearCursorPosition(pCur, 0); + if( pCur->eState==CURSOR_REQUIRESEEK ){ + clearCursorPosition(pCur); + } pRoot = pCur->pPage; if( pRoot && pRoot->pgno==pCur->pgnoRoot ){ assert( pRoot->isInit ); @@ -3297,14 +3380,18 @@ int sqlite3BtreeLast(BtCursor *pCur, int ** *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 sqlite3BtreeMoveto( + BtCursor *pCur, /* The cursor to be moved */ + const void *pKey, /* The key content for indices. Not used by tables */ + i64 nKey, /* Size of pKey. Or the key for tables */ + int biasRight, /* If true, bias the search to the high end */ + int *pRes /* Search result flag */ +){ 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 ); @@ -3320,16 +3407,17 @@ int sqlite3BtreeMoveto(BtCursor *pCur, c if( !pPage->intKey && pKey==0 ){ return SQLITE_CORRUPT_BKPT; } - while( lwr<=upr ){ + if( biasRight ){ + pCur->idx = upr; + }else{ + pCur->idx = (upr+lwr)/2; + } + if( lwr<=upr ) for(;;){ void *pCellKey; i64 nCellKey; - pCur->idx = (lwr+upr)/2; pCur->info.nSize = 0; if( pPage->intKey ){ u8 *pCell; - if( tryRightmost ){ - pCur->idx = upr; - } pCell = findCell(pPage, pCur->idx) + pPage->childPtrSize; if( pPage->hasData ){ u32 dummy; @@ -3340,7 +3428,6 @@ int sqlite3BtreeMoveto(BtCursor *pCur, c c = -1; }else if( nCellKey>nKey ){ c = +1; - tryRightmost = 0; }else{ c = 0; } @@ -3374,6 +3461,10 @@ int sqlite3BtreeMoveto(BtCursor *pCur, c }else{ upr = pCur->idx-1; } + if( lwr>upr ){ + break; + } + pCur->idx = (lwr+upr)/2; } assert( lwr==upr+1 ); assert( pPage->isInit ); @@ -3425,10 +3516,18 @@ int sqlite3BtreeNext(BtCursor *pCur, int MemPage *pPage; #ifndef SQLITE_OMIT_SHARED_CACHE - rc = restoreOrClearCursorPosition(pCur, 1); + rc = restoreOrClearCursorPosition(pCur); if( rc!=SQLITE_OK ){ return rc; } +#endif + assert( pRes!=0 ); + pPage = pCur->pPage; + if( CURSOR_INVALID==pCur->eState ){ + *pRes = 1; + return SQLITE_OK; + } +#ifndef SQLITE_OMIT_SHARED_CACHE if( pCur->skip>0 ){ pCur->skip = 0; *pRes = 0; @@ -3437,12 +3536,6 @@ int sqlite3BtreeNext(BtCursor *pCur, int pCur->skip = 0; #endif - assert( pRes!=0 ); - pPage = pCur->pPage; - if( CURSOR_INVALID==pCur->eState ){ - *pRes = 1; - return SQLITE_OK; - } assert( pPage->isInit ); assert( pCur->idxnCell ); @@ -3493,10 +3586,16 @@ int sqlite3BtreePrevious(BtCursor *pCur, MemPage *pPage; #ifndef SQLITE_OMIT_SHARED_CACHE - rc = restoreOrClearCursorPosition(pCur, 1); + rc = restoreOrClearCursorPosition(pCur); if( rc!=SQLITE_OK ){ return rc; } +#endif + if( CURSOR_INVALID==pCur->eState ){ + *pRes = 1; + return SQLITE_OK; + } +#ifndef SQLITE_OMIT_SHARED_CACHE if( pCur->skip<0 ){ pCur->skip = 0; *pRes = 0; @@ -3505,11 +3604,6 @@ int sqlite3BtreePrevious(BtCursor *pCur, pCur->skip = 0; #endif - if( CURSOR_INVALID==pCur->eState ){ - *pRes = 1; - return SQLITE_OK; - } - pPage = pCur->pPage; assert( pPage->isInit ); assert( pCur->idx>=0 ); @@ -3543,14 +3637,14 @@ int sqlite3BtreePrevious(BtCursor *pCur, /* ** Allocate a new page from the database file. ** -** The new page is marked as dirty. (In other words, sqlite3pager_write() +** The new page is marked as dirty. (In other words, sqlite3PagerWrite() ** has already been called on the new page.) The new page has also ** been referenced and the calling routine is responsible for calling -** sqlite3pager_unref() on the new page when it is done. +** sqlite3PagerUnref() on the new page when it is done. ** ** SQLITE_OK is returned on success. Any other return value indicates ** an error. *ppPage and *pPgno are undefined in the event of an error. -** Do not invoke sqlite3pager_unref() on *ppPage if an error is returned. +** Do not invoke sqlite3PagerUnref() on *ppPage if an error is returned. ** ** If the "nearby" parameter is not 0, then a (feeble) effort is made to ** locate a page close to the page number "nearby". This can be used in an @@ -3561,7 +3655,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, ** anywhere on the free-list, then it is guarenteed to be returned. This ** is only used by auto-vacuum databases when allocating a new table. */ -static int allocatePage( +static int allocateBtreePage( BtShared *pBt, MemPage **ppPage, Pgno *pPgno, @@ -3603,7 +3697,7 @@ static int allocatePage( /* Decrement the free-list count by 1. Set iTrunk to the index of the ** first free-list trunk page. iPrevTrunk is initially 1. */ - rc = sqlite3pager_write(pPage1->aData); + rc = sqlite3PagerWrite(pPage1->pDbPage); if( rc ) return rc; put4byte(&pPage1->aData[36], n-1); @@ -3618,7 +3712,7 @@ static int allocatePage( }else{ iTrunk = get4byte(&pPage1->aData[32]); } - rc = getPage(pBt, iTrunk, &pTrunk); + rc = getPage(pBt, iTrunk, &pTrunk, 0); if( rc ){ pTrunk = 0; goto end_allocate_page; @@ -3630,7 +3724,7 @@ static int allocatePage( ** So extract the trunk page itself and use it as the newly ** allocated page */ assert( pPrevTrunk==0 ); - rc = sqlite3pager_write(pTrunk->aData); + rc = sqlite3PagerWrite(pTrunk->pDbPage); if( rc ){ goto end_allocate_page; } @@ -3651,7 +3745,7 @@ static int allocatePage( assert( *pPgno==iTrunk ); *ppPage = pTrunk; searchList = 0; - rc = sqlite3pager_write(pTrunk->aData); + rc = sqlite3PagerWrite(pTrunk->pDbPage); if( rc ){ goto end_allocate_page; } @@ -3668,11 +3762,11 @@ static int allocatePage( */ MemPage *pNewTrunk; Pgno iNewTrunk = get4byte(&pTrunk->aData[8]); - rc = getPage(pBt, iNewTrunk, &pNewTrunk); + rc = getPage(pBt, iNewTrunk, &pNewTrunk, 0); if( rc!=SQLITE_OK ){ goto end_allocate_page; } - rc = sqlite3pager_write(pNewTrunk->aData); + rc = sqlite3PagerWrite(pNewTrunk->pDbPage); if( rc!=SQLITE_OK ){ releasePage(pNewTrunk); goto end_allocate_page; @@ -3684,7 +3778,7 @@ static int allocatePage( if( !pPrevTrunk ){ put4byte(&pPage1->aData[32], iNewTrunk); }else{ - rc = sqlite3pager_write(pPrevTrunk->aData); + rc = sqlite3PagerWrite(pPrevTrunk->pDbPage); if( rc ){ goto end_allocate_page; } @@ -3699,7 +3793,7 @@ static int allocatePage( int closest; Pgno iPage; unsigned char *aData = pTrunk->aData; - rc = sqlite3pager_write(aData); + rc = sqlite3PagerWrite(pTrunk->pDbPage); if( rc ){ goto end_allocate_page; } @@ -3723,7 +3817,7 @@ static int allocatePage( iPage = get4byte(&aData[8+closest*4]); if( !searchList || iPage==nearby ){ *pPgno = iPage; - if( *pPgno>sqlite3pager_pagecount(pBt->pPager) ){ + if( *pPgno>sqlite3PagerPagecount(pBt->pPager) ){ /* Free page off the end of the file */ return SQLITE_CORRUPT_BKPT; } @@ -3734,10 +3828,9 @@ static int allocatePage( memcpy(&aData[8+closest*4], &aData[4+k*4], 4); } put4byte(&aData[4], k-1); - rc = getPage(pBt, *pPgno, ppPage); + rc = getPage(pBt, *pPgno, ppPage, 1); if( rc==SQLITE_OK ){ - sqlite3pager_dont_rollback((*ppPage)->aData); - rc = sqlite3pager_write((*ppPage)->aData); + rc = sqlite3PagerWrite((*ppPage)->pDbPage); if( rc!=SQLITE_OK ){ releasePage(*ppPage); } @@ -3751,7 +3844,7 @@ static int allocatePage( }else{ /* There are no pages on the freelist, so create a new page at the ** end of the file */ - *pPgno = sqlite3pager_pagecount(pBt->pPager) + 1; + *pPgno = sqlite3PagerPagecount(pBt->pPager) + 1; #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, *pPgno) ){ @@ -3766,9 +3859,9 @@ static int allocatePage( #endif assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); - rc = getPage(pBt, *pPgno, ppPage); + rc = getPage(pBt, *pPgno, ppPage, 0); if( rc ) return rc; - rc = sqlite3pager_write((*ppPage)->aData); + rc = sqlite3PagerWrite((*ppPage)->pDbPage); if( rc!=SQLITE_OK ){ releasePage(*ppPage); } @@ -3786,7 +3879,7 @@ end_allocate_page: /* ** Add a page of the database file to the freelist. ** -** sqlite3pager_unref() is NOT called for pPage. +** sqlite3PagerUnref() is NOT called for pPage. */ static int freePage(MemPage *pPage){ BtShared *pBt = pPage->pBt; @@ -3800,7 +3893,7 @@ static int freePage(MemPage *pPage){ pPage->pParent = 0; /* Increment the free page count on pPage1 */ - rc = sqlite3pager_write(pPage1->aData); + rc = sqlite3PagerWrite(pPage1->pDbPage); if( rc ) return rc; n = get4byte(&pPage1->aData[36]); put4byte(&pPage1->aData[36], n+1); @@ -3809,7 +3902,7 @@ static int freePage(MemPage *pPage){ /* If the SQLITE_SECURE_DELETE compile-time option is enabled, then ** always fully overwrite deleted information with zeros. */ - rc = sqlite3pager_write(pPage->aData); + rc = sqlite3PagerWrite(pPage->pDbPage); if( rc ) return rc; memset(pPage->aData, 0, pPage->pBt->pageSize); #endif @@ -3826,7 +3919,7 @@ static int freePage(MemPage *pPage){ if( n==0 ){ /* This is the first free page */ - rc = sqlite3pager_write(pPage->aData); + rc = sqlite3PagerWrite(pPage->pDbPage); if( rc ) return rc; memset(pPage->aData, 0, 8); put4byte(&pPage1->aData[32], pPage->pgno); @@ -3835,13 +3928,13 @@ static int freePage(MemPage *pPage){ /* Other free pages already exist. Retrive the first trunk page ** of the freelist and find out how many leaves it has. */ MemPage *pTrunk; - rc = getPage(pBt, get4byte(&pPage1->aData[32]), &pTrunk); + rc = getPage(pBt, get4byte(&pPage1->aData[32]), &pTrunk, 0); if( rc ) return rc; k = get4byte(&pTrunk->aData[4]); if( k>=pBt->usableSize/4 - 8 ){ /* The trunk is full. Turn the page being freed into a new ** trunk page with no leaves. */ - rc = sqlite3pager_write(pPage->aData); + rc = sqlite3PagerWrite(pPage->pDbPage); if( rc ) return rc; put4byte(pPage->aData, pTrunk->pgno); put4byte(&pPage->aData[4], 0); @@ -3850,13 +3943,14 @@ static int freePage(MemPage *pPage){ pPage->pgno, pTrunk->pgno)); }else{ /* Add the newly freed page as a leaf on the current trunk */ - rc = sqlite3pager_write(pTrunk->aData); - if( rc ) return rc; - put4byte(&pTrunk->aData[4], k+1); - put4byte(&pTrunk->aData[8+k*4], pPage->pgno); + rc = sqlite3PagerWrite(pTrunk->pDbPage); + if( rc==SQLITE_OK ){ + put4byte(&pTrunk->aData[4], k+1); + put4byte(&pTrunk->aData[8+k*4], pPage->pgno); #ifndef SQLITE_SECURE_DELETE - sqlite3pager_dont_write(pBt->pPager, pPage->pgno); + sqlite3PagerDontWrite(pBt->pPager, pPage->pgno); #endif + } TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno)); } releasePage(pTrunk); @@ -3872,22 +3966,29 @@ static int clearCell(MemPage *pPage, uns CellInfo info; Pgno ovflPgno; int rc; + int nOvfl; + int ovflPageSize; parseCellPtr(pPage, pCell, &info); if( info.iOverflow==0 ){ return SQLITE_OK; /* No overflow pages. Return without doing anything */ } ovflPgno = get4byte(&pCell[info.iOverflow]); - while( ovflPgno!=0 ){ + ovflPageSize = pBt->usableSize - 4; + nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize; + assert( ovflPgno==0 || nOvfl>0 ); + while( nOvfl-- ){ MemPage *pOvfl; - if( ovflPgno>sqlite3pager_pagecount(pBt->pPager) ){ + if( ovflPgno==0 || ovflPgno>sqlite3PagerPagecount(pBt->pPager) ){ return SQLITE_CORRUPT_BKPT; } - rc = getPage(pBt, ovflPgno, &pOvfl); + rc = getPage(pBt, ovflPgno, &pOvfl, 0); if( rc ) return rc; - ovflPgno = get4byte(pOvfl->aData); + if( nOvfl ){ + ovflPgno = get4byte(pOvfl->aData); + } rc = freePage(pOvfl); - sqlite3pager_unref(pOvfl->aData); + sqlite3PagerUnref(pOvfl->pDbPage); if( rc ) return rc; } return SQLITE_OK; @@ -3962,7 +4063,7 @@ static int fillInCell( #ifndef SQLITE_OMIT_AUTOVACUUM Pgno pgnoPtrmap = pgnoOvfl; /* Overflow page pointer-map entry page */ #endif - rc = allocatePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl, 0); + rc = allocateBtreePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl, 0); #ifndef SQLITE_OMIT_AUTOVACUUM /* If the database supports auto-vacuum, and the second or subsequent ** overflow page is being allocated, add an entry to the pointer-map @@ -3975,7 +4076,6 @@ static int fillInCell( #endif if( rc ){ releasePage(pToRelease); - /* clearCell(pPage, pCell); */ return rc; } put4byte(pPrior, pgnoOvfl); @@ -4012,24 +4112,24 @@ static int reparentPage(BtShared *pBt, P */ static int reparentPage(BtShared *pBt, Pgno pgno, MemPage *pNewParent, int idx){ MemPage *pThis; - unsigned char *aData; + DbPage *pDbPage; assert( pNewParent!=0 ); if( pgno==0 ) return SQLITE_OK; assert( pBt->pPager!=0 ); - aData = sqlite3pager_lookup(pBt->pPager, pgno); - if( aData ){ - pThis = (MemPage*)&aData[pBt->pageSize]; - assert( pThis->aData==aData ); + pDbPage = sqlite3PagerLookup(pBt->pPager, pgno); + if( pDbPage ){ + pThis = (MemPage *)sqlite3PagerGetExtra(pDbPage); if( pThis->isInit ){ + assert( pThis->aData==(sqlite3PagerGetData(pDbPage)) ); if( pThis->pParent!=pNewParent ){ - if( pThis->pParent ) sqlite3pager_unref(pThis->pParent->aData); + if( pThis->pParent ) sqlite3PagerUnref(pThis->pParent->pDbPage); pThis->pParent = pNewParent; - sqlite3pager_ref(pNewParent->aData); + sqlite3PagerRef(pNewParent->pDbPage); } pThis->idxParent = idx; } - sqlite3pager_unref(aData); + sqlite3PagerUnref(pDbPage); } #ifndef SQLITE_OMIT_AUTOVACUUM @@ -4090,7 +4190,7 @@ static void dropCell(MemPage *pPage, int assert( idx>=0 && idxnCell ); assert( sz==cellSize(pPage, idx) ); - assert( sqlite3pager_iswriteable(pPage->aData) ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); data = pPage->aData; ptr = &data[pPage->cellOffset + 2*idx]; pc = get2byte(ptr); @@ -4143,7 +4243,7 @@ static int insertCell( assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); assert( sz==cellSizePtr(pPage, pCell) ); - assert( sqlite3pager_iswriteable(pPage->aData) ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); if( pPage->nOverflow || sz+2>pPage->nFree ){ if( pTemp ){ memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip); @@ -4187,6 +4287,7 @@ static int insertCell( */ CellInfo info; parseCellPtr(pPage, pCell, &info); + assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload ); if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){ Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]); int rc = ptrmapPut(pPage->pBt, pgnoOvfl, PTRMAP_OVERFLOW1, pPage->pgno); @@ -4294,7 +4395,7 @@ static int balance_quick(MemPage *pPage, /* Allocate a new page. Insert the overflow cell from pPage ** into it. Then remove the overflow cell from pPage. */ - rc = allocatePage(pBt, &pNew, &pgnoNew, 0, 0); + rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0); if( rc!=SQLITE_OK ){ return rc; } @@ -4306,7 +4407,7 @@ static int balance_quick(MemPage *pPage, /* Set the parent of the newly allocated page to pParent. */ pNew->pParent = pParent; - sqlite3pager_ref(pParent->aData); + sqlite3PagerRef(pParent->pDbPage); /* pPage is currently the right-child of pParent. Change this ** so that the right-child is the new page allocated above and @@ -4431,11 +4532,11 @@ static int balance_nonroot(MemPage *pPag ** Find the parent page. */ assert( pPage->isInit ); - assert( sqlite3pager_iswriteable(pPage->aData) ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); pBt = pPage->pBt; pParent = pPage->pParent; assert( pParent ); - if( SQLITE_OK!=(rc = sqlite3pager_write(pParent->aData)) ){ + if( SQLITE_OK!=(rc = sqlite3PagerWrite(pParent->pDbPage)) ){ return rc; } TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno)); @@ -4473,7 +4574,7 @@ static int balance_nonroot(MemPage *pPag if( pParent->idxShift ){ Pgno pgno; pgno = pPage->pgno; - assert( pgno==sqlite3pager_pagenumber(pPage->aData) ); + assert( pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); for(idx=0; idxnCell; idx++){ if( get4byte(findCell(pParent, idx))==pgno ){ break; @@ -4490,7 +4591,7 @@ static int balance_nonroot(MemPage *pPag ** directly to balance_cleanup at any moment. */ nOld = nNew = 0; - sqlite3pager_ref(pParent->aData); + sqlite3PagerRef(pParent->pDbPage); /* ** Find sibling pages to pPage and the cells in pParent that divide @@ -4734,15 +4835,16 @@ static int balance_nonroot(MemPage *pPag pNew = apNew[i] = apOld[i]; pgnoNew[i] = pgnoOld[i]; apOld[i] = 0; - rc = sqlite3pager_write(pNew->aData); + rc = sqlite3PagerWrite(pNew->pDbPage); + nNew++; if( rc ) goto balance_cleanup; }else{ assert( i>0 ); - rc = allocatePage(pBt, &pNew, &pgnoNew[i], pgnoNew[i-1], 0); + rc = allocateBtreePage(pBt, &pNew, &pgnoNew[i], pgnoNew[i-1], 0); if( rc ) goto balance_cleanup; apNew[i] = pNew; + nNew++; } - nNew++; zeroPage(pNew, pageFlags); } @@ -4977,8 +5079,8 @@ static int balance_shallower(MemPage *pP */ pgnoChild = get4byte(&pPage->aData[pPage->hdrOffset+8]); assert( pgnoChild>0 ); - assert( pgnoChild<=sqlite3pager_pagecount(pPage->pBt->pPager) ); - rc = getPage(pPage->pBt, pgnoChild, &pChild); + assert( pgnoChild<=sqlite3PagerPagecount(pPage->pBt->pPager) ); + rc = getPage(pPage->pBt, pgnoChild, &pChild, 0); if( rc ) goto end_shallow_balance; if( pPage->pgno==1 ){ rc = initPage(pChild, pPage); @@ -5059,9 +5161,9 @@ static int balance_deeper(MemPage *pPage assert( pPage->pParent==0 ); assert( pPage->nOverflow>0 ); pBt = pPage->pBt; - rc = allocatePage(pBt, &pChild, &pgnoChild, pPage->pgno, 0); + rc = allocateBtreePage(pBt, &pChild, &pgnoChild, pPage->pgno, 0); if( rc ) return rc; - assert( sqlite3pager_iswriteable(pChild->aData) ); + assert( sqlite3PagerIswriteable(pChild->pDbPage) ); usableSize = pBt->usableSize; data = pPage->aData; hdr = pPage->hdrOffset; @@ -5172,7 +5274,8 @@ int sqlite3BtreeInsert( int sqlite3BtreeInsert( BtCursor *pCur, /* Insert data into the table of this cursor */ const void *pKey, i64 nKey, /* The key of the new record */ - const void *pData, int nData /* The data of the new record */ + const void *pData, int nData, /* The data of the new record */ + int appendBias /* True if this is likely an append */ ){ int rc; int loc; @@ -5195,10 +5298,10 @@ int sqlite3BtreeInsert( } /* Save the positions of any other cursors open on this table */ - restoreOrClearCursorPosition(pCur, 0); + clearCursorPosition(pCur); if( SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || - SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, &loc)) + SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc)) ){ return rc; } @@ -5210,7 +5313,7 @@ int sqlite3BtreeInsert( pCur->pgnoRoot, nKey, nData, pPage->pgno, loc==0 ? "overwrite" : "new entry")); assert( pPage->isInit ); - rc = sqlite3pager_write(pPage->aData); + rc = sqlite3PagerWrite(pPage->pDbPage); if( rc ) return rc; newCell = sqliteMallocRaw( MX_CELL_SIZE(pBt) ); if( newCell==0 ) return SQLITE_NOMEM; @@ -5278,13 +5381,13 @@ int sqlite3BtreeDelete(BtCursor *pCur){ /* Restore the current cursor position (a no-op if the cursor is not in ** CURSOR_REQUIRESEEK state) and save the positions of any other cursors - ** open on the same table. Then call sqlite3pager_write() on the page + ** open on the same table. Then call sqlite3PagerWrite() on the page ** that the entry will be deleted from. */ if( - (rc = restoreOrClearCursorPosition(pCur, 1))!=0 || + (rc = restoreOrClearCursorPosition(pCur))!=0 || (rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur))!=0 || - (rc = sqlite3pager_write(pPage->aData))!=0 + (rc = sqlite3PagerWrite(pPage->pDbPage))!=0 ){ return rc; } @@ -5318,13 +5421,8 @@ int sqlite3BtreeDelete(BtCursor *pCur){ assert( !pPage->leafData ); getTempCursor(pCur, &leafCur); rc = sqlite3BtreeNext(&leafCur, ¬Used); - if( rc!=SQLITE_OK ){ - if( rc!=SQLITE_NOMEM ){ - rc = SQLITE_CORRUPT_BKPT; - } - } if( rc==SQLITE_OK ){ - rc = sqlite3pager_write(leafCur.pPage->aData); + rc = sqlite3PagerWrite(leafCur.pPage->pDbPage); } if( rc==SQLITE_OK ){ TRACE(("DELETE: table=%d delete internal from %d replace from leaf %d\n", @@ -5395,7 +5493,7 @@ int sqlite3BtreeCreateTable(Btree *p, in } #ifdef SQLITE_OMIT_AUTOVACUUM - rc = allocatePage(pBt, &pRoot, &pgnoRoot, 1, 0); + rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0); if( rc ) return rc; #else if( pBt->autoVacuum ){ @@ -5423,17 +5521,25 @@ int sqlite3BtreeCreateTable(Btree *p, in ** be moved to the allocated page (unless the allocated page happens ** to reside at pgnoRoot). */ - rc = allocatePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, 1); + rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, 1); if( rc!=SQLITE_OK ){ return rc; } if( pgnoMove!=pgnoRoot ){ + /* pgnoRoot is the page that will be used for the root-page of + ** the new table (assuming an error did not occur). But we were + ** allocated pgnoMove. If required (i.e. if it was not allocated + ** by extending the file), the current page at position pgnoMove + ** is already journaled. + */ u8 eType; Pgno iPtrPage; releasePage(pPageMove); - rc = getPage(pBt, pgnoRoot, &pRoot); + + /* Move the page currently at pgnoRoot to pgnoMove. */ + rc = getPage(pBt, pgnoRoot, &pRoot, 0); if( rc!=SQLITE_OK ){ return rc; } @@ -5444,21 +5550,23 @@ int sqlite3BtreeCreateTable(Btree *p, in } assert( eType!=PTRMAP_ROOTPAGE ); assert( eType!=PTRMAP_FREEPAGE ); - rc = sqlite3pager_write(pRoot->aData); + rc = sqlite3PagerWrite(pRoot->pDbPage); if( rc!=SQLITE_OK ){ releasePage(pRoot); return rc; } rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove); releasePage(pRoot); + + /* Obtain the page at pgnoRoot */ if( rc!=SQLITE_OK ){ return rc; } - rc = getPage(pBt, pgnoRoot, &pRoot); + rc = getPage(pBt, pgnoRoot, &pRoot, 0); if( rc!=SQLITE_OK ){ return rc; } - rc = sqlite3pager_write(pRoot->aData); + rc = sqlite3PagerWrite(pRoot->pDbPage); if( rc!=SQLITE_OK ){ releasePage(pRoot); return rc; @@ -5480,13 +5588,13 @@ int sqlite3BtreeCreateTable(Btree *p, in } }else{ - rc = allocatePage(pBt, &pRoot, &pgnoRoot, 1, 0); + rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0); if( rc ) return rc; } #endif - assert( sqlite3pager_iswriteable(pRoot->aData) ); + assert( sqlite3PagerIswriteable(pRoot->pDbPage) ); zeroPage(pRoot, flags | PTF_LEAF); - sqlite3pager_unref(pRoot->aData); + sqlite3PagerUnref(pRoot->pDbPage); *piTable = (int)pgnoRoot; return SQLITE_OK; } @@ -5506,14 +5614,12 @@ static int clearDatabasePage( unsigned char *pCell; int i; - if( pgno>sqlite3pager_pagecount(pBt->pPager) ){ + if( pgno>sqlite3PagerPagecount(pBt->pPager) ){ return SQLITE_CORRUPT_BKPT; } rc = getAndInitPage(pBt, pgno, &pPage, pParent); if( rc ) goto cleardatabasepage_out; - rc = sqlite3pager_write(pPage->aData); - if( rc ) goto cleardatabasepage_out; for(i=0; inCell; i++){ pCell = findCell(pPage, i); if( !pPage->leaf ){ @@ -5529,7 +5635,7 @@ static int clearDatabasePage( } if( freePageFlag ){ rc = freePage(pPage); - }else{ + }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){ zeroPage(pPage, pPage->aData[0] | PTF_LEAF); } @@ -5605,7 +5711,7 @@ int sqlite3BtreeDropTable(Btree *p, int return SQLITE_LOCKED; } - rc = getPage(pBt, (Pgno)iTable, &pPage); + rc = getPage(pBt, (Pgno)iTable, &pPage, 0); if( rc ) return rc; rc = sqlite3BtreeClearTable(p, iTable); if( rc ){ @@ -5644,7 +5750,7 @@ int sqlite3BtreeDropTable(Btree *p, int */ MemPage *pMove; releasePage(pPage); - rc = getPage(pBt, maxRootPgno, &pMove); + rc = getPage(pBt, maxRootPgno, &pMove, 0); if( rc!=SQLITE_OK ){ return rc; } @@ -5653,7 +5759,7 @@ int sqlite3BtreeDropTable(Btree *p, int if( rc!=SQLITE_OK ){ return rc; } - rc = getPage(pBt, maxRootPgno, &pMove); + rc = getPage(pBt, maxRootPgno, &pMove, 0); if( rc!=SQLITE_OK ){ return rc; } @@ -5705,6 +5811,7 @@ int sqlite3BtreeGetMeta(Btree *p, int id ** free pages is not visible. So Cookie[0] is the same as Meta[1]. */ int sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){ + DbPage *pDbPage; int rc; unsigned char *pP1; BtShared *pBt = p->pBt; @@ -5720,10 +5827,11 @@ int sqlite3BtreeGetMeta(Btree *p, int id } assert( idx>=0 && idx<=15 ); - rc = sqlite3pager_get(pBt->pPager, 1, (void**)&pP1); + rc = sqlite3PagerGet(pBt->pPager, 1, &pDbPage); if( rc ) return rc; + pP1 = (unsigned char *)sqlite3PagerGetData(pDbPage); *pMeta = get4byte(&pP1[36 + idx*4]); - sqlite3pager_unref(pP1); + sqlite3PagerUnref(pDbPage); /* If autovacuumed is disabled in this build but we are trying to ** access an autovacuumed database, then make the database readonly. @@ -5751,7 +5859,7 @@ int sqlite3BtreeUpdateMeta(Btree *p, int } assert( pBt->pPage1!=0 ); pP1 = pBt->pPage1->aData; - rc = sqlite3pager_write(pP1); + rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); if( rc ) return rc; put4byte(&pP1[36 + idx*4], iMeta); return SQLITE_OK; @@ -5787,7 +5895,7 @@ static int btreePageDump(BtShared *pBt, char range[20]; unsigned char payload[20]; - rc = getPage(pBt, (Pgno)pgno, &pPage); + rc = getPage(pBt, (Pgno)pgno, &pPage, 0); isInit = pPage->isInit; if( pPage->isInit==0 ){ initPage(pPage, pParent); @@ -5866,7 +5974,7 @@ static int btreePageDump(BtShared *pBt, btreePageDump(pBt, get4byte(&data[hdr+8]), 1, pPage); } pPage->isInit = isInit; - sqlite3pager_unref(data); + sqlite3PagerUnref(pPage->pDbPage); fflush(stdout); return SQLITE_OK; } @@ -5899,7 +6007,7 @@ int sqlite3BtreeCursorInfo(BtCursor *pCu MemPage *pPage = pCur->pPage; BtCursor tmpCur; - int rc = restoreOrClearCursorPosition(pCur, 1); + int rc = restoreOrClearCursorPosition(pCur); if( rc!=SQLITE_OK ){ return rc; } @@ -5910,7 +6018,7 @@ int sqlite3BtreeCursorInfo(BtCursor *pCu moveToParent(&tmpCur); } pPage = tmpCur.pPage; - aResult[0] = sqlite3pager_pagenumber(pPage->aData); + aResult[0] = sqlite3PagerPagenumber(pPage->pDbPage); assert( aResult[0]==pPage->pgno ); aResult[1] = tmpCur.idx; aResult[2] = pPage->nCell; @@ -6071,7 +6179,8 @@ static void checkList( int expected = N; int iFirst = iPage; while( N-- > 0 && pCheck->mxErr ){ - unsigned char *pOvfl; + DbPage *pOvflPage; + unsigned char *pOvflData; if( iPage<1 ){ checkAppendMsg(pCheck, zContext, "%d of %d pages missing from overflow list starting at %d", @@ -6079,12 +6188,13 @@ static void checkList( break; } if( checkRef(pCheck, iPage, zContext) ) break; - if( sqlite3pager_get(pCheck->pPager, (Pgno)iPage, (void**)&pOvfl) ){ + if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage) ){ checkAppendMsg(pCheck, zContext, "failed to get page %d", iPage); break; } + pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage); if( isFreeList ){ - int n = get4byte(&pOvfl[4]); + int n = get4byte(&pOvflData[4]); #ifndef SQLITE_OMIT_AUTOVACUUM if( pCheck->pBt->autoVacuum ){ checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0, zContext); @@ -6096,7 +6206,7 @@ static void checkList( N--; }else{ for(i=0; ipBt->autoVacuum ){ checkPtrmap(pCheck, iFreePage, PTRMAP_FREEPAGE, 0, zContext); @@ -6114,13 +6224,13 @@ static void checkList( ** the following page matches iPage. */ if( pCheck->pBt->autoVacuum && N>0 ){ - i = get4byte(pOvfl); + i = get4byte(pOvflData); checkPtrmap(pCheck, i, PTRMAP_OVERFLOW2, iPage, zContext); } } #endif - iPage = get4byte(pOvfl); - sqlite3pager_unref(pOvfl); + iPage = get4byte(pOvflData); + sqlite3PagerUnref(pOvflPage); } } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ @@ -6168,7 +6278,7 @@ static int checkTreePage( usableSize = pBt->usableSize; if( iPage==0 ) return 0; if( checkRef(pCheck, iPage, zParentContext) ) return 0; - if( (rc = getPage(pBt, (Pgno)iPage, &pPage))!=0 ){ + if( (rc = getPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){ checkAppendMsg(pCheck, zContext, "unable to get the page. error code=%d", rc); return 0; @@ -6194,6 +6304,7 @@ static int checkTreePage( parseCellPtr(pPage, pCell, &info); sz = info.nData; if( !pPage->intKey ) sz += info.nKey; + assert( sz==info.nPayload ); if( sz>info.nLocal ){ int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4); Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]); @@ -6309,13 +6420,13 @@ char *sqlite3BtreeIntegrityCheck( IntegrityCk sCheck; BtShared *pBt = p->pBt; - nRef = sqlite3pager_refcount(pBt->pPager); + nRef = sqlite3PagerRefcount(pBt->pPager); if( lockBtreeWithRetry(p)!=SQLITE_OK ){ return sqliteStrDup("Unable to acquire a read lock on the database"); } sCheck.pBt = pBt; sCheck.pPager = pBt->pPager; - sCheck.nPage = sqlite3pager_pagecount(sCheck.pPager); + sCheck.nPage = sqlite3PagerPagecount(sCheck.pPager); sCheck.mxErr = mxErr; sCheck.nErr = 0; *pnErr = 0; @@ -6379,10 +6490,10 @@ char *sqlite3BtreeIntegrityCheck( /* Make sure this analysis did not leave any unref() pages */ unlockBtreeIfUnused(pBt); - if( nRef != sqlite3pager_refcount(pBt->pPager) ){ + if( nRef != sqlite3PagerRefcount(pBt->pPager) ){ checkAppendMsg(&sCheck, 0, "Outstanding page count goes from %d to %d during this analysis", - nRef, sqlite3pager_refcount(pBt->pPager) + nRef, sqlite3PagerRefcount(pBt->pPager) ); } @@ -6399,7 +6510,7 @@ const char *sqlite3BtreeGetFilename(Btre */ const char *sqlite3BtreeGetFilename(Btree *p){ assert( p->pBt->pPager!=0 ); - return sqlite3pager_filename(p->pBt->pPager); + return sqlite3PagerFilename(p->pBt->pPager); } /* @@ -6407,7 +6518,7 @@ const char *sqlite3BtreeGetDirname(Btree */ const char *sqlite3BtreeGetDirname(Btree *p){ assert( p->pBt->pPager!=0 ); - return sqlite3pager_dirname(p->pBt->pPager); + return sqlite3PagerDirname(p->pBt->pPager); } /* @@ -6417,7 +6528,7 @@ const char *sqlite3BtreeGetJournalname(B */ const char *sqlite3BtreeGetJournalname(Btree *p){ assert( p->pBt->pPager!=0 ); - return sqlite3pager_journalname(p->pBt->pPager); + return sqlite3PagerJournalname(p->pBt->pPager); } #ifndef SQLITE_OMIT_VACUUM @@ -6439,28 +6550,28 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btr return SQLITE_ERROR; } if( pBtTo->pCursor ) return SQLITE_BUSY; - nToPage = sqlite3pager_pagecount(pBtTo->pPager); - nPage = sqlite3pager_pagecount(pBtFrom->pPager); + nToPage = sqlite3PagerPagecount(pBtTo->pPager); + nPage = sqlite3PagerPagecount(pBtFrom->pPager); iSkip = PENDING_BYTE_PAGE(pBtTo); for(i=1; rc==SQLITE_OK && i<=nPage; i++){ - void *pPage; + DbPage *pDbPage; if( i==iSkip ) continue; - rc = sqlite3pager_get(pBtFrom->pPager, i, &pPage); + rc = sqlite3PagerGet(pBtFrom->pPager, i, &pDbPage); if( rc ) break; - rc = sqlite3pager_overwrite(pBtTo->pPager, i, pPage); - sqlite3pager_unref(pPage); + rc = sqlite3PagerOverwrite(pBtTo->pPager, i, sqlite3PagerGetData(pDbPage)); + sqlite3PagerUnref(pDbPage); } for(i=nPage+1; rc==SQLITE_OK && i<=nToPage; i++){ - void *pPage; + DbPage *pDbPage; if( i==iSkip ) continue; - rc = sqlite3pager_get(pBtTo->pPager, i, &pPage); + rc = sqlite3PagerGet(pBtTo->pPager, i, &pDbPage); if( rc ) break; - rc = sqlite3pager_write(pPage); - sqlite3pager_unref(pPage); - sqlite3pager_dont_write(pBtTo->pPager, i); + rc = sqlite3PagerWrite(pDbPage); + sqlite3PagerUnref(pDbPage); + sqlite3PagerDontWrite(pBtTo->pPager, i); } if( !rc && nPagepPager, nPage); + rc = sqlite3PagerTruncate(pBtTo->pPager, nPage); } if( rc ){ sqlite3BtreeRollback(pTo); @@ -6491,38 +6602,6 @@ int sqlite3BtreeIsInReadTrans(Btree *p){ } /* -** This call is a no-op if no write-transaction is currently active on pBt. -** -** Otherwise, sync the database file for the btree pBt. zMaster points to -** the name of a master journal file that should be written into the -** individual journal file, or is NULL, indicating no master journal file -** (single database transaction). -** -** When this is called, the master journal should already have been -** created, populated with this journal pointer and synced to disk. -** -** Once this is routine has returned, the only thing required to commit -** the write-transaction for this database file is to delete the journal. -*/ -int sqlite3BtreeSync(Btree *p, const char *zMaster){ - int rc = SQLITE_OK; - if( p->inTrans==TRANS_WRITE ){ - BtShared *pBt = p->pBt; - Pgno nTrunc = 0; -#ifndef SQLITE_OMIT_AUTOVACUUM - if( pBt->autoVacuum ){ - rc = autoVacuumCommit(pBt, &nTrunc); - if( rc!=SQLITE_OK ){ - return rc; - } - } -#endif - rc = sqlite3pager_sync(pBt->pPager, zMaster, nTrunc); - } - return rc; -} - -/* ** This function returns a pointer to a blob of memory associated with ** a single shared-btree. The memory is used by client code for it's own ** purposes (for example, to store a high-level schema associated with @@ -6592,7 +6671,7 @@ int sqlite3_shared_cache_report( BtShared *pBt; Tcl_Obj *pRet = Tcl_NewObj(); for(pBt=pTd->pBtree; pBt; pBt=pBt->pNext){ - const char *zFile = sqlite3pager_filename(pBt->pPager); + const char *zFile = sqlite3PagerFilename(pBt->pPager); Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(zFile, -1)); Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(pBt->nRef)); } ============================================================ --- sqlite/btree.h 066444ee25bd6e6accb997bfd2cf5ace14dbcd00 +++ sqlite/btree.h 9b2cc0d113c0bc2d37d244b9a394d56948c9acbf @@ -13,7 +13,7 @@ ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** -** @(#) $Id: btree.h,v 1.72 2007/01/27 02:24:55 drh Exp $ +** @(#) $Id: btree.h,v 1.74 2007/03/30 14:06:34 drh Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ @@ -67,6 +67,8 @@ int sqlite3BtreeBeginTrans(Btree*,int); int sqlite3BtreeSetAutoVacuum(Btree *, int); int sqlite3BtreeGetAutoVacuum(Btree *); int sqlite3BtreeBeginTrans(Btree*,int); +int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); +int sqlite3BtreeCommitPhaseTwo(Btree*); int sqlite3BtreeCommit(Btree*); int sqlite3BtreeRollback(Btree*); int sqlite3BtreeBeginStmt(Btree*); @@ -76,7 +78,6 @@ int sqlite3BtreeIsInReadTrans(Btree*); int sqlite3BtreeIsInTrans(Btree*); int sqlite3BtreeIsInStmt(Btree*); int sqlite3BtreeIsInReadTrans(Btree*); -int sqlite3BtreeSync(Btree*, const char *zMaster); void *sqlite3BtreeSchema(Btree *, int, void(*)(void *)); int sqlite3BtreeSchemaLocked(Btree *); int sqlite3BtreeLockTable(Btree *, int, u8); @@ -114,10 +115,10 @@ int sqlite3BtreeCloseCursor(BtCursor*); ); int sqlite3BtreeCloseCursor(BtCursor*); -int sqlite3BtreeMoveto(BtCursor*, const void *pKey, i64 nKey, int *pRes); +int sqlite3BtreeMoveto(BtCursor*,const void *pKey,i64 nKey,int bias,int *pRes); int sqlite3BtreeDelete(BtCursor*); int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, - const void *pData, int nData); + const void *pData, int nData, int bias); int sqlite3BtreeFirst(BtCursor*, int *pRes); int sqlite3BtreeLast(BtCursor*, int *pRes); int sqlite3BtreeNext(BtCursor*, int *pRes); ============================================================ --- sqlite/build.c 6bd68dc730b01c1727738f8e4b5c730eb0ddb421 +++ sqlite/build.c 7c2efa468f0c404ef5aa648d43c383318390937f @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.413 2007/02/02 12:44:37 drh Exp $ +** $Id: build.c,v 1.419 2007/04/05 11:25:58 drh Exp $ */ #include "sqliteInt.h" #include @@ -82,7 +82,7 @@ void sqlite3TableLock( } nBytes = sizeof(TableLock) * (pParse->nTableLock+1); - sqliteReallocOrFree((void **)&pParse->aTableLock, nBytes); + pParse->aTableLock = sqliteReallocOrFree(pParse->aTableLock, nBytes); if( pParse->aTableLock ){ p = &pParse->aTableLock[pParse->nTableLock++]; p->iDb = iDb; @@ -443,17 +443,6 @@ void sqlite3ResetInternalSchema(sqlite3 } /* -** This routine is called whenever a rollback occurs. If there were -** schema changes during the transaction, then we have to reset the -** internal hash tables and reload them from disk. -*/ -void sqlite3RollbackInternalChanges(sqlite3 *db){ - if( db->flags & SQLITE_InternChanges ){ - sqlite3ResetInternalSchema(db, 0); - } -} - -/* ** This routine is called when a commit occurs. */ void sqlite3CommitInternalChanges(sqlite3 *db){ @@ -887,7 +876,7 @@ void sqlite3StartTable( sqlite3VdbeAddOp(v, OP_NewRowid, 0, 0); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3VdbeAddOp(v, OP_Null, 0, 0); - sqlite3VdbeAddOp(v, OP_Insert, 0, 0); + sqlite3VdbeAddOp(v, OP_Insert, 0, OPFLAG_APPEND); sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); } @@ -2357,17 +2346,17 @@ void sqlite3CreateIndex( } if( !db->init.busy ){ if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index; - if( sqlite3FindIndex(db, zName, pDb->zName)!=0 ){ - if( !ifNotExist ){ - sqlite3ErrorMsg(pParse, "index %s already exists", zName); - } - goto exit_create_index; - } if( sqlite3FindTable(db, zName, 0)!=0 ){ sqlite3ErrorMsg(pParse, "there is already a table named %s", zName); goto exit_create_index; } } + if( sqlite3FindIndex(db, zName, pDb->zName)!=0 ){ + if( !ifNotExist ){ + sqlite3ErrorMsg(pParse, "index %s already exists", zName); + } + goto exit_create_index; + } }else{ char zBuf[30]; int n; @@ -2783,44 +2772,46 @@ exit_drop_index: } /* -** ppArray points into a structure where there is an array pointer -** followed by two integers. The first integer is the -** number of elements in the structure array. The second integer -** is the number of allocated slots in the array. +** pArray is a pointer to an array of objects. Each object in the +** array is szEntry bytes in size. This routine allocates a new +** object on the end of the array. ** -** In other words, the structure looks something like this: +** *pnEntry is the number of entries already in use. *pnAlloc is +** the previously allocated size of the array. initSize is the +** suggested initial array size allocation. ** -** struct Example1 { -** struct subElem *aEntry; -** int nEntry; -** int nAlloc; -** } +** The index of the new entry is returned in *pIdx. ** -** The pnEntry parameter points to the equivalent of Example1.nEntry. -** -** This routine allocates a new slot in the array, zeros it out, -** and returns its index. If malloc fails a negative number is returned. -** -** szEntry is the sizeof of a single array entry. initSize is the -** number of array entries allocated on the initial allocation. +** This routine returns a pointer to the array of objects. This +** might be the same as the pArray parameter or it might be a different +** pointer if the array was resized. */ -int sqlite3ArrayAllocate(void **ppArray, int szEntry, int initSize){ - char *p; - int *an = (int*)&ppArray[1]; - if( an[0]>=an[1] ){ +void *sqlite3ArrayAllocate( + void *pArray, /* Array of objects. Might be reallocated */ + int szEntry, /* Size of each object in the array */ + int initSize, /* Suggested initial allocation, in elements */ + int *pnEntry, /* Number of objects currently in use */ + int *pnAlloc, /* Current size of the allocation, in elements */ + int *pIdx /* Write the index of a new slot here */ +){ + char *z; + if( *pnEntry >= *pnAlloc ){ void *pNew; int newSize; - newSize = an[1]*2 + initSize; - pNew = sqliteRealloc(*ppArray, newSize*szEntry); + newSize = (*pnAlloc)*2 + initSize; + pNew = sqliteRealloc(pArray, newSize*szEntry); if( pNew==0 ){ - return -1; + *pIdx = -1; + return pArray; } - an[1] = newSize; - *ppArray = pNew; + *pnAlloc = newSize; + pArray = pNew; } - p = *ppArray; - memset(&p[an[0]*szEntry], 0, szEntry); - return an[0]++; + z = (char*)pArray; + memset(&z[*pnEntry * szEntry], 0, szEntry); + *pIdx = *pnEntry; + ++*pnEntry; + return pArray; } /* @@ -2836,7 +2827,14 @@ IdList *sqlite3IdListAppend(IdList *pLis if( pList==0 ) return 0; pList->nAlloc = 0; } - i = sqlite3ArrayAllocate((void**)&pList->a, sizeof(pList->a[0]), 5); + pList->a = sqlite3ArrayAllocate( + pList->a, + sizeof(pList->a[0]), + 5, + &pList->nId, + &pList->nAlloc, + &i + ); if( i<0 ){ sqlite3IdListDelete(pList); return 0; ============================================================ --- sqlite/date.c 393c73fc027597e008dcd81454544659e978b05c +++ sqlite/date.c 74b76691bddf58b634f6bf4a77c8c58234268c6e @@ -16,7 +16,7 @@ ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: date.c,v 1.60 2007/01/08 16:19:07 drh Exp $ +** $Id: date.c,v 1.62 2007/04/06 02:32:34 drh Exp $ ** ** NOTES: ** @@ -577,7 +577,7 @@ static int parseModifier(const char *zMo case '8': case '9': { n = getValue(z, &r); - if( n<=0 ) break; + assert( n>=1 ); if( z[n]==':' ){ /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the ** specified number of hours, minutes, seconds, and fractional seconds @@ -827,7 +827,7 @@ static void strftimeFunc( case 'f': { double s = x.s; if( s>59.999 ) s = 59.999; - sqlite3_snprintf(7, &z[j],"%02.3f", s); + sqlite3_snprintf(7, &z[j],"%06.3f", s); j += strlen(&z[j]); break; } ============================================================ --- sqlite/expr.c dfd25ae8f8f2ebf3d8dea605a5cea959946aabb7 +++ sqlite/expr.c a8740c24af3f39f2d502be1a1c640c96435eaac0 @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.275 2007/02/07 13:09:46 drh Exp $ +** $Id: expr.c,v 1.283 2007/03/27 13:36:37 drh Exp $ */ #include "sqliteInt.h" #include @@ -131,7 +131,7 @@ static char comparisonAffinity(Expr *pEx aff = sqlite3CompareAffinity(pExpr->pSelect->pEList->a[0].pExpr, aff); } else if( !aff ){ - aff = SQLITE_AFF_NUMERIC; + aff = SQLITE_AFF_NONE; } return aff; } @@ -404,7 +404,7 @@ void sqlite3ExprAssignVarNumber(Parse *p pExpr->iTable = ++pParse->nVar; if( pParse->nVarExpr>=pParse->nVarExprAlloc-1 ){ pParse->nVarExprAlloc += pParse->nVarExprAlloc + 10; - sqliteReallocOrFree((void**)&pParse->apVarExpr, + pParse->apVarExpr = sqliteReallocOrFree(pParse->apVarExpr, pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0]) ); } if( !sqlite3MallocFailed() ){ @@ -1518,7 +1518,32 @@ static void codeInteger(Vdbe *v, const c } } + /* +** Generate code that will extract the iColumn-th column from +** table pTab and push that column value on the stack. There +** is an open cursor to pTab in iTable. If iColumn<0 then +** code is generated that extracts the rowid. +*/ +void sqlite3ExprCodeGetColumn(Vdbe *v, Table *pTab, int iColumn, int iTable){ + if( iColumn<0 ){ + int op = (pTab && IsVirtual(pTab)) ? OP_VRowid : OP_Rowid; + sqlite3VdbeAddOp(v, op, iTable, 0); + }else if( pTab==0 ){ + sqlite3VdbeAddOp(v, OP_Column, iTable, iColumn); + }else{ + int op = IsVirtual(pTab) ? OP_VColumn : OP_Column; + sqlite3VdbeAddOp(v, op, iTable, iColumn); + sqlite3ColumnDefault(v, pTab, iColumn); +#ifndef SQLITE_OMIT_FLOATING_POINT + if( pTab->aCol[iColumn].affinity==SQLITE_AFF_REAL ){ + sqlite3VdbeAddOp(v, OP_RealAffinity, 0, 0); + } +#endif + } +} + +/* ** Generate code into the current Vdbe to evaluate the given ** expression and leave the result on the top of stack. ** @@ -1558,21 +1583,8 @@ void sqlite3ExprCode(Parse *pParse, Expr /* This only happens when coding check constraints */ assert( pParse->ckOffset>0 ); sqlite3VdbeAddOp(v, OP_Dup, pParse->ckOffset-pExpr->iColumn-1, 1); - }else if( pExpr->iColumn>=0 ){ - Table *pTab = pExpr->pTab; - int iCol = pExpr->iColumn; - int op = (pTab && IsVirtual(pTab)) ? OP_VColumn : OP_Column; - sqlite3VdbeAddOp(v, op, pExpr->iTable, iCol); - sqlite3ColumnDefault(v, pTab, iCol); -#ifndef SQLITE_OMIT_FLOATING_POINT - if( pTab && pTab->aCol[iCol].affinity==SQLITE_AFF_REAL ){ - sqlite3VdbeAddOp(v, OP_RealAffinity, 0, 0); - } -#endif }else{ - Table *pTab = pExpr->pTab; - int op = (pTab && IsVirtual(pTab)) ? OP_VRowid : OP_Rowid; - sqlite3VdbeAddOp(v, op, pExpr->iTable, 0); + sqlite3ExprCodeGetColumn(v, pExpr->pTab, pExpr->iColumn, pExpr->iTable); } break; } @@ -2175,6 +2187,16 @@ void sqlite3ExprIfFalse(Parse *pParse, E /* ** Do a deep comparison of two expression trees. Return TRUE (non-zero) ** if they are identical and return FALSE if they differ in any way. +** +** Sometimes this routine will return FALSE even if the two expressions +** really are equivalent. If we cannot prove that the expressions are +** identical, we return FALSE just to be safe. So if this routine +** returns false, then you do not really know for certain if the two +** expressions are the same. But if you get a TRUE return, then you +** can be sure the expressions are the same. In the places where +** this routine is used, it does not hurt to get an extra FALSE - that +** just might result in some slightly slower code. But returning +** an incorrect TRUE could lead to a malfunction. */ int sqlite3ExprCompare(Expr *pA, Expr *pB){ int i; @@ -2198,7 +2220,7 @@ int sqlite3ExprCompare(Expr *pA, Expr *p } if( pA->pSelect || pB->pSelect ) return 0; if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0; - if( pA->token.z ){ + if( pA->op!=TK_COLUMN && pA->token.z ){ if( pB->token.z==0 ) return 0; if( pB->token.n!=pA->token.n ) return 0; if( sqlite3StrNICmp((char*)pA->token.z,(char*)pB->token.z,pB->token.n)!=0 ){ @@ -2215,10 +2237,14 @@ static int addAggInfoColumn(AggInfo *pIn */ static int addAggInfoColumn(AggInfo *pInfo){ int i; - i = sqlite3ArrayAllocate((void**)&pInfo->aCol, sizeof(pInfo->aCol[0]), 3); - if( i<0 ){ - return -1; - } + pInfo->aCol = sqlite3ArrayAllocate( + pInfo->aCol, + sizeof(pInfo->aCol[0]), + 3, + &pInfo->nColumn, + &pInfo->nColumnAlloc, + &i + ); return i; } @@ -2228,10 +2254,14 @@ static int addAggInfoFunc(AggInfo *pInfo */ static int addAggInfoFunc(AggInfo *pInfo){ int i; - i = sqlite3ArrayAllocate((void**)&pInfo->aFunc, sizeof(pInfo->aFunc[0]), 2); - if( i<0 ){ - return -1; - } + pInfo->aFunc = sqlite3ArrayAllocate( + pInfo->aFunc, + sizeof(pInfo->aFunc[0]), + 3, + &pInfo->nFunc, + &pInfo->nFuncAlloc, + &i + ); return i; } @@ -2266,15 +2296,17 @@ static int analyzeAggregate(void *pArg, ** Make an entry for the column in pAggInfo->aCol[] if there ** is not an entry there already. */ + int k; pCol = pAggInfo->aCol; - for(i=0; inColumn; i++, pCol++){ + for(k=0; knColumn; k++, pCol++){ if( pCol->iTable==pExpr->iTable && pCol->iColumn==pExpr->iColumn ){ break; } } - if( i>=pAggInfo->nColumn && (i = addAggInfoColumn(pAggInfo))>=0 ){ - pCol = &pAggInfo->aCol[i]; + if( k>=pAggInfo->nColumn && (k = addAggInfoColumn(pAggInfo))>=0 ){ + pCol = &pAggInfo->aCol[k]; + pCol->pTab = pExpr->pTab; pCol->iTable = pExpr->iTable; pCol->iColumn = pExpr->iColumn; pCol->iMem = pParse->nMem++; @@ -2305,7 +2337,7 @@ static int analyzeAggregate(void *pArg, */ pExpr->pAggInfo = pAggInfo; pExpr->op = TK_AGG_COLUMN; - pExpr->iAgg = i; + pExpr->iAgg = k; break; } /* endif pExpr->iTable==pItem->iCursor */ } /* end loop over pSrcList */ ============================================================ --- sqlite/func.c b7e1e220a6795ecae7649815145ea5f8644dfa5f +++ sqlite/func.c 94372fe3cf26b81d4dcdc15f98ff240c37c8c708 @@ -16,7 +16,7 @@ ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: func.c,v 1.136 2007/01/29 17:58:28 drh Exp $ +** $Id: func.c,v 1.138 2007/03/17 17:52:42 drh Exp $ */ #include "sqliteInt.h" #include @@ -669,6 +669,114 @@ static void hexFunc( sqlite3_result_text(context, zHex, n*2, sqlite3_free); } +/* +** The replace() function. Three arguments are all strings: call +** them A, B, and C. The result is also a string which is derived +** from A by replacing every occurance of B with C. The match +** must be exact. Collating sequences are not used. +*/ +static void replaceFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const unsigned char *zStr; /* The input string A */ + const unsigned char *zPattern; /* The pattern string B */ + const unsigned char *zRep; /* The replacement string C */ + unsigned char *zOut; /* The output */ + int nStr; /* Size of zStr */ + int nPattern; /* Size of zPattern */ + int nRep; /* Size of zRep */ + int nOut; /* Maximum size of zOut */ + int loopLimit; /* Last zStr[] that might match zPattern[] */ + int i, j; /* Loop counters */ + + assert( argc==3 ); + if( sqlite3_value_type(argv[0])==SQLITE_NULL || + sqlite3_value_type(argv[1])==SQLITE_NULL || + sqlite3_value_type(argv[2])==SQLITE_NULL ){ + return; + } + zStr = sqlite3_value_text(argv[0]); + nStr = sqlite3_value_bytes(argv[0]); + zPattern = sqlite3_value_text(argv[1]); + nPattern = sqlite3_value_bytes(argv[1]); + zRep = sqlite3_value_text(argv[2]); + nRep = sqlite3_value_bytes(argv[2]); + if( nPattern>=nRep ){ + nOut = nStr; + }else{ + nOut = (nStr/nPattern + 1)*nRep; + } + zOut = sqlite3_malloc(nOut+1); + if( zOut==0 ) return; + loopLimit = nStr - nPattern; + for(i=j=0; i<=loopLimit; i++){ + if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){ + zOut[j++] = zStr[i]; + }else{ + memcpy(&zOut[j], zRep, nRep); + j += nRep; + i += nPattern-1; + } + } + memcpy(&zOut[j], &zStr[i], nStr-i); + j += nStr - i; + assert( j<=nOut ); + zOut[j] = 0; + sqlite3_result_text(context, (char*)zOut, j, sqlite3_free); +} + +/* +** Implementation of the TRIM(), LTRIM(), and RTRIM() functions. +** The userdata is 0x1 for left trim, 0x2 for right trim, 0x3 for both. +*/ +static void trimFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const unsigned char *zIn; /* Input string */ + const unsigned char *zCharSet; /* Set of characters to trim */ + int nIn; /* Number of bytes in input */ + int flags; + int i; + unsigned char cFirst, cNext; + if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ + return; + } + zIn = sqlite3_value_text(argv[0]); + nIn = sqlite3_value_bytes(argv[0]); + if( argc==1 ){ + static const unsigned char zSpace[] = " "; + zCharSet = zSpace; + }else if( sqlite3_value_type(argv[1])==SQLITE_NULL ){ + return; + }else{ + zCharSet = sqlite3_value_text(argv[1]); + } + cFirst = zCharSet[0]; + if( cFirst ){ + flags = (int)sqlite3_user_data(context); + if( flags & 1 ){ + for(; nIn>0; nIn--, zIn++){ + if( cFirst==zIn[0] ) continue; + for(i=1; zCharSet[i] && zCharSet[i]!=zIn[0]; i++){} + if( zCharSet[i]==0 ) break; + } + } + if( flags & 2 ){ + for(; nIn>0; nIn--){ + cNext = zIn[nIn-1]; + if( cFirst==cNext ) continue; + for(i=1; zCharSet[i] && zCharSet[i]!=cNext; i++){} + if( zCharSet[i]==0 ) break; + } + } + } + sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT); +} + #ifdef SQLITE_SOUNDEX /* ** Compute the soundex encoding of a word. @@ -1020,7 +1128,7 @@ static void minmaxStep(sqlite3_context * ** Therefore the next statement sets variable 'max' to 1 for the max() ** aggregate, or 0 for min(). */ - max = ((sqlite3_user_data(context)==(void *)-1)?1:0); + max = sqlite3_user_data(context)!=0; cmp = sqlite3MemCompare(pBest, pArg, pColl); if( (max && cmp<0) || (!max && cmp>0) ){ sqlite3VdbeMemCopy(pBest, pArg); @@ -1050,15 +1158,15 @@ void sqlite3RegisterBuiltinFunctions(sql static const struct { char *zName; signed char nArg; - u8 argType; /* 0: none. 1: db 2: (-1) */ + u8 argType; /* ff: db 1: 0, 2: 1, 3: 2,... N: N-1. */ u8 eTextRep; /* 1: UTF-16. 0: UTF-8 */ u8 needCollSeq; void (*xFunc)(sqlite3_context*,int,sqlite3_value **); } aFuncs[] = { { "min", -1, 0, SQLITE_UTF8, 1, minmaxFunc }, { "min", 0, 0, SQLITE_UTF8, 1, 0 }, - { "max", -1, 2, SQLITE_UTF8, 1, minmaxFunc }, - { "max", 0, 2, SQLITE_UTF8, 1, 0 }, + { "max", -1, 1, SQLITE_UTF8, 1, minmaxFunc }, + { "max", 0, 1, SQLITE_UTF8, 1, 0 }, { "typeof", 1, 0, SQLITE_UTF8, 0, typeofFunc }, { "length", 1, 0, SQLITE_UTF8, 0, lengthFunc }, { "substr", 3, 0, SQLITE_UTF8, 0, substrFunc }, @@ -1080,22 +1188,29 @@ void sqlite3RegisterBuiltinFunctions(sql { "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc }, { "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc}, { "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc }, - { "last_insert_rowid", 0, 1, SQLITE_UTF8, 0, last_insert_rowid }, - { "changes", 0, 1, SQLITE_UTF8, 0, changes }, - { "total_changes", 0, 1, SQLITE_UTF8, 0, total_changes }, + { "last_insert_rowid", 0, 0xff, SQLITE_UTF8, 0, last_insert_rowid }, + { "changes", 0, 0xff, SQLITE_UTF8, 0, changes }, + { "total_changes", 0, 0xff, SQLITE_UTF8, 0, total_changes }, + { "replace", 3, 0, SQLITE_UTF8, 0, replaceFunc }, + { "ltrim", 1, 1, SQLITE_UTF8, 0, trimFunc }, + { "ltrim", 2, 1, SQLITE_UTF8, 0, trimFunc }, + { "rtrim", 1, 2, SQLITE_UTF8, 0, trimFunc }, + { "rtrim", 2, 2, SQLITE_UTF8, 0, trimFunc }, + { "trim", 1, 3, SQLITE_UTF8, 0, trimFunc }, + { "trim", 2, 3, SQLITE_UTF8, 0, trimFunc }, #ifdef SQLITE_SOUNDEX - { "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc}, + { "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc}, #endif #ifndef SQLITE_OMIT_LOAD_EXTENSION - { "load_extension", 1, 1, SQLITE_UTF8, 0, loadExt }, - { "load_extension", 2, 1, SQLITE_UTF8, 0, loadExt }, + { "load_extension", 1, 0xff, SQLITE_UTF8, 0, loadExt }, + { "load_extension", 2, 0xff, SQLITE_UTF8, 0, loadExt }, #endif #ifdef SQLITE_TEST - { "randstr", 2, 0, SQLITE_UTF8, 0, randStr }, - { "test_destructor", 1, 1, SQLITE_UTF8, 0, test_destructor}, - { "test_destructor_count", 0, 0, SQLITE_UTF8, 0, test_destructor_count}, - { "test_auxdata", -1, 0, SQLITE_UTF8, 0, test_auxdata}, - { "test_error", 1, 0, SQLITE_UTF8, 0, test_error}, + { "randstr", 2, 0, SQLITE_UTF8, 0, randStr }, + { "test_destructor", 1, 0xff, SQLITE_UTF8, 0, test_destructor}, + { "test_destructor_count", 0, 0, SQLITE_UTF8, 0, test_destructor_count}, + { "test_auxdata", -1, 0, SQLITE_UTF8, 0, test_auxdata}, + { "test_error", 1, 0, SQLITE_UTF8, 0, test_error}, #endif }; static const struct { @@ -1107,7 +1222,7 @@ void sqlite3RegisterBuiltinFunctions(sql void (*xFinalize)(sqlite3_context*); } aAggs[] = { { "min", 1, 0, 1, minmaxStep, minMaxFinalize }, - { "max", 1, 2, 1, minmaxStep, minMaxFinalize }, + { "max", 1, 1, 1, minmaxStep, minMaxFinalize }, { "sum", 1, 0, 0, sumStep, sumFinalize }, { "total", 1, 0, 0, sumStep, totalFinalize }, { "avg", 1, 0, 0, sumStep, avgFinalize }, @@ -1117,10 +1232,12 @@ void sqlite3RegisterBuiltinFunctions(sql int i; for(i=0; i @@ -291,7 +291,7 @@ static void removeElementGivenHash( if( pEntry->count<=0 ){ pEntry->chain = 0; } - if( pH->copyKey && elem->pKey ){ + if( pH->copyKey ){ pH->xFree(elem->pKey); } pH->xFree( elem ); @@ -378,6 +378,9 @@ void *sqlite3HashInsert(Hash *pH, const rehash(pH,8); if( pH->htsize==0 ){ pH->count = 0; + if( pH->copyKey ){ + pH->xFree(new_elem->pKey); + } pH->xFree(new_elem); return data; } ============================================================ --- sqlite/insert.c e9526ced19978a55687b55faea969b6ff2a53fb4 +++ sqlite/insert.c 967be8c143d64c904ba4e6f66760824898a75e3c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.172 2006/08/29 18:46:14 drh Exp $ +** $Id: insert.c,v 1.183 2007/04/01 23:49:52 drh Exp $ */ #include "sqliteInt.h" @@ -118,7 +118,118 @@ static int selectReadsTable(Select *p, S return 0; } +#ifndef SQLITE_OMIT_AUTOINCREMENT /* +** Write out code to initialize the autoincrement logic. This code +** looks up the current autoincrement value in the sqlite_sequence +** table and stores that value in a memory cell. Code generated by +** autoIncStep() will keep that memory cell holding the largest +** rowid value. Code generated by autoIncEnd() will write the new +** largest value of the counter back into the sqlite_sequence table. +** +** This routine returns the index of the mem[] cell that contains +** the maximum rowid counter. +** +** Two memory cells are allocated. The next memory cell after the +** one returned holds the rowid in sqlite_sequence where we will +** write back the revised maximum rowid. +*/ +static int autoIncBegin( + Parse *pParse, /* Parsing context */ + int iDb, /* Index of the database holding pTab */ + Table *pTab /* The table we are writing to */ +){ + int memId = 0; + if( pTab->autoInc ){ + Vdbe *v = pParse->pVdbe; + Db *pDb = &pParse->db->aDb[iDb]; + int iCur = pParse->nTab; + int addr; + assert( v ); + addr = sqlite3VdbeCurrentAddr(v); + memId = pParse->nMem+1; + pParse->nMem += 2; + sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead); + sqlite3VdbeAddOp(v, OP_Rewind, iCur, addr+13); + sqlite3VdbeAddOp(v, OP_Column, iCur, 0); + sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0); + sqlite3VdbeAddOp(v, OP_Ne, 0x100, addr+12); + sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0); + sqlite3VdbeAddOp(v, OP_MemStore, memId-1, 1); + sqlite3VdbeAddOp(v, OP_Column, iCur, 1); + sqlite3VdbeAddOp(v, OP_MemStore, memId, 1); + sqlite3VdbeAddOp(v, OP_Goto, 0, addr+13); + sqlite3VdbeAddOp(v, OP_Next, iCur, addr+4); + sqlite3VdbeAddOp(v, OP_Close, iCur, 0); + } + return memId; +} + +/* +** Update the maximum rowid for an autoincrement calculation. +** +** This routine should be called when the top of the stack holds a +** new rowid that is about to be inserted. If that new rowid is +** larger than the maximum rowid in the memId memory cell, then the +** memory cell is updated. The stack is unchanged. +*/ +static void autoIncStep(Parse *pParse, int memId){ + if( memId>0 ){ + sqlite3VdbeAddOp(pParse->pVdbe, OP_MemMax, memId, 0); + } +} + +/* +** After doing one or more inserts, the maximum rowid is stored +** in mem[memId]. Generate code to write this value back into the +** the sqlite_sequence table. +*/ +static void autoIncEnd( + Parse *pParse, /* The parsing context */ + int iDb, /* Index of the database holding pTab */ + Table *pTab, /* Table we are inserting into */ + int memId /* Memory cell holding the maximum rowid */ +){ + if( pTab->autoInc ){ + int iCur = pParse->nTab; + Vdbe *v = pParse->pVdbe; + Db *pDb = &pParse->db->aDb[iDb]; + int addr; + assert( v ); + addr = sqlite3VdbeCurrentAddr(v); + sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); + sqlite3VdbeAddOp(v, OP_MemLoad, memId-1, 0); + sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+7); + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + sqlite3VdbeAddOp(v, OP_NewRowid, iCur, 0); + sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0); + sqlite3VdbeAddOp(v, OP_MemLoad, memId, 0); + sqlite3VdbeAddOp(v, OP_MakeRecord, 2, 0); + sqlite3VdbeAddOp(v, OP_Insert, iCur, OPFLAG_APPEND); + sqlite3VdbeAddOp(v, OP_Close, iCur, 0); + } +} +#else +/* +** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines +** above are all no-ops +*/ +# define autoIncBegin(A,B,C) (0) +# define autoIncStep(A,B) +# define autoIncEnd(A,B,C,D) +#endif /* SQLITE_OMIT_AUTOINCREMENT */ + + +/* Forward declaration */ +static int xferOptimization( + Parse *pParse, /* Parser context */ + Table *pDest, /* The table we are inserting into */ + Select *pSelect, /* A SELECT statement to use as the data source */ + int onError, /* How to handle constraint errors */ + int iDbDest /* The database of pDest */ +); + +/* ** This routine is call to handle SQL of the following forms: ** ** insert into TABLE (IDLIST) values(EXPRLIST) @@ -133,7 +244,7 @@ static int selectReadsTable(Select *p, S ** NULL and pSelect is a pointer to the select statement used to generate ** data for the insert. ** -** The code generated follows one of three templates. For a simple +** The code generated follows one of four templates. For a simple ** select with data coming from a VALUES clause, the code executes ** once straight down through. The template looks like this: ** @@ -142,16 +253,37 @@ static int selectReadsTable(Select *p, S ** write the resulting record into ** cleanup ** -** If the statement is of the form +** The three remaining templates assume the statement is of the form ** ** INSERT INTO
SELECT ... ** -** And the SELECT clause does not read from
at any time, then -** the generated code follows this template: +** If the SELECT clause is of the restricted form "SELECT * FROM " - +** in other words if the SELECT pulls all columns from a single table +** and there is no WHERE or LIMIT or GROUP BY or ORDER BY clauses, and +** if and are distinct tables but have identical +** schemas, including all the same indices, then a special optimization +** is invoked that copies raw records from over to . +** See the xferOptimization() function for the implementation of this +** template. This is the second template. ** +** open a write cursor to
+** open read cursor on +** transfer all records in over to
+** close cursors +** foreach index on
+** open a write cursor on the
index +** open a read cursor on the corresponding index +** transfer all records from the read to the write cursors +** close cursors +** end foreach +** +** The third template is for when the second template does not apply +** and the SELECT clause does not read from
at any time. +** The generated code follows this template: +** ** goto B ** A: setup for the SELECT -** loop over the tables in the SELECT +** loop over the rows in the SELECT ** gosub C ** end loop ** cleanup after the SELECT @@ -162,7 +294,7 @@ static int selectReadsTable(Select *p, S ** return ** D: cleanup ** -** The third template is used if the insert statement takes its +** The fourth template is used if the insert statement takes its ** values from a SELECT but the data is being inserted into a table ** that is also read as part of the SELECT. In the third form, ** we have to use a intermediate table to store the results of @@ -214,6 +346,7 @@ void sqlite3Insert( int newIdx = -1; /* Cursor for the NEW table */ Db *pDb; /* The database containing table being inserted into */ int counterMem = 0; /* Memory cell holding AUTOINCREMENT counter */ + int appendFlag = 0; /* True if the insert is likely to be an append */ int iDb; #ifndef SQLITE_OMIT_TRIGGER @@ -221,10 +354,6 @@ void sqlite3Insert( int triggers_exist = 0; /* True if there are FOR EACH ROW triggers */ #endif -#ifndef SQLITE_OMIT_AUTOINCREMENT - int counterRowid = 0; /* Memory cell holding rowid of autoinc counter */ -#endif - if( pParse->nErr || sqlite3MallocFailed() ){ goto insert_cleanup; } @@ -291,31 +420,27 @@ void sqlite3Insert( newIdx = pParse->nTab++; } -#ifndef SQLITE_OMIT_AUTOINCREMENT +#ifndef SQLITE_OMIT_XFER_OPT + /* If the statement is of the form + ** + ** INSERT INTO SELECT * FROM ; + ** + ** Then special optimizations can be applied that make the transfer + ** very fast and which reduce fragmentation of indices. + */ + if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){ + assert( !triggers_exist ); + assert( pList==0 ); + goto insert_cleanup; + } +#endif /* SQLITE_OMIT_XFER_OPT */ + /* If this is an AUTOINCREMENT table, look up the sequence number in the ** sqlite_sequence table and store it in memory cell counterMem. Also ** remember the rowid of the sqlite_sequence table entry in memory cell ** counterRowid. */ - if( pTab->autoInc ){ - int iCur = pParse->nTab; - int addr = sqlite3VdbeCurrentAddr(v); - counterRowid = pParse->nMem++; - counterMem = pParse->nMem++; - sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead); - sqlite3VdbeAddOp(v, OP_Rewind, iCur, addr+13); - sqlite3VdbeAddOp(v, OP_Column, iCur, 0); - sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0); - sqlite3VdbeAddOp(v, OP_Ne, 0x100, addr+12); - sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0); - sqlite3VdbeAddOp(v, OP_MemStore, counterRowid, 1); - sqlite3VdbeAddOp(v, OP_Column, iCur, 1); - sqlite3VdbeAddOp(v, OP_MemStore, counterMem, 1); - sqlite3VdbeAddOp(v, OP_Goto, 0, addr+13); - sqlite3VdbeAddOp(v, OP_Next, iCur, addr+4); - sqlite3VdbeAddOp(v, OP_Close, iCur, 0); - } -#endif /* SQLITE_OMIT_AUTOINCREMENT */ + counterMem = autoIncBegin(pParse, iDb, pTab); /* Figure out how many columns of data are supplied. If the data ** is coming from a SELECT statement, then this step also generates @@ -365,7 +490,7 @@ void sqlite3Insert( sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); sqlite3VdbeAddOp(v, OP_NewRowid, srcTab, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); - sqlite3VdbeAddOp(v, OP_Insert, srcTab, 0); + sqlite3VdbeAddOp(v, OP_Insert, srcTab, OPFLAG_APPEND); sqlite3VdbeAddOp(v, OP_Return, 0, 0); /* The following code runs first because the GOTO at the very top @@ -577,25 +702,32 @@ void sqlite3Insert( }else if( pSelect ){ sqlite3VdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1); }else{ + VdbeOp *pOp; sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr); + pOp = sqlite3VdbeGetOp(v, sqlite3VdbeCurrentAddr(v) - 1); + if( pOp->opcode==OP_Null ){ + appendFlag = 1; + pOp->opcode = OP_NewRowid; + pOp->p1 = base; + pOp->p2 = counterMem; + } } /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid ** to generate a unique primary key value. */ - sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); - sqlite3VdbeAddOp(v, OP_Pop, 1, 0); - sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem); - sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); + if( !appendFlag ){ + sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem); + sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); + } }else if( IsVirtual(pTab) ){ sqlite3VdbeAddOp(v, OP_Null, 0, 0); }else{ sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem); + appendFlag = 1; } -#ifndef SQLITE_OMIT_AUTOINCREMENT - if( pTab->autoInc ){ - sqlite3VdbeAddOp(v, OP_MemMax, counterMem, 0); - } -#endif /* SQLITE_OMIT_AUTOINCREMENT */ + autoIncStep(pParse, counterMem); /* Push onto the stack, data for all columns of the new entry, beginning ** with the first column. @@ -641,7 +773,8 @@ void sqlite3Insert( sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0, 0, onError, endOfLoop); sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0, - (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1); + (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1, + appendFlag); } } @@ -688,26 +821,11 @@ void sqlite3Insert( } } -#ifndef SQLITE_OMIT_AUTOINCREMENT /* Update the sqlite_sequence table by storing the content of the ** counter value in memory counterMem back into the sqlite_sequence ** table. */ - if( pTab->autoInc ){ - int iCur = pParse->nTab; - int addr = sqlite3VdbeCurrentAddr(v); - sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); - sqlite3VdbeAddOp(v, OP_MemLoad, counterRowid, 0); - sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+7); - sqlite3VdbeAddOp(v, OP_Pop, 1, 0); - sqlite3VdbeAddOp(v, OP_NewRowid, iCur, 0); - sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0); - sqlite3VdbeAddOp(v, OP_MemLoad, counterMem, 0); - sqlite3VdbeAddOp(v, OP_MakeRecord, 2, 0); - sqlite3VdbeAddOp(v, OP_Insert, iCur, 0); - sqlite3VdbeAddOp(v, OP_Close, iCur, 0); - } -#endif + autoIncEnd(pParse, iDb, pTab, counterMem); /* ** Return the number of rows inserted. If this routine is @@ -1067,7 +1185,8 @@ void sqlite3CompleteInsertion( char *aIdxUsed, /* Which indices are used. NULL means all are used */ int rowidChng, /* True if the record number will change */ int isUpdate, /* True for UPDATE, False for INSERT */ - int newIdx /* Index of NEW table for triggers. -1 if none */ + int newIdx, /* Index of NEW table for triggers. -1 if none */ + int appendBias /* True if this is likely to be an append */ ){ int i; Vdbe *v; @@ -1098,6 +1217,9 @@ void sqlite3CompleteInsertion( pik_flags = OPFLAG_NCHANGE; pik_flags |= (isUpdate?OPFLAG_ISUPDATE:OPFLAG_LASTROWID); } + if( appendBias ){ + pik_flags |= OPFLAG_APPEND; + } sqlite3VdbeAddOp(v, OP_Insert, base, pik_flags); if( !pParse->nested ){ sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC); @@ -1140,3 +1262,327 @@ void sqlite3OpenTableAndIndices( pParse->nTab = base+i; } } + + +#ifdef SQLITE_TEST +/* +** The following global variable is incremented whenever the +** transfer optimization is used. This is used for testing +** purposes only - to make sure the transfer optimization really +** is happening when it is suppose to. +*/ +int sqlite3_xferopt_count; +#endif /* SQLITE_TEST */ + + +#ifndef SQLITE_OMIT_XFER_OPT +/* +** Check to collation names to see if they are compatible. +*/ +static int xferCompatibleCollation(const char *z1, const char *z2){ + if( z1==0 ){ + return z2==0; + } + if( z2==0 ){ + return 0; + } + return sqlite3StrICmp(z1, z2)==0; +} + + +/* +** Check to see if index pSrc is compatible as a source of data +** for index pDest in an insert transfer optimization. The rules +** for a compatible index: +** +** * The index is over the same set of columns +** * The same DESC and ASC markings occurs on all columns +** * The same onError processing (OE_Abort, OE_Ignore, etc) +** * The same collating sequence on each column +*/ +static int xferCompatibleIndex(Index *pDest, Index *pSrc){ + int i; + assert( pDest && pSrc ); + assert( pDest->pTable!=pSrc->pTable ); + if( pDest->nColumn!=pSrc->nColumn ){ + return 0; /* Different number of columns */ + } + if( pDest->onError!=pSrc->onError ){ + return 0; /* Different conflict resolution strategies */ + } + for(i=0; inColumn; i++){ + if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){ + return 0; /* Different columns indexed */ + } + if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){ + return 0; /* Different sort orders */ + } + if( pSrc->azColl[i]!=pDest->azColl[i] ){ + return 0; /* Different sort orders */ + } + } + + /* If no test above fails then the indices must be compatible */ + return 1; +} + +/* +** Attempt the transfer optimization on INSERTs of the form +** +** INSERT INTO tab1 SELECT * FROM tab2; +** +** This optimization is only attempted if +** +** (1) tab1 and tab2 have identical schemas including all the +** same indices and constraints +** +** (2) tab1 and tab2 are different tables +** +** (3) There must be no triggers on tab1 +** +** (4) The result set of the SELECT statement is "*" +** +** (5) The SELECT statement has no WHERE, HAVING, ORDER BY, GROUP BY, +** or LIMIT clause. +** +** (6) The SELECT statement is a simple (not a compound) select that +** contains only tab2 in its FROM clause +** +** This method for implementing the INSERT transfers raw records from +** tab2 over to tab1. The columns are not decoded. Raw records from +** the indices of tab2 are transfered to tab1 as well. In so doing, +** the resulting tab1 has much less fragmentation. +** +** This routine returns TRUE if the optimization is attempted. If any +** of the conditions above fail so that the optimization should not +** be attempted, then this routine returns FALSE. +*/ +static int xferOptimization( + Parse *pParse, /* Parser context */ + Table *pDest, /* The table we are inserting into */ + Select *pSelect, /* A SELECT statement to use as the data source */ + int onError, /* How to handle constraint errors */ + int iDbDest /* The database of pDest */ +){ + ExprList *pEList; /* The result set of the SELECT */ + Table *pSrc; /* The table in the FROM clause of SELECT */ + Index *pSrcIdx, *pDestIdx; /* Source and destination indices */ + struct SrcList_item *pItem; /* An element of pSelect->pSrc */ + int i; /* Loop counter */ + int iDbSrc; /* The database of pSrc */ + int iSrc, iDest; /* Cursors from source and destination */ + int addr1, addr2; /* Loop addresses */ + int emptyDestTest; /* Address of test for empty pDest */ + int emptySrcTest; /* Address of test for empty pSrc */ + int memRowid = 0; /* A memcell containing a rowid from pSrc */ + Vdbe *v; /* The VDBE we are building */ + KeyInfo *pKey; /* Key information for an index */ + int counterMem; /* Memory register used by AUTOINC */ + + if( pSelect==0 ){ + return 0; /* Must be of the form INSERT INTO ... SELECT ... */ + } + if( pDest->pTrigger ){ + return 0; /* tab1 must not have triggers */ + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( pDest->isVirtual ){ + return 0; /* tab1 must not be a virtual table */ + } +#endif + if( onError==OE_Default ){ + onError = OE_Abort; + } + if( onError!=OE_Abort && onError!=OE_Rollback ){ + return 0; /* Cannot do OR REPLACE or OR IGNORE or OR FAIL */ + } + if( pSelect->pSrc==0 ){ + return 0; /* SELECT must have a FROM clause */ + } + if( pSelect->pSrc->nSrc!=1 ){ + return 0; /* FROM clause must have exactly one term */ + } + if( pSelect->pSrc->a[0].pSelect ){ + return 0; /* FROM clause cannot contain a subquery */ + } + if( pSelect->pWhere ){ + return 0; /* SELECT may not have a WHERE clause */ + } + if( pSelect->pOrderBy ){ + return 0; /* SELECT may not have an ORDER BY clause */ + } + /* Do not need to test for a HAVING clause. If HAVING is present but + ** there is no ORDER BY, we will get an error. */ + if( pSelect->pGroupBy ){ + return 0; /* SELECT may not have a GROUP BY clause */ + } + if( pSelect->pLimit ){ + return 0; /* SELECT may not have a LIMIT clause */ + } + assert( pSelect->pOffset==0 ); /* Must be so if pLimit==0 */ + if( pSelect->pPrior ){ + return 0; /* SELECT may not be a compound query */ + } + if( pSelect->isDistinct ){ + return 0; /* SELECT may not be DISTINCT */ + } + pEList = pSelect->pEList; + assert( pEList!=0 ); + if( pEList->nExpr!=1 ){ + return 0; /* The result set must have exactly one column */ + } + assert( pEList->a[0].pExpr ); + if( pEList->a[0].pExpr->op!=TK_ALL ){ + return 0; /* The result set must be the special operator "*" */ + } + + /* At this point we have established that the statement is of the + ** correct syntactic form to participate in this optimization. Now + ** we have to check the semantics. + */ + pItem = pSelect->pSrc->a; + pSrc = sqlite3LocateTable(pParse, pItem->zName, pItem->zDatabase); + if( pSrc==0 ){ + return 0; /* FROM clause does not contain a real table */ + } + if( pSrc==pDest ){ + return 0; /* tab1 and tab2 may not be the same table */ + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( pSrc->isVirtual ){ + return 0; /* tab2 must not be a virtual table */ + } +#endif + if( pSrc->pSelect ){ + return 0; /* tab2 may not be a view */ + } + if( pDest->nCol!=pSrc->nCol ){ + return 0; /* Number of columns must be the same in tab1 and tab2 */ + } + if( pDest->iPKey!=pSrc->iPKey ){ + return 0; /* Both tables must have the same INTEGER PRIMARY KEY */ + } + for(i=0; inCol; i++){ + if( pDest->aCol[i].affinity!=pSrc->aCol[i].affinity ){ + return 0; /* Affinity must be the same on all columns */ + } + if( !xferCompatibleCollation(pDest->aCol[i].zColl, pSrc->aCol[i].zColl) ){ + return 0; /* Collating sequence must be the same on all columns */ + } + if( pDest->aCol[i].notNull && !pSrc->aCol[i].notNull ){ + return 0; /* tab2 must be NOT NULL if tab1 is */ + } + } + for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ + for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){ + if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; + } + if( pSrcIdx==0 ){ + return 0; /* pDestIdx has no corresponding index in pSrc */ + } + } +#ifndef SQLITE_OMIT_CHECK + if( pDest->pCheck && !sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){ + return 0; /* Tables have different CHECK constraints. Ticket #2252 */ + } +#endif + + /* If we get this far, it means either: + ** + ** * We can always do the transfer if the table contains an + ** an integer primary key + ** + ** * We can conditionally do the transfer if the destination + ** table is empty. + */ +#ifdef SQLITE_TEST + sqlite3_xferopt_count++; +#endif + iDbSrc = sqlite3SchemaToIndex(pParse->db, pSrc->pSchema); + v = sqlite3GetVdbe(pParse); + iSrc = pParse->nTab++; + iDest = pParse->nTab++; + counterMem = autoIncBegin(pParse, iDbDest, pDest); + sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite); + if( pDest->iPKey<0 && pDest->pIndex!=0 ){ + /* If tables do not have an INTEGER PRIMARY KEY and there + ** are indices to be copied and the destination is not empty, + ** we have to disallow the transfer optimization because the + ** the rowids might change which will mess up indexing. + */ + addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iDest, 0); + emptyDestTest = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); + sqlite3VdbeJumpHere(v, addr1); + }else{ + emptyDestTest = 0; + } + sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); + emptySrcTest = sqlite3VdbeAddOp(v, OP_Rewind, iSrc, 0); + if( pDest->pIndex!=0 ){ + sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0); + memRowid = pParse->nMem++; + sqlite3VdbeAddOp(v, OP_MemStore, memRowid, pDest->iPKey>=0); + } + if( pDest->iPKey>=0 ){ + addr1 = sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0); + sqlite3VdbeAddOp(v, OP_Dup, 0, 0); + addr2 = sqlite3VdbeAddOp(v, OP_NotExists, iDest, 0); + sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, + "PRIMARY KEY must be unique", P3_STATIC); + sqlite3VdbeJumpHere(v, addr2); + autoIncStep(pParse, counterMem); + }else if( pDest->pIndex==0 ){ + addr1 = sqlite3VdbeAddOp(v, OP_NewRowid, iDest, 0); + }else{ + addr1 = sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0); + assert( pDest->autoInc==0 ); + } + sqlite3VdbeAddOp(v, OP_RowData, iSrc, 0); + sqlite3VdbeOp3(v, OP_Insert, iDest, + OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND, + pDest->zName, 0); + sqlite3VdbeAddOp(v, OP_Next, iSrc, addr1); + autoIncEnd(pParse, iDbDest, pDest, counterMem); + for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ + for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){ + if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; + } + assert( pSrcIdx ); + sqlite3VdbeAddOp(v, OP_Close, iSrc, 0); + sqlite3VdbeAddOp(v, OP_Close, iDest, 0); + sqlite3VdbeAddOp(v, OP_Integer, iDbSrc, 0); + pKey = sqlite3IndexKeyinfo(pParse, pSrcIdx); + VdbeComment((v, "# %s", pSrcIdx->zName)); + sqlite3VdbeOp3(v, OP_OpenRead, iSrc, pSrcIdx->tnum, + (char*)pKey, P3_KEYINFO_HANDOFF); + sqlite3VdbeAddOp(v, OP_Integer, iDbDest, 0); + pKey = sqlite3IndexKeyinfo(pParse, pDestIdx); + VdbeComment((v, "# %s", pDestIdx->zName)); + sqlite3VdbeOp3(v, OP_OpenWrite, iDest, pDestIdx->tnum, + (char*)pKey, P3_KEYINFO_HANDOFF); + addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iSrc, 0); + sqlite3VdbeAddOp(v, OP_RowKey, iSrc, 0); + if( pDestIdx->onError!=OE_None ){ + sqlite3VdbeAddOp(v, OP_MemLoad, memRowid, 0); + addr2 = sqlite3VdbeAddOp(v, OP_IsUnique, iDest, 0); + sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, + "UNIQUE constraint failed", P3_STATIC); + sqlite3VdbeJumpHere(v, addr2); + } + sqlite3VdbeAddOp(v, OP_IdxInsert, iDest, 1); + sqlite3VdbeAddOp(v, OP_Next, iSrc, addr1+1); + sqlite3VdbeJumpHere(v, addr1); + } + sqlite3VdbeJumpHere(v, emptySrcTest); + sqlite3VdbeAddOp(v, OP_Close, iSrc, 0); + sqlite3VdbeAddOp(v, OP_Close, iDest, 0); + if( emptyDestTest ){ + sqlite3VdbeAddOp(v, OP_Halt, SQLITE_OK, 0); + sqlite3VdbeJumpHere(v, emptyDestTest); + sqlite3VdbeAddOp(v, OP_Close, iDest, 0); + return 0; + }else{ + return 1; + } +} +#endif /* SQLITE_OMIT_XFER_OPT */ ============================================================ --- sqlite/keywordhash.h abfcf4e03418b130f420f2d8c4a733d137bd2912 +++ sqlite/keywordhash.h 65fe072d2fa7cf2cfece3c7550f9085ec2988717 @@ -1,85 +1,98 @@ -/* Hash score: 167 */ +/***** This file contains automatically generated code ****** +** +** The code in this file has been automatically generated by +** +** $Header: /sqlite/sqlite/tool/mkkeywordhash.c,v 1.27 2007/04/06 11:26:00 drh Exp $ +** +** The code in this file implements a function that determines whether +** or not a given identifier is really an SQL keyword. The same thing +** might be implemented more directly using a hand-written hash table. +** But by using this automatically generated code, the size of the code +** is substantially reduced. This is important for embedded applications +** on platforms with limited memory. +*/ +/* Hash score: 165 */ static int keywordCode(const char *z, int n){ - static const char zText[544] = + static const char zText[536] = "ABORTABLEFTEMPORARYADDATABASELECTHENDEFAULTRANSACTIONATURALTER" "AISEACHECKEYAFTEREFERENCESCAPELSEXCEPTRIGGEREGEXPLAINITIALLYANALYZE" - "XCLUSIVEXISTSTATEMENTANDEFERRABLEATTACHAVINGLOBEFOREIGNOREINDEX" - "AUTOINCREMENTBEGINNERENAMEBETWEENOTNULLIKEBYCASCADEFERREDELETE" - "CASECASTCOLLATECOLUMNCOMMITCONFLICTCONSTRAINTERSECTCREATECROSS" - "CURRENT_DATECURRENT_TIMESTAMPLANDESCDETACHDISTINCTDROPRAGMATCH" - "FAILIMITFROMFULLGROUPDATEIFIMMEDIATEINSERTINSTEADINTOFFSETISNULL" - "JOINORDEREPLACEOUTERESTRICTPRIMARYQUERYRIGHTROLLBACKROWHENUNION" - "UNIQUEUSINGVACUUMVALUESVIEWHEREVIRTUAL"; + "XCLUSIVEXISTSANDEFERRABLEATTACHAVINGLOBEFOREIGNOREINDEXAUTOINCREMENT" + "BEGINNERENAMEBETWEENOTNULLIKEBYCASCADEFERREDELETECASECASTCOLLATE" + "COLUMNCOMMITCONFLICTCONSTRAINTERSECTCREATECROSSCURRENT_DATECURRENT_TIMESTAMP" + "LANDESCDETACHDISTINCTDROPRAGMATCHFAILIMITFROMFULLGROUPDATEIFIMMEDIATE" + "INSERTINSTEADINTOFFSETISNULLJOINORDEREPLACEOUTERESTRICTPRIMARY" + "QUERYRIGHTROLLBACKROWHENUNIONUNIQUEUSINGVACUUMVALUESVIEWHEREVIRTUAL" + ; static const unsigned char aHash[127] = { - 92, 80, 107, 91, 0, 4, 0, 0, 114, 0, 83, 0, 0, - 95, 44, 76, 93, 0, 106, 109, 97, 90, 0, 10, 0, 0, - 113, 0, 117, 103, 0, 28, 48, 0, 41, 0, 0, 65, 71, - 0, 63, 19, 0, 105, 36, 104, 0, 108, 74, 0, 0, 33, - 0, 61, 37, 0, 8, 0, 115, 38, 12, 0, 77, 40, 25, - 66, 0, 0, 31, 81, 53, 30, 50, 20, 88, 0, 34, 0, - 75, 26, 0, 72, 0, 0, 0, 64, 47, 67, 22, 87, 29, - 69, 86, 0, 1, 0, 9, 101, 58, 18, 0, 112, 82, 99, - 54, 6, 85, 0, 0, 49, 94, 0, 102, 0, 70, 0, 0, - 15, 0, 116, 51, 56, 0, 2, 55, 0, 111, + 91, 79, 106, 90, 0, 4, 0, 0, 113, 0, 82, 0, 0, + 94, 43, 75, 92, 0, 105, 108, 96, 89, 0, 10, 0, 0, + 112, 0, 116, 102, 0, 28, 47, 0, 40, 0, 0, 64, 70, + 0, 62, 19, 0, 104, 35, 103, 0, 107, 73, 0, 0, 33, + 0, 60, 36, 0, 8, 0, 114, 37, 12, 0, 76, 39, 25, + 65, 0, 0, 31, 80, 52, 30, 49, 20, 87, 0, 34, 0, + 74, 26, 0, 71, 0, 0, 0, 63, 46, 66, 22, 86, 29, + 68, 85, 0, 1, 0, 9, 100, 57, 18, 0, 111, 81, 98, + 53, 6, 84, 0, 0, 48, 93, 0, 101, 0, 69, 0, 0, + 15, 0, 115, 50, 55, 0, 2, 54, 0, 110, }; - static const unsigned char aNext[117] = { + static const unsigned char aNext[116] = { 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, - 0, 11, 0, 0, 0, 0, 5, 13, 0, 7, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, - 0, 0, 16, 0, 23, 52, 0, 0, 0, 0, 45, 0, 59, - 0, 0, 0, 0, 0, 0, 0, 0, 73, 42, 0, 24, 60, - 21, 0, 79, 0, 0, 68, 0, 0, 84, 46, 0, 0, 0, - 0, 0, 0, 0, 0, 39, 96, 98, 0, 0, 100, 0, 32, - 0, 14, 27, 78, 0, 57, 89, 0, 35, 0, 62, 0, 110, + 0, 11, 0, 0, 0, 0, 5, 13, 7, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, + 0, 16, 0, 23, 51, 0, 0, 0, 0, 44, 0, 58, 0, + 0, 0, 0, 0, 0, 0, 0, 72, 41, 0, 24, 59, 21, + 0, 78, 0, 0, 67, 0, 0, 83, 45, 0, 0, 0, 0, + 0, 0, 0, 0, 38, 95, 97, 0, 0, 99, 0, 32, 0, + 14, 27, 77, 0, 56, 88, 0, 0, 0, 61, 0, 109, }; - static const unsigned char aLen[117] = { + static const unsigned char aLen[116] = { 5, 5, 4, 4, 9, 2, 3, 8, 2, 6, 4, 3, 7, 11, 2, 7, 5, 5, 4, 5, 3, 5, 10, 6, 4, 6, - 7, 6, 7, 9, 3, 7, 9, 6, 9, 3, 10, 6, 6, - 4, 6, 3, 7, 6, 7, 5, 13, 2, 2, 5, 5, 6, - 7, 3, 7, 4, 4, 2, 7, 3, 8, 6, 4, 4, 7, - 6, 6, 8, 10, 9, 6, 5, 12, 12, 17, 4, 4, 6, - 8, 2, 4, 6, 5, 4, 5, 4, 4, 5, 6, 2, 9, - 6, 7, 4, 2, 6, 3, 6, 4, 5, 7, 5, 8, 7, - 5, 5, 8, 3, 4, 5, 6, 5, 6, 6, 4, 5, 7, + 7, 6, 7, 9, 3, 7, 9, 6, 3, 10, 6, 6, 4, + 6, 3, 7, 6, 7, 5, 13, 2, 2, 5, 5, 6, 7, + 3, 7, 4, 4, 2, 7, 3, 8, 6, 4, 4, 7, 6, + 6, 8, 10, 9, 6, 5, 12, 12, 17, 4, 4, 6, 8, + 2, 4, 6, 5, 4, 5, 4, 4, 5, 6, 2, 9, 6, + 7, 4, 2, 6, 3, 6, 4, 5, 7, 5, 8, 7, 5, + 5, 8, 3, 4, 5, 6, 5, 6, 6, 4, 5, 7, }; - static const unsigned short int aOffset[117] = { + static const unsigned short int aOffset[116] = { 0, 4, 7, 10, 10, 14, 19, 21, 26, 27, 32, 34, 36, 42, 51, 52, 57, 61, 65, 67, 71, 74, 78, 86, 91, 94, - 99, 105, 108, 113, 118, 122, 128, 136, 141, 150, 152, 162, 167, - 172, 175, 177, 177, 181, 185, 187, 192, 194, 196, 205, 208, 212, - 218, 224, 224, 227, 230, 234, 236, 237, 241, 248, 254, 258, 262, - 269, 275, 281, 289, 296, 305, 311, 316, 328, 328, 344, 348, 352, - 358, 359, 366, 369, 373, 378, 381, 386, 390, 394, 397, 403, 405, - 414, 420, 427, 430, 430, 433, 436, 442, 446, 450, 457, 461, 469, - 476, 481, 486, 494, 496, 500, 505, 511, 516, 522, 528, 531, 536, + 99, 105, 108, 113, 118, 122, 128, 136, 142, 144, 154, 159, 164, + 167, 169, 169, 173, 177, 179, 184, 186, 188, 197, 200, 204, 210, + 216, 216, 219, 222, 226, 228, 229, 233, 240, 246, 250, 254, 261, + 267, 273, 281, 288, 297, 303, 308, 320, 320, 336, 340, 344, 350, + 351, 358, 361, 365, 370, 373, 378, 382, 386, 389, 395, 397, 406, + 412, 419, 422, 422, 425, 428, 434, 438, 442, 449, 453, 461, 468, + 473, 478, 486, 488, 492, 497, 503, 508, 514, 520, 523, 528, }; - static const unsigned char aCode[117] = { + static const unsigned char aCode[116] = { TK_ABORT, TK_TABLE, TK_JOIN_KW, TK_TEMP, TK_TEMP, TK_OR, TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_THEN, TK_END, TK_DEFAULT, TK_TRANSACTION,TK_ON, TK_JOIN_KW, TK_ALTER, TK_RAISE, TK_EACH, TK_CHECK, TK_KEY, TK_AFTER, TK_REFERENCES, TK_ESCAPE, TK_ELSE, TK_EXCEPT, TK_TRIGGER, TK_LIKE_KW, TK_EXPLAIN, TK_INITIALLY, - TK_ALL, TK_ANALYZE, TK_EXCLUSIVE, TK_EXISTS, TK_STATEMENT, - TK_AND, TK_DEFERRABLE, TK_ATTACH, TK_HAVING, TK_LIKE_KW, - TK_BEFORE, TK_FOR, TK_FOREIGN, TK_IGNORE, TK_REINDEX, - TK_INDEX, TK_AUTOINCR, TK_TO, TK_IN, TK_BEGIN, - TK_JOIN_KW, TK_RENAME, TK_BETWEEN, TK_NOT, TK_NOTNULL, - TK_NULL, TK_LIKE_KW, TK_BY, TK_CASCADE, TK_ASC, - TK_DEFERRED, TK_DELETE, TK_CASE, TK_CAST, TK_COLLATE, - TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_CONSTRAINT, TK_INTERSECT, - TK_CREATE, TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW, TK_CTIME_KW, - TK_PLAN, TK_DESC, TK_DETACH, TK_DISTINCT, TK_IS, - TK_DROP, TK_PRAGMA, TK_MATCH, TK_FAIL, TK_LIMIT, - TK_FROM, TK_JOIN_KW, TK_GROUP, TK_UPDATE, TK_IF, - TK_IMMEDIATE, TK_INSERT, TK_INSTEAD, TK_INTO, TK_OF, - TK_OFFSET, TK_SET, TK_ISNULL, TK_JOIN, TK_ORDER, - TK_REPLACE, TK_JOIN_KW, TK_RESTRICT, TK_PRIMARY, TK_QUERY, - TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_WHEN, TK_UNION, - TK_UNIQUE, TK_USING, TK_VACUUM, TK_VALUES, TK_VIEW, - TK_WHERE, TK_VIRTUAL, + TK_ALL, TK_ANALYZE, TK_EXCLUSIVE, TK_EXISTS, TK_AND, + TK_DEFERRABLE, TK_ATTACH, TK_HAVING, TK_LIKE_KW, TK_BEFORE, + TK_FOR, TK_FOREIGN, TK_IGNORE, TK_REINDEX, TK_INDEX, + TK_AUTOINCR, TK_TO, TK_IN, TK_BEGIN, TK_JOIN_KW, + TK_RENAME, TK_BETWEEN, TK_NOT, TK_NOTNULL, TK_NULL, + TK_LIKE_KW, TK_BY, TK_CASCADE, TK_ASC, TK_DEFERRED, + TK_DELETE, TK_CASE, TK_CAST, TK_COLLATE, TK_COLUMNKW, + TK_COMMIT, TK_CONFLICT, TK_CONSTRAINT, TK_INTERSECT, TK_CREATE, + TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW, TK_CTIME_KW, TK_PLAN, + TK_DESC, TK_DETACH, TK_DISTINCT, TK_IS, TK_DROP, + TK_PRAGMA, TK_MATCH, TK_FAIL, TK_LIMIT, TK_FROM, + TK_JOIN_KW, TK_GROUP, TK_UPDATE, TK_IF, TK_IMMEDIATE, + TK_INSERT, TK_INSTEAD, TK_INTO, TK_OF, TK_OFFSET, + TK_SET, TK_ISNULL, TK_JOIN, TK_ORDER, TK_REPLACE, + TK_JOIN_KW, TK_RESTRICT, TK_PRIMARY, TK_QUERY, TK_JOIN_KW, + TK_ROLLBACK, TK_ROW, TK_WHEN, TK_UNION, TK_UNIQUE, + TK_USING, TK_VACUUM, TK_VALUES, TK_VIEW, TK_WHERE, + TK_VIRTUAL, }; int h, i; if( n<2 ) return TK_ID; ============================================================ --- sqlite/loadext.c bbfdbf452c71b6f2723375478a365788498ec3cd +++ sqlite/loadext.c 146fb9b9dc6133e763888d710205c32ebf8eeca2 @@ -229,6 +229,13 @@ const sqlite3_api_routines sqlite3_apis ************************************************************************* */ sqlite3_overload_function, + + /* + ** Added after 3.3.13 + */ + sqlite3_prepare_v2, + sqlite3_prepare16_v2, + sqlite3_clear_bindings, }; /* ============================================================ --- sqlite/main.c 33c32014da3a1471e8869d2eba32b2c4314c39ce +++ sqlite/main.c c8915777ae8e50823d01eefe2b674ef68c32bf61 @@ -14,19 +14,13 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.360 2006/12/19 18:57:11 drh Exp $ +** $Id: main.c,v 1.368 2007/04/02 16:40:38 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include /* -** The following constant value is used by the SQLITE_BIGENDIAN and -** SQLITE_LITTLEENDIAN macros. -*/ -const int sqlite3one = 1; - -/* ** The version of the library */ const char sqlite3_version[] = SQLITE_VERSION; @@ -34,6 +28,24 @@ int sqlite3_libversion_number(void){ ret int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } /* +** If the following function pointer is not NULL and if +** SQLITE_ENABLE_IOTRACE is enabled, then messages describing +** I/O active are written using this function. These messages +** are intended for debugging activity only. +*/ +void (*sqlite3_io_trace)(const char*, ...) = 0; + +/* +** 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; + + +/* ** This is the default collating function named "BINARY" which is always ** available. */ @@ -128,6 +140,9 @@ int sqlite3_close(sqlite3 *db){ ** cannot be opened for some reason. So this routine needs to run in ** that case. But maybe there should be an extra magic value for the ** "failed to open" state. + ** + ** TODO: Coverage tests do not test the case where this condition is + ** true. It's hard to see how to cause it without messing with threads. */ if( db->magic!=SQLITE_MAGIC_CLOSED && sqlite3SafetyOn(db) ){ /* printf("DID NOT CLOSE\n"); fflush(stdout); */ @@ -239,7 +254,6 @@ const char *sqlite3ErrStr(int rc){ case SQLITE_CORRUPT: z = "database disk image is malformed"; break; case SQLITE_FULL: z = "database or disk is full"; break; case SQLITE_CANTOPEN: z = "unable to open database file"; break; - case SQLITE_PROTOCOL: z = "database locking protocol failure"; break; case SQLITE_EMPTY: z = "table contains no data"; break; case SQLITE_SCHEMA: z = "database schema has changed"; break; case SQLITE_CONSTRAINT: z = "constraint failed"; break; @@ -722,7 +736,8 @@ const char *sqlite3_errmsg(sqlite3 *db){ */ const char *sqlite3_errmsg(sqlite3 *db){ const char *z; - if( !db || sqlite3MallocFailed() ){ + assert( !sqlite3MallocFailed() ); + if( !db ){ return sqlite3ErrStr(SQLITE_NOMEM); } if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){ @@ -761,7 +776,8 @@ const void *sqlite3_errmsg16(sqlite3 *db }; const void *z; - if( sqlite3MallocFailed() ){ + assert( !sqlite3MallocFailed() ); + if( !db ){ return (void *)(&outOfMemBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]); } if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){ @@ -877,6 +893,9 @@ static int openDatabase( #if SQLITE_DEFAULT_FILE_FORMAT<4 | SQLITE_LegacyFileFmt #endif +#ifdef SQLITE_ENABLE_LOAD_EXTENSION + | SQLITE_LoadExtension +#endif ; sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0); sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0); @@ -958,6 +977,16 @@ static int openDatabase( } #endif + /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking + ** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking + ** mode. Doing nothing at all also makes NORMAL the default. + */ +#ifdef SQLITE_DEFAULT_LOCKING_MODE + db->dfltLockMode = SQLITE_DEFAULT_LOCKING_MODE; + sqlite3PagerLockingMode(sqlite3BtreePager(db->aDb[0].pBt), + SQLITE_DEFAULT_LOCKING_MODE); +#endif + opendb_out: if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){ sqlite3_close(db); ============================================================ --- sqlite/opcodes.c 89763333d47d401e5b32d2a5fe456a49414b4544 +++ sqlite/opcodes.c d21a21fc60da3874a0970a6e67c81c56ec507d6c @@ -61,36 +61,36 @@ const char *const sqlite3OpcodeNames[] = /* 57 */ "Callback", /* 58 */ "ContextPush", /* 59 */ "DropTrigger", - /* 60 */ "DropIndex", - /* 61 */ "Or", - /* 62 */ "And", + /* 60 */ "Or", + /* 61 */ "And", + /* 62 */ "DropIndex", /* 63 */ "IdxGE", /* 64 */ "IdxDelete", - /* 65 */ "Vacuum", - /* 66 */ "IsNull", - /* 67 */ "NotNull", - /* 68 */ "Ne", - /* 69 */ "Eq", - /* 70 */ "Gt", - /* 71 */ "Le", - /* 72 */ "Lt", - /* 73 */ "Ge", - /* 74 */ "MoveLe", - /* 75 */ "BitAnd", - /* 76 */ "BitOr", - /* 77 */ "ShiftLeft", - /* 78 */ "ShiftRight", - /* 79 */ "Add", - /* 80 */ "Subtract", - /* 81 */ "Multiply", - /* 82 */ "Divide", - /* 83 */ "Remainder", - /* 84 */ "Concat", - /* 85 */ "IfNot", - /* 86 */ "Negative", - /* 87 */ "DropTable", - /* 88 */ "BitNot", - /* 89 */ "String8", + /* 65 */ "IsNull", + /* 66 */ "NotNull", + /* 67 */ "Ne", + /* 68 */ "Eq", + /* 69 */ "Gt", + /* 70 */ "Le", + /* 71 */ "Lt", + /* 72 */ "Ge", + /* 73 */ "Vacuum", + /* 74 */ "BitAnd", + /* 75 */ "BitOr", + /* 76 */ "ShiftLeft", + /* 77 */ "ShiftRight", + /* 78 */ "Add", + /* 79 */ "Subtract", + /* 80 */ "Multiply", + /* 81 */ "Divide", + /* 82 */ "Remainder", + /* 83 */ "Concat", + /* 84 */ "MoveLe", + /* 85 */ "Negative", + /* 86 */ "IfNot", + /* 87 */ "BitNot", + /* 88 */ "String8", + /* 89 */ "DropTable", /* 90 */ "MakeRecord", /* 91 */ "Delete", /* 92 */ "AggFinal", @@ -126,9 +126,9 @@ const char *const sqlite3OpcodeNames[] = /* 122 */ "Blob", /* 123 */ "MemStore", /* 124 */ "Rewind", - /* 125 */ "MoveGe", - /* 126 */ "Real", - /* 127 */ "HexBlob", + /* 125 */ "Real", + /* 126 */ "HexBlob", + /* 127 */ "MoveGe", /* 128 */ "VBegin", /* 129 */ "VUpdate", /* 130 */ "VCreate", @@ -139,11 +139,10 @@ const char *const sqlite3OpcodeNames[] = /* 135 */ "NotUsed_135", /* 136 */ "NotUsed_136", /* 137 */ "NotUsed_137", - /* 138 */ "NotUsed_138", - /* 139 */ "ToText", - /* 140 */ "ToBlob", - /* 141 */ "ToNumeric", - /* 142 */ "ToInt", - /* 143 */ "ToReal", + /* 138 */ "ToText", + /* 139 */ "ToBlob", + /* 140 */ "ToNumeric", + /* 141 */ "ToInt", + /* 142 */ "ToReal", }; #endif ============================================================ --- sqlite/opcodes.h 2a03d6171b53b07d4b9db8a68943cb44da8191e7 +++ sqlite/opcodes.h a58b9a527965930bd27502dd8b1f101d326aa08f @@ -1,39 +1,39 @@ /* Automatically generated. Do not edit */ /* See the mkopcodeh.awk script for details */ #define OP_MemLoad 1 #define OP_VNext 2 -#define OP_HexBlob 127 /* same as TK_BLOB */ +#define OP_HexBlob 126 /* same as TK_BLOB */ #define OP_Column 3 #define OP_SetCookie 4 #define OP_IfMemPos 5 -#define OP_Real 126 /* same as TK_FLOAT */ +#define OP_Real 125 /* same as TK_FLOAT */ #define OP_Sequence 6 #define OP_MoveGt 7 -#define OP_Ge 73 /* same as TK_GE */ +#define OP_Ge 72 /* same as TK_GE */ #define OP_RowKey 8 -#define OP_Eq 69 /* same as TK_EQ */ +#define OP_Eq 68 /* same as TK_EQ */ #define OP_OpenWrite 9 -#define OP_NotNull 67 /* same as TK_NOTNULL */ +#define OP_NotNull 66 /* same as TK_NOTNULL */ #define OP_If 10 -#define OP_ToInt 142 /* same as TK_TO_INT */ -#define OP_String8 89 /* same as TK_STRING */ +#define OP_ToInt 141 /* same as TK_TO_INT */ +#define OP_String8 88 /* same as TK_STRING */ #define OP_Pop 11 #define OP_VRowid 12 #define OP_CollSeq 13 #define OP_OpenRead 14 #define OP_Expire 15 #define OP_AutoCommit 17 -#define OP_Gt 70 /* same as TK_GT */ +#define OP_Gt 69 /* same as TK_GT */ #define OP_IntegrityCk 18 #define OP_Sort 19 #define OP_Function 20 -#define OP_And 62 /* same as TK_AND */ -#define OP_Subtract 80 /* same as TK_MINUS */ +#define OP_And 61 /* same as TK_AND */ +#define OP_Subtract 79 /* same as TK_MINUS */ #define OP_Noop 21 #define OP_Return 22 -#define OP_Remainder 83 /* same as TK_REM */ +#define OP_Remainder 82 /* same as TK_REM */ #define OP_NewRowid 23 -#define OP_Multiply 81 /* same as TK_STAR */ +#define OP_Multiply 80 /* same as TK_STAR */ #define OP_IfMemNeg 24 #define OP_Variable 25 #define OP_String 26 @@ -54,41 +54,41 @@ #define OP_RowData 41 #define OP_MemMax 42 #define OP_Push 43 -#define OP_Or 61 /* same as TK_OR */ +#define OP_Or 60 /* same as TK_OR */ #define OP_NotExists 44 #define OP_MemIncr 45 #define OP_Gosub 46 -#define OP_Divide 82 /* same as TK_SLASH */ +#define OP_Divide 81 /* same as TK_SLASH */ #define OP_Integer 47 -#define OP_ToNumeric 141 /* same as TK_TO_NUMERIC*/ +#define OP_ToNumeric 140 /* same as TK_TO_NUMERIC*/ #define OP_MemInt 48 #define OP_Prev 49 -#define OP_Concat 84 /* same as TK_CONCAT */ -#define OP_BitAnd 75 /* same as TK_BITAND */ +#define OP_Concat 83 /* same as TK_CONCAT */ +#define OP_BitAnd 74 /* same as TK_BITAND */ #define OP_VColumn 50 #define OP_CreateTable 51 #define OP_Last 52 -#define OP_IsNull 66 /* same as TK_ISNULL */ +#define OP_IsNull 65 /* same as TK_ISNULL */ #define OP_IdxRowid 53 #define OP_MakeIdxRec 54 -#define OP_ShiftRight 78 /* same as TK_RSHIFT */ +#define OP_ShiftRight 77 /* same as TK_RSHIFT */ #define OP_ResetCount 55 #define OP_FifoWrite 56 #define OP_Callback 57 #define OP_ContextPush 58 #define OP_DropTrigger 59 -#define OP_DropIndex 60 +#define OP_DropIndex 62 #define OP_IdxGE 63 #define OP_IdxDelete 64 -#define OP_Vacuum 65 -#define OP_MoveLe 74 -#define OP_IfNot 85 -#define OP_DropTable 87 +#define OP_Vacuum 73 +#define OP_MoveLe 84 +#define OP_IfNot 86 +#define OP_DropTable 89 #define OP_MakeRecord 90 -#define OP_ToBlob 140 /* same as TK_TO_BLOB */ +#define OP_ToBlob 139 /* same as TK_TO_BLOB */ #define OP_Delete 91 #define OP_AggFinal 92 -#define OP_ShiftLeft 77 /* same as TK_LSHIFT */ +#define OP_ShiftLeft 76 /* same as TK_LSHIFT */ #define OP_Dup 93 #define OP_Goto 94 #define OP_TableLock 95 @@ -96,26 +96,26 @@ #define OP_Clear 97 #define OP_IdxGT 98 #define OP_MoveLt 99 -#define OP_Le 71 /* same as TK_LE */ +#define OP_Le 70 /* same as TK_LE */ #define OP_VerifyCookie 100 #define OP_AggStep 101 #define OP_Pull 102 -#define OP_ToText 139 /* same as TK_TO_TEXT */ +#define OP_ToText 138 /* same as TK_TO_TEXT */ #define OP_Not 16 /* same as TK_NOT */ -#define OP_ToReal 143 /* same as TK_TO_REAL */ +#define OP_ToReal 142 /* same as TK_TO_REAL */ #define OP_SetNumColumns 103 #define OP_AbsValue 104 #define OP_Transaction 105 #define OP_VFilter 106 -#define OP_Negative 86 /* same as TK_UMINUS */ -#define OP_Ne 68 /* same as TK_NE */ +#define OP_Negative 85 /* same as TK_UMINUS */ +#define OP_Ne 67 /* same as TK_NE */ #define OP_VDestroy 107 #define OP_ContextPop 108 -#define OP_BitOr 76 /* same as TK_BITOR */ +#define OP_BitOr 75 /* same as TK_BITOR */ #define OP_Next 109 #define OP_IdxInsert 110 #define OP_Distinct 111 -#define OP_Lt 72 /* same as TK_LT */ +#define OP_Lt 71 /* same as TK_LT */ #define OP_Insert 112 #define OP_Destroy 113 #define OP_ReadCookie 114 @@ -127,13 +127,13 @@ #define OP_OpenEphemeral 120 #define OP_Null 121 #define OP_Blob 122 -#define OP_Add 79 /* same as TK_PLUS */ +#define OP_Add 78 /* same as TK_PLUS */ #define OP_MemStore 123 #define OP_Rewind 124 -#define OP_MoveGe 125 +#define OP_MoveGe 127 #define OP_VBegin 128 #define OP_VUpdate 129 -#define OP_BitNot 88 /* same as TK_BITNOT */ +#define OP_BitNot 87 /* same as TK_BITNOT */ #define OP_VCreate 130 #define OP_MemMove 131 #define OP_MemNull 132 @@ -144,7 +144,6 @@ #define OP_NotUsed_135 135 #define OP_NotUsed_136 136 #define OP_NotUsed_137 137 -#define OP_NotUsed_138 138 /* Opcodes that are guaranteed to never push a value onto the stack ** contain a 1 their corresponding position of the following mask @@ -154,8 +153,8 @@ #define NOPUSH_MASK_2 0x7ddb #define NOPUSH_MASK_3 0xff92 #define NOPUSH_MASK_4 0xffff -#define NOPUSH_MASK_5 0xd9ef +#define NOPUSH_MASK_5 0xdaf7 #define NOPUSH_MASK_6 0xfefe -#define NOPUSH_MASK_7 0x39d9 -#define NOPUSH_MASK_8 0xf867 +#define NOPUSH_MASK_7 0x99d9 +#define NOPUSH_MASK_8 0x7c67 #define NOPUSH_MASK_9 0x0000 ============================================================ --- sqlite/os.c 59f05de8c5777c34876607114a2fbe55ae578235 +++ sqlite/os.c 4650e98aadd27abfe1698ff58edf6893c58d4881 @@ -16,6 +16,7 @@ #define _SQLITE_OS_C_ 1 #include "sqliteInt.h" #include "os.h" +#undef _SQLITE_OS_C_ /* ** The following routines are convenience wrappers around methods @@ -75,6 +76,10 @@ int sqlite3OsCheckReservedLock(OsFile *i int sqlite3OsCheckReservedLock(OsFile *id){ return id->pMethod->xCheckReservedLock(id); } +int sqlite3OsSectorSize(OsFile *id){ + int (*xSectorSize)(OsFile*) = id->pMethod->xSectorSize; + return xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE; +} #ifdef SQLITE_ENABLE_REDEF_IO /* ============================================================ --- sqlite/os.h 17fc73165cb7436aa79492d2dff754baec74fcb9 +++ sqlite/os.h 9240adf088fd55732f8926f9017601ba3430ead8 @@ -21,6 +21,18 @@ ** Figure out if we are dealing with Unix, Windows, or some other ** operating system. */ +#if defined(OS_OTHER) +# if OS_OTHER==1 +# undef OS_UNIX +# define OS_UNIX 0 +# undef OS_WIN +# define OS_WIN 0 +# undef OS_OS2 +# define OS_OS2 0 +# else +# undef OS_OTHER +# endif +#endif #if !defined(OS_UNIX) && !defined(OS_OTHER) # define OS_OTHER 0 # ifndef OS_WIN @@ -74,6 +86,13 @@ #endif /* +** The default size of a disk sector +*/ +#ifndef SQLITE_DEFAULT_SECTOR_SIZE +# define SQLITE_DEFAULT_SECTOR_SIZE 512 +#endif + +/* ** Temporary files are named starting with this prefix followed by 16 random ** alphanumeric characters, and no file extension. They are stored in the ** OS's standard temporary file directory, and are deleted prior to exit. @@ -216,6 +235,7 @@ struct IoMethod { int (*xUnlock)(OsFile*, int); int (*xLockState)(OsFile *id); int (*xCheckReservedLock)(OsFile *id); + int (*xSectorSize)(OsFile *id); }; /* @@ -346,6 +366,7 @@ int sqlite3OsSyncDirectory(const char*); char *sqlite3OsFullPathname(const char*); int sqlite3OsIsDirWritable(char*); int sqlite3OsSyncDirectory(const char*); +int sqlite3OsSectorSize(OsFile *id); int sqlite3OsTempFileName(char*); int sqlite3OsRandomSeed(char*); int sqlite3OsSleep(int ms); @@ -426,9 +447,12 @@ struct sqlite3OsVtbl { #endif -#ifdef _SQLITE_OS_C_ +#if defined(_SQLITE_OS_C_) || defined(SQLITE_AMALGAMATION) /* ** The os.c file implements the global virtual function table. + ** We have to put this file here because the initializers + ** (ex: sqlite3OsRandomSeed) are macros that are about to be + ** redefined. */ struct sqlite3OsVtbl sqlite3Os = { IF_DISKIO( sqlite3OsOpenReadWrite ), ============================================================ --- sqlite/os_common.h 545426356f0868a6765e70cb59e319d3acad0ed6 +++ sqlite/os_common.h 0969285cc1e0b1ccc7a2cd7ce8eb144176ce3369 @@ -38,25 +38,23 @@ int sqlite3_os_trace = 0; int sqlite3_os_trace = 0; #ifdef SQLITE_DEBUG -static int last_page = 0; -#define SEEK(X) last_page=(X) -#define TRACE1(X) if( sqlite3_os_trace ) sqlite3DebugPrintf(X) -#define TRACE2(X,Y) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y) -#define TRACE3(X,Y,Z) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z) -#define TRACE4(X,Y,Z,A) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A) -#define TRACE5(X,Y,Z,A,B) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A,B) -#define TRACE6(X,Y,Z,A,B,C) if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C) -#define TRACE7(X,Y,Z,A,B,C,D) \ +#define OSTRACE1(X) if( sqlite3_os_trace ) sqlite3DebugPrintf(X) +#define OSTRACE2(X,Y) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y) +#define OSTRACE3(X,Y,Z) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z) +#define OSTRACE4(X,Y,Z,A) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A) +#define OSTRACE5(X,Y,Z,A,B) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A,B) +#define OSTRACE6(X,Y,Z,A,B,C) \ + if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C) +#define OSTRACE7(X,Y,Z,A,B,C,D) \ if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C,D) #else -#define SEEK(X) -#define TRACE1(X) -#define TRACE2(X,Y) -#define TRACE3(X,Y,Z) -#define TRACE4(X,Y,Z,A) -#define TRACE5(X,Y,Z,A,B) -#define TRACE6(X,Y,Z,A,B,C) -#define TRACE7(X,Y,Z,A,B,C,D) +#define OSTRACE1(X) +#define OSTRACE2(X,Y) +#define OSTRACE3(X,Y,Z) +#define OSTRACE4(X,Y,Z,A) +#define OSTRACE5(X,Y,Z,A,B) +#define OSTRACE6(X,Y,Z,A,B,C) +#define OSTRACE7(X,Y,Z,A,B,C,D) #endif /* @@ -90,19 +88,23 @@ int sqlite3_io_error_pending = 0; #ifdef SQLITE_TEST int sqlite3_io_error_hit = 0; int sqlite3_io_error_pending = 0; +int sqlite3_io_error_persist = 0; int sqlite3_diskfull_pending = 0; int sqlite3_diskfull = 0; #define SimulateIOError(CODE) \ - if( sqlite3_io_error_pending ) \ - if( sqlite3_io_error_pending-- == 1 ){ local_ioerr(); CODE; } + if( sqlite3_io_error_pending || sqlite3_io_error_hit ) \ + if( sqlite3_io_error_pending-- == 1 \ + || (sqlite3_io_error_persist && sqlite3_io_error_hit) ) \ + { local_ioerr(); CODE; } static void local_ioerr(){ - sqlite3_io_error_hit = 1; /* Really just a place to set a breakpoint */ + sqlite3_io_error_hit = 1; } #define SimulateDiskfullError(CODE) \ if( sqlite3_diskfull_pending ){ \ if( sqlite3_diskfull_pending == 1 ){ \ local_ioerr(); \ sqlite3_diskfull = 1; \ + sqlite3_io_error_hit = 1; \ CODE; \ }else{ \ sqlite3_diskfull_pending--; \ @@ -186,3 +188,10 @@ int sqlite3GenericAllocationSize(void *p /* Never actually used, but needed for the linker */ int sqlite3GenericAllocationSize(void *p){ return 0; } #endif + +/* +** The default size of a disk sector +*/ +#ifndef PAGER_SECTOR_SIZE +# define PAGER_SECTOR_SIZE 512 +#endif ============================================================ --- sqlite/os_os2.c 8ee8207fe218a1acf3a31d59753e165e5c23bb95 +++ sqlite/os_os2.c 2ce97909b926a598823f97338027dbec1dcf4165 @@ -62,7 +62,7 @@ int sqlite3Os2Delete( const char *zFilen APIRET rc = NO_ERROR; rc = DosDelete( (PSZ)zFilename ); - TRACE2( "DELETE \"%s\"\n", zFilename ); + OSTRACE2( "DELETE \"%s\"\n", zFilename ); return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR; } @@ -127,7 +127,7 @@ int sqlite3Os2OpenReadWrite( f.delOnClose = 0; f.pathToDel = NULL; OpenCounter(+1); - TRACE3( "OPEN R/W %d \"%s\"\n", hf, zFilename ); + OSTRACE3( "OPEN R/W %d \"%s\"\n", hf, zFilename ); return allocateOs2File( &f, pld ); } @@ -167,7 +167,7 @@ int sqlite3Os2OpenExclusive( const char f.pathToDel = delFlag ? sqlite3OsFullPathname( zFilename ) : NULL; OpenCounter( +1 ); if( delFlag ) DosForceDelete( sqlite3OsFullPathname( zFilename ) ); - TRACE3( "OPEN EX %d \"%s\"\n", hf, sqlite3OsFullPathname ( zFilename ) ); + OSTRACE3( "OPEN EX %d \"%s\"\n", hf, sqlite3OsFullPathname ( zFilename ) ); return allocateOs2File( &f, pld ); } @@ -197,7 +197,7 @@ int sqlite3Os2OpenReadOnly( const char * f.delOnClose = 0; f.pathToDel = NULL; OpenCounter( +1 ); - TRACE3( "OPEN RO %d \"%s\"\n", hf, zFilename ); + OSTRACE3( "OPEN RO %d \"%s\"\n", hf, zFilename ); return allocateOs2File( &f, pld ); } @@ -225,13 +225,6 @@ int os2OpenDirectory( } /* -** 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. -*/ -char *sqlite3_temp_directory = 0; - -/* ** Create a temporary file name in zBuf. zBuf must be big enough to ** hold at least SQLITE_TEMPNAME_SIZE characters. */ @@ -261,7 +254,7 @@ int sqlite3Os2TempFileName( char *zBuf ) zBuf[j] = 0; if( !sqlite3OsFileExists( zBuf ) ) break; } - TRACE2( "TEMP FILENAME: %s\n", zBuf ); + OSTRACE2( "TEMP FILENAME: %s\n", zBuf ); return SQLITE_OK; } @@ -272,7 +265,7 @@ int os2Close( OsFile **pld ){ os2File *pFile; APIRET rc = NO_ERROR; if( pld && (pFile = (os2File*)*pld) != 0 ){ - TRACE2( "CLOSE %d\n", pFile->h ); + OSTRACE2( "CLOSE %d\n", pFile->h ); rc = DosClose( pFile->h ); pFile->locktype = NO_LOCK; if( pFile->delOnClose != 0 ){ @@ -294,7 +287,7 @@ int os2Read( OsFile *id, void *pBuf, int ULONG got; assert( id!=0 ); SimulateIOError( return SQLITE_IOERR ); - TRACE3( "READ %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype ); + OSTRACE3( "READ %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype ); DosRead( ((os2File*)id)->h, pBuf, amt, &got ); if (got == (ULONG)amt) return SQLITE_OK; @@ -316,7 +309,7 @@ int os2Write( OsFile *id, const void *pB assert( id!=0 ); SimulateIOError( return SQLITE_IOERR ); SimulateDiskfullError( return SQLITE_FULL ); - TRACE3( "WRITE %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype ); + OSTRACE3( "WRITE %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype ); while( amt > 0 && (rc = DosWrite( ((os2File*)id)->h, (PVOID)pBuf, amt, &wrote )) && wrote > 0 ){ amt -= wrote; @@ -334,7 +327,7 @@ int os2Seek( OsFile *id, i64 offset ){ ULONG filePointer = 0L; assert( id!=0 ); rc = DosSetFilePtr( ((os2File*)id)->h, offset, FILE_BEGIN, &filePointer ); - TRACE3( "SEEK %d %lld\n", ((os2File*)id)->h, offset ); + OSTRACE3( "SEEK %d %lld\n", ((os2File*)id)->h, offset ); return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR; } @@ -343,7 +336,7 @@ int os2Sync( OsFile *id, int dataOnly ){ */ int os2Sync( OsFile *id, int dataOnly ){ assert( id!=0 ); - TRACE3( "SYNC %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype ); + OSTRACE3( "SYNC %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype ); return DosResetBuffer( ((os2File*)id)->h ) == NO_ERROR ? SQLITE_OK : SQLITE_IOERR; } @@ -363,7 +356,7 @@ int os2Truncate( OsFile *id, i64 nByte ) APIRET rc = NO_ERROR; ULONG upperBits = nByte>>32; assert( id!=0 ); - TRACE3( "TRUNCATE %d %lld\n", ((os2File*)id)->h, nByte ); + OSTRACE3( "TRUNCATE %d %lld\n", ((os2File*)id)->h, nByte ); SimulateIOError( return SQLITE_IOERR ); rc = DosSetFilePtr( ((os2File*)id)->h, nByte, FILE_BEGIN, &upperBits ); if( rc != NO_ERROR ){ @@ -478,7 +471,7 @@ int os2Lock( OsFile *id, int locktype ){ memset(&LockArea, 0, sizeof(LockArea)); memset(&UnlockArea, 0, sizeof(UnlockArea)); assert( pFile!=0 ); - TRACE4( "LOCK %d %d was %d\n", pFile->h, locktype, pFile->locktype ); + OSTRACE4( "LOCK %d %d was %d\n", pFile->h, locktype, pFile->locktype ); /* 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 @@ -513,7 +506,7 @@ int os2Lock( OsFile *id, int locktype ){ /* Try 3 times to get the pending lock. The pending lock might be ** held by another reader process who will release it momentarily. */ - TRACE2( "could not get a PENDING lock. cnt=%d\n", cnt ); + OSTRACE2( "could not get a PENDING lock. cnt=%d\n", cnt ); DosSleep(1); } gotPendingLock = res; @@ -555,7 +548,7 @@ int os2Lock( OsFile *id, int locktype ){ if( locktype==EXCLUSIVE_LOCK && res ){ assert( pFile->locktype>=SHARED_LOCK ); res = unlockReadLock(pFile); - TRACE2( "unreadlock = %d\n", res ); + OSTRACE2( "unreadlock = %d\n", res ); LockArea.lOffset = SHARED_FIRST; LockArea.lRange = SHARED_SIZE; UnlockArea.lOffset = 0L; @@ -564,7 +557,7 @@ int os2Lock( OsFile *id, int locktype ){ if( res == NO_ERROR ){ newLocktype = EXCLUSIVE_LOCK; }else{ - TRACE2( "error-code = %d\n", res ); + OSTRACE2( "error-code = %d\n", res ); } } @@ -585,7 +578,7 @@ int os2Lock( OsFile *id, int locktype ){ if( res == NO_ERROR ){ rc = SQLITE_OK; }else{ - TRACE4( "LOCK FAILED %d trying for %d but got %d\n", pFile->h, + OSTRACE4( "LOCK FAILED %d trying for %d but got %d\n", pFile->h, locktype, newLocktype ); rc = SQLITE_BUSY; } @@ -604,7 +597,7 @@ int os2CheckReservedLock( OsFile *id ){ assert( pFile!=0 ); if( pFile->locktype>=RESERVED_LOCK ){ rc = 1; - TRACE3( "TEST WR-LOCK %d %d (local)\n", pFile->h, rc ); + OSTRACE3( "TEST WR-LOCK %d %d (local)\n", pFile->h, rc ); }else{ FILELOCK LockArea, UnlockArea; @@ -622,7 +615,7 @@ int os2CheckReservedLock( OsFile *id ){ UnlockArea.lRange = 1L; rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); } - TRACE3( "TEST WR-LOCK %d %d (remote)\n", pFile->h, rc ); + OSTRACE3( "TEST WR-LOCK %d %d (remote)\n", pFile->h, rc ); } return rc; } @@ -648,7 +641,7 @@ int os2Unlock( OsFile *id, int locktype memset(&UnlockArea, 0, sizeof(UnlockArea)); assert( pFile!=0 ); assert( locktype<=SHARED_LOCK ); - TRACE4( "UNLOCK %d to %d was %d\n", pFile->h, locktype, pFile->locktype ); + OSTRACE4( "UNLOCK %d to %d was %d\n", pFile->h, locktype, pFile->locktype ); type = pFile->locktype; if( type>=EXCLUSIVE_LOCK ){ LockArea.lOffset = 0L; @@ -733,6 +726,20 @@ static int os2LockState( OsFile *id ){ } /* +** Return the sector size in bytes of the underlying block device for +** the specified file. This is almost always 512 bytes, but may be +** larger for some devices. +** +** SQLite code assumes this function cannot fail. It also assumes that +** if two files are created in the same file-system directory (i.e. +** a database and it's journal file) that the sector size will be the +** same for both. +*/ +static int os2SectorSize(OsFile *id){ + return SQLITE_DEFAULT_SECTOR_SIZE; +} + +/* ** This vector defines all the methods that can operate on an OsFile ** for os2. */ @@ -751,6 +758,7 @@ static const IoMethod sqlite3Os2IoMethod os2Unlock, os2LockState, os2CheckReservedLock, + os2SectorSize, }; /* ============================================================ --- sqlite/os_unix.c 2f7f7dbb95bbfa109f951c828b248102ab75b621 +++ sqlite/os_unix.c 426b4c03c304ad78746d65d9ba101e0b72e18e23 @@ -59,7 +59,10 @@ ** If we are to be thread-safe, include the pthreads header and define ** the SQLITE_UNIX_THREADS macro. */ -#if defined(THREADSAFE) && THREADSAFE +#ifndef THREADSAFE +# define THREADSAFE 1 +#endif +#if THREADSAFE # include # define SQLITE_UNIX_THREADS 1 #endif @@ -457,7 +460,7 @@ static int lockTrace(int fd, int op, str sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n", threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len, (int)p->l_pid, s); - if( s && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){ + if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){ struct flock l2; l2 = *p; fcntl(fd, F_GETLK, &l2); @@ -753,19 +756,20 @@ static int transferOwnership(unixFile *p hSelf = pthread_self(); if( pthread_equal(pFile->tid, hSelf) ){ /* We are still in the same thread */ - TRACE1("No-transfer, same thread\n"); + OSTRACE1("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); + OSTRACE4("Transfer ownership of %d from %d to %d\n", + pFile->h, pFile->tid, hSelf); pFile->tid = hSelf; if (pFile->pLock != NULL) { releaseLockInfo(pFile->pLock); rc = findLockInfo(pFile->h, &pFile->pLock, 0); - TRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h, + OSTRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h, locktypeName(pFile->locktype), locktypeName(pFile->pLock->locktype), pFile->pLock->cnt); return rc; @@ -782,6 +786,7 @@ int sqlite3UnixDelete(const char *zFilen ** Delete the named file */ int sqlite3UnixDelete(const char *zFilename){ + SimulateIOError(return SQLITE_IOERR_DELETE); unlink(zFilename); return SQLITE_OK; } @@ -864,7 +869,7 @@ int sqlite3UnixOpenExclusive(const char assert( 0==*pId ); h = open(zFilename, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, - SQLITE_DEFAULT_FILE_PERMISSIONS); + delFlag ? 0600 : SQLITE_DEFAULT_FILE_PERMISSIONS); if( h<0 ){ return SQLITE_CANTOPEN; } @@ -914,31 +919,18 @@ static int unixOpenDirectory( const char *zDirname ){ unixFile *pFile = (unixFile*)id; - if( pFile==0 ){ - /* Do not open the directory if the corresponding file is not already - ** open. */ - return SQLITE_CANTOPEN; - } + assert( pFile!=0 ); SET_THREADID(pFile); assert( pFile->dirfd<0 ); pFile->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0); if( pFile->dirfd<0 ){ return SQLITE_CANTOPEN; } - TRACE3("OPENDIR %-3d %s\n", pFile->dirfd, zDirname); + OSTRACE3("OPENDIR %-3d %s\n", pFile->dirfd, zDirname); return SQLITE_OK; } /* -** 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 ** hold at least SQLITE_TEMPNAME_SIZE characters. */ @@ -1001,15 +993,23 @@ static int seekAndRead(unixFile *id, voi static int seekAndRead(unixFile *id, void *pBuf, int cnt){ int got; i64 newOffset; -#ifdef USE_PREAD + TIMER_START; +#if defined(USE_PREAD) got = pread(id->h, pBuf, cnt, id->offset); + SimulateIOError( got = -1 ); +#elif defined(USE_PREAD64) + got = pread64(id->h, pBuf, cnt, id->offset); + SimulateIOError( got = -1 ); #else newOffset = lseek(id->h, id->offset, SEEK_SET); + SimulateIOError( newOffset-- ); if( newOffset!=id->offset ){ return -1; } got = read(id->h, pBuf, cnt); #endif + TIMER_END; + OSTRACE5("READ %-3d %5d %7lld %d\n", id->h, got, id->offset, TIMER_ELAPSED); if( got>0 ){ id->offset += got; } @@ -1024,13 +1024,7 @@ static int unixRead(OsFile *id, void *pB static int unixRead(OsFile *id, void *pBuf, int amt){ int got; assert( id ); - TIMER_START; got = seekAndRead((unixFile*)id, pBuf, amt); - TIMER_END; - TRACE5("READ %-3d %5d %7d %d\n", ((unixFile*)id)->h, got, - last_page, TIMER_ELAPSED); - SEEK(0); - SimulateIOError( got = -1 ); if( got==amt ){ return SQLITE_OK; }else if( got<0 ){ @@ -1048,8 +1042,11 @@ static int seekAndWrite(unixFile *id, co static int seekAndWrite(unixFile *id, const void *pBuf, int cnt){ int got; i64 newOffset; -#ifdef USE_PREAD + TIMER_START; +#if defined(USE_PREAD) got = pwrite(id->h, pBuf, cnt, id->offset); +#elif defined(USE_PREAD64) + got = pwrite64(id->h, pBuf, cnt, id->offset); #else newOffset = lseek(id->h, id->offset, SEEK_SET); if( newOffset!=id->offset ){ @@ -1057,6 +1054,8 @@ static int seekAndWrite(unixFile *id, co } got = write(id->h, pBuf, cnt); #endif + TIMER_END; + OSTRACE5("WRITE %-3d %5d %7lld %d\n", id->h, got, id->offset, TIMER_ELAPSED); if( got>0 ){ id->offset += got; } @@ -1072,15 +1071,10 @@ static int unixWrite(OsFile *id, const v int wrote = 0; assert( id ); assert( amt>0 ); - TIMER_START; while( amt>0 && (wrote = seekAndWrite((unixFile*)id, pBuf, amt))>0 ){ amt -= wrote; pBuf = &((char*)pBuf)[wrote]; } - TIMER_END; - TRACE5("WRITE %-3d %5d %7d %d\n", ((unixFile*)id)->h, wrote, - last_page, TIMER_ELAPSED); - SEEK(0); SimulateIOError(( wrote=(-1), amt=1 )); SimulateDiskfullError(( wrote=0, amt=1 )); if( amt>0 ){ @@ -1098,7 +1092,6 @@ static int unixSeek(OsFile *id, i64 offs */ static int unixSeek(OsFile *id, i64 offset){ assert( id ); - SEEK(offset/1024 + 1); #ifdef SQLITE_TEST if( offset ) SimulateDiskfullError(return SQLITE_FULL); #endif @@ -1212,14 +1205,14 @@ static int unixSync(OsFile *id, int data int rc; unixFile *pFile = (unixFile*)id; assert( pFile ); - TRACE2("SYNC %-3d\n", pFile->h); + OSTRACE2("SYNC %-3d\n", pFile->h); rc = full_fsync(pFile->h, pFile->fullSync, dataOnly); SimulateIOError( rc=1 ); if( rc ){ return SQLITE_IOERR_FSYNC; } if( pFile->dirfd>=0 ){ - TRACE4("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd, + OSTRACE4("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd, HAVE_FULLFSYNC, pFile->fullSync); #ifndef SQLITE_DISABLE_DIRSYNC /* The directory sync is only attempted if full_fsync is @@ -1257,7 +1250,7 @@ int sqlite3UnixSyncDirectory(const char int fd; int r; fd = open(zDirname, O_RDONLY|O_BINARY, 0); - TRACE3("DIRSYNC %-3d (%s)\n", fd, zDirname); + OSTRACE3("DIRSYNC %-3d (%s)\n", fd, zDirname); if( fd<0 ){ return SQLITE_CANTOPEN; } @@ -1336,7 +1329,7 @@ static int unixCheckReservedLock(OsFile } sqlite3OsLeaveMutex(); - TRACE3("TEST WR-LOCK %d %d\n", pFile->h, r); + OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r); return r; } @@ -1411,7 +1404,7 @@ static int unixLock(OsFile *id, int lock int s; assert( pFile ); - TRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h, + OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h, locktypeName(locktype), locktypeName(pFile->locktype), locktypeName(pLock->locktype), pLock->cnt , getpid()); @@ -1420,7 +1413,7 @@ static int unixLock(OsFile *id, int lock ** sqlite3OsEnterMutex() hasn't been called yet. */ if( pFile->locktype>=locktype ){ - TRACE3("LOCK %d %s ok (already held)\n", pFile->h, + OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h, locktypeName(locktype)); return SQLITE_OK; } @@ -1483,7 +1476,7 @@ static int unixLock(OsFile *id, int lock lock.l_type = (locktype==SHARED_LOCK?F_RDLCK:F_WRLCK); lock.l_start = PENDING_BYTE; s = fcntl(pFile->h, F_SETLK, &lock); - if( s ){ + if( s==(-1) ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; goto end_lock; } @@ -1510,7 +1503,7 @@ static int unixLock(OsFile *id, int lock rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ goto end_lock; } - if( s ){ + if( s==(-1) ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; }else{ pFile->locktype = SHARED_LOCK; @@ -1540,7 +1533,7 @@ static int unixLock(OsFile *id, int lock assert(0); } s = fcntl(pFile->h, F_SETLK, &lock); - if( s ){ + if( s==(-1) ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; } } @@ -1555,7 +1548,7 @@ end_lock: end_lock: sqlite3OsLeaveMutex(); - TRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), + OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), rc==SQLITE_OK ? "ok" : "failed"); return rc; } @@ -1574,7 +1567,7 @@ static int unixUnlock(OsFile *id, int lo unixFile *pFile = (unixFile*)id; assert( pFile ); - TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype, + OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype, pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); assert( locktype<=SHARED_LOCK ); @@ -1594,7 +1587,7 @@ static int unixUnlock(OsFile *id, int lo lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; - if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){ + if( fcntl(pFile->h, F_SETLK, &lock)==(-1) ){ /* This should never happen */ rc = SQLITE_IOERR_RDLOCK; } @@ -1603,7 +1596,7 @@ static int unixUnlock(OsFile *id, int lo lock.l_whence = SEEK_SET; lock.l_start = PENDING_BYTE; lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE ); - if( fcntl(pFile->h, F_SETLK, &lock)==0 ){ + if( fcntl(pFile->h, F_SETLK, &lock)!=(-1) ){ pLock->locktype = SHARED_LOCK; }else{ rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ @@ -1621,7 +1614,7 @@ static int unixUnlock(OsFile *id, int lo lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = lock.l_len = 0L; - if( fcntl(pFile->h, F_SETLK, &lock)==0 ){ + if( fcntl(pFile->h, F_SETLK, &lock)!=(-1) ){ pLock->locktype = NO_LOCK; }else{ rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ @@ -1687,7 +1680,7 @@ static int unixClose(OsFile **pId){ sqlite3OsLeaveMutex(); id->isOpen = 0; - TRACE2("CLOSE %-3d\n", id->h); + OSTRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); sqlite3ThreadSafeFree(id); *pId = 0; @@ -1734,11 +1727,11 @@ static int _AFPFSSetLock(const char *pat pb.offset = offset; pb.length = length; pb.fd = fd; - TRACE5("AFPLOCK setting lock %s for %d in range %llx:%llx\n", + OSTRACE5("AFPLOCK setting lock %s for %d in range %llx:%llx\n", (setLockFlag?"ON":"OFF"), fd, offset, length); err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0); if ( err==-1 ) { - TRACE4("AFPLOCK failed to fsctl() '%s' %d %s\n", path, errno, + OSTRACE4("AFPLOCK failed to fsctl() '%s' %d %s\n", path, errno, strerror(errno)); return 1; // error } else { @@ -1778,7 +1771,7 @@ static int afpUnixCheckReservedLock(OsFi _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1, 0); } } - TRACE3("TEST WR-LOCK %d %d\n", pFile->h, r); + OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r); return r; } @@ -1793,14 +1786,14 @@ static int afpUnixLock(OsFile *id, int l int gotPendingLock = 0; assert( pFile ); - TRACE5("LOCK %d %s was %s pid=%d\n", pFile->h, + OSTRACE5("LOCK %d %s was %s pid=%d\n", pFile->h, locktypeName(locktype), locktypeName(pFile->locktype), getpid()); /* If there is already a lock of this type or more restrictive on the ** OsFile, do nothing. Don't use the afp_end_lock: exit path, as ** sqlite3OsEnterMutex() hasn't been called yet. */ if( pFile->locktype>=locktype ){ - TRACE3("LOCK %d %s ok (already held)\n", pFile->h, + OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h, locktypeName(locktype)); return SQLITE_OK; } @@ -1907,7 +1900,7 @@ afp_end_lock: afp_end_lock: sqlite3OsLeaveMutex(); - TRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), + OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), rc==SQLITE_OK ? "ok" : "failed"); return rc; } @@ -1926,7 +1919,7 @@ static int afpUnixUnlock(OsFile *id, int afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; assert( pFile ); - TRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype, + OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype, pFile->locktype, getpid()); assert( locktype<=SHARED_LOCK ); @@ -2003,7 +1996,7 @@ static int afpUnixClose(OsFile **pId) { id->dirfd = -1; close(id->h); id->isOpen = 0; - TRACE2("CLOSE %-3d\n", id->h); + OSTRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); sqlite3ThreadSafeFree(id); *pId = 0; @@ -2099,7 +2092,7 @@ static int flockUnixClose(OsFile **pId) close(id->h); sqlite3OsLeaveMutex(); id->isOpen = 0; - TRACE2("CLOSE %-3d\n", id->h); + OSTRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); sqlite3ThreadSafeFree(id); *pId = 0; @@ -2218,7 +2211,7 @@ static int dotlockUnixClose(OsFile **pId sqlite3OsLeaveMutex(); id->isOpen = 0; - TRACE2("CLOSE %-3d\n", id->h); + OSTRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); sqlite3ThreadSafeFree(id); *pId = 0; @@ -2260,7 +2253,7 @@ static int nolockUnixClose(OsFile **pId) sqlite3OsLeaveMutex(); id->isOpen = 0; - TRACE2("CLOSE %-3d\n", id->h); + OSTRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); sqlite3ThreadSafeFree(id); *pId = 0; @@ -2342,6 +2335,20 @@ static int unixLockState(OsFile *id){ } /* +** Return the sector size in bytes of the underlying block device for +** the specified file. This is almost always 512 bytes, but may be +** larger for some devices. +** +** SQLite code assumes this function cannot fail. It also assumes that +** if two files are created in the same file-system directory (i.e. +** a database and it's journal file) that the sector size will be the +** same for both. +*/ +static int unixSectorSize(OsFile *id){ + return SQLITE_DEFAULT_SECTOR_SIZE; +} + +/* ** This vector defines all the methods that can operate on an OsFile ** for unix. */ @@ -2360,6 +2367,7 @@ static const IoMethod sqlite3UnixIoMetho unixUnlock, unixLockState, unixCheckReservedLock, + unixSectorSize, }; #ifdef SQLITE_ENABLE_LOCKING_STYLE @@ -2382,6 +2390,7 @@ static const IoMethod sqlite3AFPLockingU afpUnixUnlock, unixLockState, afpUnixCheckReservedLock, + unixSectorSize, }; /* @@ -2403,6 +2412,7 @@ static const IoMethod sqlite3FlockLockin flockUnixUnlock, unixLockState, flockUnixCheckReservedLock, + unixSectorSize, }; /* @@ -2424,6 +2434,7 @@ static const IoMethod sqlite3DotlockLock dotlockUnixUnlock, unixLockState, dotlockUnixCheckReservedLock, + unixSectorSize, }; /* @@ -2445,6 +2456,7 @@ static const IoMethod sqlite3NolockLocki nolockUnixUnlock, unixLockState, nolockUnixCheckReservedLock, + unixSectorSize, }; #endif /* SQLITE_ENABLE_LOCKING_STYLE */ @@ -2472,6 +2484,7 @@ static int allocateUnixFile( unixFile f; int rc; + memset(&f, 0, sizeof(f)); lockingStyle = sqlite3DetectLockingStyle(zFilename, h); if ( lockingStyle == posixLockingStyle ) { sqlite3OsEnterMutex(); @@ -2491,9 +2504,6 @@ static int allocateUnixFile( unlink(zFilename); } f.dirfd = -1; - f.fullSync = 0; - f.locktype = 0; - f.offset = 0; f.h = h; SET_THREADID(&f); pNew = sqlite3ThreadSafeMalloc( sizeof(unixFile) ); @@ -2560,6 +2570,7 @@ static int allocateUnixFile( unixFile f; int rc; + memset(&f, 0, sizeof(f)); sqlite3OsEnterMutex(); rc = findLockInfo(h, &f.pLock, &f.pOpen); sqlite3OsLeaveMutex(); @@ -2570,11 +2581,8 @@ static int allocateUnixFile( close(h); return SQLITE_NOMEM; } - TRACE3("OPEN %-3d %s\n", h, zFilename); + OSTRACE3("OPEN %-3d %s\n", h, zFilename); f.dirfd = -1; - f.fullSync = 0; - f.locktype = 0; - f.offset = 0; f.h = h; SET_THREADID(&f); pNew = sqlite3ThreadSafeMalloc( sizeof(unixFile) ); @@ -2899,8 +2907,7 @@ int sqlite3UnixCurrentTime(double *prNow *prNow = t/86400.0 + 2440587.5; #else struct timeval sNow; - struct timezone sTz; /* Not used */ - gettimeofday(&sNow, &sTz); + gettimeofday(&sNow, 0); *prNow = 2440587.5 + sNow.tv_sec/86400.0 + sNow.tv_usec/86400000000.0; #endif #ifdef SQLITE_TEST ============================================================ --- sqlite/os_win.c 8736cf3a49fd651a6538857480f302807d57814c +++ sqlite/os_win.c c9a99524d6b2bdec636264cad1b67553925e3309 @@ -596,6 +596,7 @@ int sqlite3WinDelete(const char *zFilena if( zConverted==0 ){ return SQLITE_NOMEM; } + SimulateIOError(return SQLITE_IOERR_DELETE); if( isNT() ){ do{ rc = DeleteFileW(zConverted); @@ -612,7 +613,7 @@ int sqlite3WinDelete(const char *zFilena #endif } sqliteFree(zConverted); - TRACE2("DELETE \"%s\"\n", zFilename); + OSTRACE2("DELETE \"%s\"\n", zFilename); return rc!=0 ? SQLITE_OK : SQLITE_IOERR; } @@ -738,7 +739,7 @@ int sqlite3WinOpenReadWrite( #if OS_WINCE f.zDeleteOnClose = 0; #endif - TRACE3("OPEN R/W %d \"%s\"\n", h, zFilename); + OSTRACE3("OPEN R/W %d \"%s\"\n", h, zFilename); return allocateWinFile(&f, pId); } @@ -819,7 +820,7 @@ int sqlite3WinOpenExclusive(const char * return SQLITE_CANTOPEN; } f.h = h; - TRACE3("OPEN EX %d \"%s\"\n", h, zFilename); + OSTRACE3("OPEN EX %d \"%s\"\n", h, zFilename); return allocateWinFile(&f, pId); } @@ -870,7 +871,7 @@ int sqlite3WinOpenReadOnly(const char *z f.zDeleteOnClose = 0; f.hMutex = NULL; #endif - TRACE3("OPEN RO %d \"%s\"\n", h, zFilename); + OSTRACE3("OPEN RO %d \"%s\"\n", h, zFilename); return allocateWinFile(&f, pId); } @@ -898,13 +899,6 @@ static int winOpenDirectory( } /* -** 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. -*/ -char *sqlite3_temp_directory = 0; - -/* ** Create a temporary file name in zBuf. zBuf must be big enough to ** hold at least SQLITE_TEMPNAME_SIZE characters. */ @@ -955,7 +949,7 @@ int sqlite3WinTempFileName(char *zBuf){ zBuf[j] = 0; if( !sqlite3OsFileExists(zBuf) ) break; } - TRACE2("TEMP FILENAME: %s\n", zBuf); + OSTRACE2("TEMP FILENAME: %s\n", zBuf); return SQLITE_OK; } @@ -975,7 +969,7 @@ static int winClose(OsFile **pId){ int rc = 1; if( pId && (pFile = (winFile*)*pId)!=0 ){ int rc, cnt = 0; - TRACE2("CLOSE %d\n", pFile->h); + OSTRACE2("CLOSE %d\n", pFile->h); do{ rc = CloseHandle(pFile->h); }while( rc==0 && cnt++ < MX_CLOSE_ATTEMPT && (Sleep(100), 1) ); @@ -1002,7 +996,7 @@ static int winRead(OsFile *id, void *pBu DWORD got; assert( id!=0 ); SimulateIOError(return SQLITE_IOERR_READ); - TRACE3("READ %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); + OSTRACE3("READ %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); if( !ReadFile(((winFile*)id)->h, pBuf, amt, &got, 0) ){ return SQLITE_IOERR_READ; } @@ -1024,7 +1018,7 @@ static int winWrite(OsFile *id, const vo assert( id!=0 ); SimulateIOError(return SQLITE_IOERR_READ); SimulateDiskfullError(return SQLITE_FULL); - TRACE3("WRITE %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); + OSTRACE3("WRITE %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); assert( amt>0 ); while( amt>0 && (rc = WriteFile(((winFile*)id)->h, pBuf, amt, &wrote, 0))!=0 && wrote>0 ){ @@ -1055,9 +1049,8 @@ static int winSeek(OsFile *id, i64 offse #ifdef SQLITE_TEST if( offset ) SimulateDiskfullError(return SQLITE_FULL); #endif - SEEK(offset/1024 + 1); rc = SetFilePointer(((winFile*)id)->h, lowerBits, &upperBits, FILE_BEGIN); - TRACE3("SEEK %d %lld\n", ((winFile*)id)->h, offset); + OSTRACE3("SEEK %d %lld\n", ((winFile*)id)->h, offset); if( rc==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR ){ return SQLITE_FULL; } @@ -1069,7 +1062,7 @@ static int winSync(OsFile *id, int dataO */ static int winSync(OsFile *id, int dataOnly){ assert( id!=0 ); - TRACE3("SYNC %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); + OSTRACE3("SYNC %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); if( FlushFileBuffers(((winFile*)id)->h) ){ return SQLITE_OK; }else{ @@ -1092,7 +1085,7 @@ static int winTruncate(OsFile *id, i64 n static int winTruncate(OsFile *id, i64 nByte){ LONG upperBits = nByte>>32; assert( id!=0 ); - TRACE3("TRUNCATE %d %lld\n", ((winFile*)id)->h, nByte); + OSTRACE3("TRUNCATE %d %lld\n", ((winFile*)id)->h, nByte); SimulateIOError(return SQLITE_IOERR_TRUNCATE); SetFilePointer(((winFile*)id)->h, nByte, &upperBits, FILE_BEGIN); SetEndOfFile(((winFile*)id)->h); @@ -1220,7 +1213,7 @@ static int winLock(OsFile *id, int lockt winFile *pFile = (winFile*)id; assert( pFile!=0 ); - TRACE5("LOCK %d %d was %d(%d)\n", + OSTRACE5("LOCK %d %d was %d(%d)\n", pFile->h, locktype, pFile->locktype, pFile->sharedLockByte); /* If there is already a lock of this type or more restrictive on the @@ -1250,7 +1243,7 @@ static int winLock(OsFile *id, int lockt /* Try 3 times to get the pending lock. The pending lock might be ** held by another reader process who will release it momentarily. */ - TRACE2("could not get a PENDING lock. cnt=%d\n", cnt); + OSTRACE2("could not get a PENDING lock. cnt=%d\n", cnt); Sleep(1); } gotPendingLock = res; @@ -1288,12 +1281,12 @@ static int winLock(OsFile *id, int lockt if( locktype==EXCLUSIVE_LOCK && res ){ assert( pFile->locktype>=SHARED_LOCK ); res = unlockReadLock(pFile); - TRACE2("unreadlock = %d\n", res); + OSTRACE2("unreadlock = %d\n", res); res = LockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); if( res ){ newLocktype = EXCLUSIVE_LOCK; }else{ - TRACE2("error-code = %d\n", GetLastError()); + OSTRACE2("error-code = %d\n", GetLastError()); } } @@ -1310,7 +1303,7 @@ static int winLock(OsFile *id, int lockt if( res ){ rc = SQLITE_OK; }else{ - TRACE4("LOCK FAILED %d trying for %d but got %d\n", pFile->h, + OSTRACE4("LOCK FAILED %d trying for %d but got %d\n", pFile->h, locktype, newLocktype); rc = SQLITE_BUSY; } @@ -1329,14 +1322,14 @@ static int winCheckReservedLock(OsFile * assert( pFile!=0 ); if( pFile->locktype>=RESERVED_LOCK ){ rc = 1; - TRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc); + OSTRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc); }else{ rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); if( rc ){ UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); } rc = !rc; - TRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc); + OSTRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc); } return rc; } @@ -1358,7 +1351,7 @@ static int winUnlock(OsFile *id, int loc winFile *pFile = (winFile*)id; assert( pFile!=0 ); assert( locktype<=SHARED_LOCK ); - TRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype, + OSTRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype, pFile->locktype, pFile->sharedLockByte); type = pFile->locktype; if( type>=EXCLUSIVE_LOCK ){ @@ -1455,6 +1448,20 @@ static int winLockState(OsFile *id){ } /* +** Return the sector size in bytes of the underlying block device for +** the specified file. This is almost always 512 bytes, but may be +** larger for some devices. +** +** SQLite code assumes this function cannot fail. It also assumes that +** if two files are created in the same file-system directory (i.e. +** a database and it's journal file) that the sector size will be the +** same for both. +*/ +static int winSectorSize(OsFile *id){ + return SQLITE_DEFAULT_SECTOR_SIZE; +} + +/* ** This vector defines all the methods that can operate on an OsFile ** for win32. */ @@ -1473,6 +1480,7 @@ static const IoMethod sqlite3WinIoMethod winUnlock, winLockState, winCheckReservedLock, + winSectorSize, }; /* ============================================================ --- sqlite/pager.c d6ad66eb119602cb2e6a097f8f635372ba677d23 +++ sqlite/pager.c 655073dd7b32eade2f10f69e1d51fece380d45e1 @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.282 2007/01/05 02:00:47 drh Exp $ +** @(#) $Id: pager.c,v 1.326 2007/04/09 11:20:54 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -32,21 +32,21 @@ */ #if 0 #define sqlite3DebugPrintf printf -#define TRACE1(X) sqlite3DebugPrintf(X) -#define TRACE2(X,Y) sqlite3DebugPrintf(X,Y) -#define TRACE3(X,Y,Z) sqlite3DebugPrintf(X,Y,Z) -#define TRACE4(X,Y,Z,W) sqlite3DebugPrintf(X,Y,Z,W) -#define TRACE5(X,Y,Z,W,V) sqlite3DebugPrintf(X,Y,Z,W,V) +#define PAGERTRACE1(X) sqlite3DebugPrintf(X) +#define PAGERTRACE2(X,Y) sqlite3DebugPrintf(X,Y) +#define PAGERTRACE3(X,Y,Z) sqlite3DebugPrintf(X,Y,Z) +#define PAGERTRACE4(X,Y,Z,W) sqlite3DebugPrintf(X,Y,Z,W) +#define PAGERTRACE5(X,Y,Z,W,V) sqlite3DebugPrintf(X,Y,Z,W,V) #else -#define TRACE1(X) -#define TRACE2(X,Y) -#define TRACE3(X,Y,Z) -#define TRACE4(X,Y,Z,W) -#define TRACE5(X,Y,Z,W,V) +#define PAGERTRACE1(X) +#define PAGERTRACE2(X,Y) +#define PAGERTRACE3(X,Y,Z) +#define PAGERTRACE4(X,Y,Z,W) +#define PAGERTRACE5(X,Y,Z,W,V) #endif /* -** The following two macros are used within the TRACEX() macros above +** The following two macros are used within the PAGERTRACEX() macros above ** to print out file-descriptors. ** ** PAGERID() takes a pointer to a Pager struct as it's argument. The @@ -85,21 +85,24 @@ ** PAGER_SYNCED The pager moves to this state from PAGER_EXCLUSIVE ** after all dirty pages have been written to the ** database file and the file has been synced to -** disk. All that remains to do is to remove the -** journal file and the transaction will be -** committed. +** disk. All that remains to do is to remove or +** truncate the journal file and the transaction +** will be committed. ** ** The page cache comes up in PAGER_UNLOCK. The first time a -** sqlite3pager_get() occurs, the state transitions to PAGER_SHARED. +** sqlite3PagerGet() occurs, the state transitions to PAGER_SHARED. ** After all pages have been released using sqlite_page_unref(), ** the state transitions back to PAGER_UNLOCK. The first time -** that sqlite3pager_write() is called, the state transitions to -** PAGER_RESERVED. (Note that sqlite_page_write() can only be +** that sqlite3PagerWrite() is called, the state transitions to +** PAGER_RESERVED. (Note that sqlite3PagerWrite() can only be ** called on an outstanding page which means that the pager must ** be in PAGER_SHARED before it transitions to PAGER_RESERVED.) -** The transition to PAGER_EXCLUSIVE occurs when before any changes -** are made to the database file. After an sqlite3pager_rollback() -** or sqlite_pager_commit(), the state goes back to PAGER_SHARED. +** PAGER_RESERVED means that there is an open rollback journal. +** The transition to PAGER_EXCLUSIVE occurs before any changes +** are made to the database file, though writes to the rollback +** journal occurs with just PAGER_RESERVED. After an sqlite3PagerRollback() +** or sqlite3PagerCommitPhaseTwo(), the state can go back to PAGER_SHARED, +** or it can stay at PAGER_EXCLUSIVE if we are in exclusive access mode. */ #define PAGER_UNLOCK 0 #define PAGER_SHARED 1 /* same as SHARED_LOCK */ @@ -135,8 +138,8 @@ ** This header is only visible to this pager module. The client ** code that calls pager sees only the data that follows the header. ** -** Client code should call sqlite3pager_write() on a page prior to making -** any modifications to that page. The first time sqlite3pager_write() +** Client code should call sqlite3PagerWrite() on a page prior to making +** any modifications to that page. The first time sqlite3PagerWrite() ** is called, the original page contents are written into the rollback ** journal and PgHdr.inJournal and PgHdr.needSync are set. Later, once ** the journal page has made it onto the disk surface, PgHdr.needSync @@ -144,7 +147,7 @@ ** database file until the journal pages has been synced to disk and the ** PgHdr.needSync has been cleared. ** -** The PgHdr.dirty flag is set when sqlite3pager_write() is called and +** The PgHdr.dirty flag is set when sqlite3PagerWrite() is called and ** is cleared again when the page content is written back to the original ** database file. */ @@ -155,12 +158,10 @@ struct PgHdr { PgHdr *pNextHash, *pPrevHash; /* Hash collision chain for PgHdr.pgno */ PgHdr *pNextFree, *pPrevFree; /* Freelist of pages where nRef==0 */ PgHdr *pNextAll; /* A list of all pages */ - PgHdr *pNextStmt, *pPrevStmt; /* List of pages in the statement journal */ u8 inJournal; /* TRUE if has been written to journal */ - u8 inStmt; /* TRUE if in the statement subjournal */ u8 dirty; /* TRUE if we need to write back changes */ u8 needSync; /* Sync journal before writing this page */ - u8 alwaysRollback; /* Disable dont_rollback() for this page */ + u8 alwaysRollback; /* Disable DontRollback() for this page */ short int nRef; /* Number of users of this page */ PgHdr *pDirty, *pPrevDirty; /* Dirty pages */ u32 notUsed; /* Buffer space */ @@ -186,6 +187,8 @@ struct PgHistory { struct PgHistory { u8 *pOrig; /* Original page text. Restore to this on a full rollback */ u8 *pStmt; /* Text as it was at the beginning of the current statement */ + PgHdr *pNextStmt, *pPrevStmt; /* List of pages in the statement journal */ + u8 inStmt; /* TRUE if in the statement subjournal */ }; /* @@ -212,12 +215,12 @@ struct PgHistory { /* ** A open page cache is an instance of the following structure. ** -** Pager.errCode may be set to SQLITE_IOERR, SQLITE_CORRUPT, SQLITE_PROTOCOL +** Pager.errCode may be set to SQLITE_IOERR, SQLITE_CORRUPT, or ** 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() +** SQLITE_FULL does not affect the sqlite3PagerGet() and sqlite3PagerLookup() ** APIs, they may still be used successfully. */ struct Pager { @@ -236,9 +239,12 @@ struct Pager { 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 */ + u8 alwaysRollback; /* Disable DontRollback() for all pages */ u8 memDb; /* True to inhibit all file I/O */ u8 setMaster; /* True if a m-j name has been written to jrnl */ + u8 doNotSync; /* Boolean. While true, do not spill the cache */ + u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */ + u8 changeCountDone; /* Set after incrementing the change-counter */ int errCode; /* One of several kinds of errors */ int dbSize; /* Number of pages in the file */ int origDbSize; /* dbSize before the current change */ @@ -272,18 +278,22 @@ struct Pager { i64 stmtJSize; /* Size of journal at stmt_begin() */ int sectorSize; /* Assumed sector size during rollback */ #ifdef SQLITE_TEST - int nHit, nMiss, nOvfl; /* Cache hits, missing, and LRU overflows */ - int nRead,nWrite; /* Database pages read/written */ + int nHit, nMiss; /* Cache hits and missing */ + int nRead, nWrite; /* Database pages read/written */ #endif - void (*xDestructor)(void*,int); /* Call this routine when freeing pages */ - void (*xReiniter)(void*,int); /* Call this routine when reloading pages */ + void (*xDestructor)(DbPage*,int); /* Call this routine when freeing pages */ + void (*xReiniter)(DbPage*,int); /* Call this routine when reloading pages */ +#ifdef SQLITE_HAS_CODEC void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ void *pCodecArg; /* First argument to xCodec() */ +#endif int nHash; /* Size of the pager hash table */ PgHdr **aHash; /* Hash table to map page number to PgHdr */ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT Pager *pNext; /* Linked list of pagers in this thread */ #endif + char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */ + u32 iChangeCount; /* Db change-counter for which cache is valid */ }; /* @@ -349,13 +359,6 @@ static const unsigned char aJournalMagic #endif /* -** The default size of a disk sector -*/ -#ifndef PAGER_SECTOR_SIZE -# define PAGER_SECTOR_SIZE 512 -#endif - -/* ** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is ** reserved for working around a windows/posix incompatibility). It is ** used in the journal to signify that the remainder of the journal file @@ -373,7 +376,7 @@ static const unsigned char aJournalMagic /* ** Enable reference count tracking (for debugging) here: */ -#ifdef SQLITE_TEST +#ifdef SQLITE_DEBUG int pager3_refinfo_enable = 0; static void pager_refinfo(PgHdr *p){ static int cnt = 0; @@ -389,6 +392,21 @@ static const unsigned char aJournalMagic # define REFINFO(X) #endif +/* +** Return true if page *pPg has already been written to the statement +** journal (or statement snapshot has been created, if *pPg is part +** of an in-memory database). +*/ +static int pageInStatement(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + if( MEMDB ){ + return PGHDR_TO_HIST(pPg, pPager)->inStmt; + }else{ + Pgno pgno = pPg->pgno; + u8 *a = pPager->aInStmt; + return (a && (int)pgno<=pPager->stmtSize && (a[pgno/8] & (1<<(pgno&7)))); + } +} /* ** Change the size of the pager hash table to N. N must be a power @@ -474,18 +492,17 @@ static u32 retrieve32bits(PgHdr *p, int ** 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, +** If the second argument is SQLITE_IOERR, SQLITE_CORRUPT, or SQLITE_FULL ** 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){ int rc2 = rc & 0xff; assert( pPager->errCode==SQLITE_FULL || pPager->errCode==SQLITE_OK ); - if( + if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR || - rc2==SQLITE_CORRUPT || - rc2==SQLITE_PROTOCOL + rc2==SQLITE_CORRUPT ){ pPager->errCode = rc; } @@ -634,14 +651,16 @@ static int writeJournalHdr(Pager *pPager */ static int writeJournalHdr(Pager *pPager){ char zHeader[sizeof(aJournalMagic)+16]; + int rc; - int rc = seekJournalHdr(pPager); + if( pPager->stmtHdrOff==0 ){ + pPager->stmtHdrOff = pPager->journalOff; + } + + rc = seekJournalHdr(pPager); if( rc ) return rc; pPager->journalHdr = pPager->journalOff; - if( pPager->stmtHdrOff==0 ){ - pPager->stmtHdrOff = pPager->journalHdr; - } pPager->journalOff += JOURNAL_HDR_SZ(pPager); /* FIX ME: @@ -662,12 +681,14 @@ static int writeJournalHdr(Pager *pPager put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbSize); /* The assumed sector size for this process */ put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize); + IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, sizeof(zHeader))) rc = sqlite3OsWrite(pPager->jfd, zHeader, sizeof(zHeader)); /* The journal header has been written successfully. Seek the journal ** file descriptor to the end of the journal header sector. */ if( rc==SQLITE_OK ){ + IOTRACE(("JTAIL %p %lld\n", pPager, pPager->journalOff-1)) rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff-1); if( rc==SQLITE_OK ){ rc = sqlite3OsWrite(pPager->jfd, "\000", 1); @@ -802,39 +823,24 @@ static int writeMasterJournal(Pager *pPa ** statement journal. ** ** The Pager keeps a separate list of pages that are currently in -** the statement journal. This helps the sqlite3pager_stmt_commit() +** the statement journal. This helps the sqlite3PagerStmtCommit() ** routine run MUCH faster for the common case where there are many ** pages in memory but only a few are in the statement journal. */ static void page_add_to_stmt_list(PgHdr *pPg){ Pager *pPager = pPg->pPager; - if( pPg->inStmt ) return; - assert( pPg->pPrevStmt==0 && pPg->pNextStmt==0 ); - pPg->pPrevStmt = 0; - if( pPager->pStmt ){ - pPager->pStmt->pPrevStmt = pPg; + PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); + assert( MEMDB ); + if( !pHist->inStmt ){ + assert( pHist->pPrevStmt==0 && pHist->pNextStmt==0 ); + if( pPager->pStmt ){ + PGHDR_TO_HIST(pPager->pStmt, pPager)->pPrevStmt = pPg; + } + pHist->pNextStmt = pPager->pStmt; + pPager->pStmt = pPg; + pHist->inStmt = 1; } - pPg->pNextStmt = pPager->pStmt; - pPager->pStmt = pPg; - pPg->inStmt = 1; } -static void page_remove_from_stmt_list(PgHdr *pPg){ - if( !pPg->inStmt ) return; - if( pPg->pPrevStmt ){ - assert( pPg->pPrevStmt->pNextStmt==pPg ); - pPg->pPrevStmt->pNextStmt = pPg->pNextStmt; - }else{ - assert( pPg->pPager->pStmt==pPg ); - pPg->pPager->pStmt = pPg->pNextStmt; - } - if( pPg->pNextStmt ){ - assert( pPg->pNextStmt->pPrevStmt==pPg ); - pPg->pNextStmt->pPrevStmt = pPg->pPrevStmt; - } - pPg->pNextStmt = 0; - pPg->pPrevStmt = 0; - pPg->inStmt = 0; -} /* ** Find a page in the hash table given its page number. Return @@ -852,23 +858,38 @@ static PgHdr *pager_lookup(Pager *pPager /* ** Unlock the database file. -** -** Once all locks have been removed from the database file, other -** processes or threads might change the file. So make sure all of -** our internal cache is invalidated. */ static void pager_unlock(Pager *pPager){ - if( !MEMDB ){ - sqlite3OsUnlock(pPager->fd, NO_LOCK); - pPager->dbSize = -1; + if( !pPager->exclusiveMode ){ + if( !MEMDB ){ + sqlite3OsUnlock(pPager->fd, NO_LOCK); + pPager->dbSize = -1; + IOTRACE(("UNLOCK %p\n", pPager)) + } + pPager->state = PAGER_UNLOCK; + pPager->changeCountDone = 0; } - pPager->state = PAGER_UNLOCK; - assert( pPager->pAll==0 ); } +/* +** Execute a rollback if a transaction is active and unlock the +** database file. This is a no-op if the pager has already entered +** the error-state. +*/ +static void pagerUnlockAndRollback(Pager *p){ + if( p->errCode ) return; + assert( p->state>=PAGER_RESERVED || p->journalOpen==0 ); + if( p->state>=PAGER_RESERVED ){ + sqlite3PagerRollback(p); + } + pager_unlock(p); + assert( p->errCode || !p->journalOpen || (p->exclusiveMode&&!p->journalOff) ); + assert( p->errCode || !p->stmtOpen || p->exclusiveMode ); +} + /* -** Unlock the database and clear the in-memory cache. This routine +** Clear the in-memory cache. This routine ** sets the state of the pager back to what it was when it was first ** opened. Any outstanding pages are invalidated and subsequent attempts ** to access those pages will likely result in a coredump. @@ -880,6 +901,7 @@ static void pager_reset(Pager *pPager){ pNext = pPg->pNextAll; sqliteFree(pPg); } + pPager->pStmt = 0; pPager->pFirst = 0; pPager->pFirstSynced = 0; pPager->pLast = 0; @@ -888,46 +910,59 @@ static void pager_reset(Pager *pPager){ sqliteFree(pPager->aHash); pPager->nPage = 0; pPager->aHash = 0; - if( pPager->state>=PAGER_RESERVED ){ - sqlite3pager_rollback(pPager); - } - pager_unlock(pPager); pPager->nRef = 0; - assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) ); } /* +** This routine ends a transaction. A transaction is ended by either +** a COMMIT or a ROLLBACK. +** ** When this routine is called, the pager has the journal file open and -** a RESERVED or EXCLUSIVE lock on the database. This routine releases -** the database lock and acquires a SHARED lock in its place. The journal -** file is deleted and closed. +** a RESERVED or EXCLUSIVE lock on the database. This routine will release +** the database lock and acquires a SHARED lock in its place if that is +** the appropriate thing to do. Release locks usually is appropriate, +** unless we are in exclusive access mode or unless this is a +** COMMIT AND BEGIN or ROLLBACK AND BEGIN operation. ** +** The journal file is either deleted or truncated. +** ** TODO: Consider keeping the journal file open for temporary databases. ** This might give a performance improvement on windows where opening ** a file is an expensive operation. */ -static int pager_unwritelock(Pager *pPager){ +static int pager_end_transaction(Pager *pPager){ PgHdr *pPg; - int rc; + int rc = SQLITE_OK; + int rc2 = SQLITE_OK; assert( !MEMDB ); if( pPager->statestmtOpen ){ + sqlite3PagerStmtCommit(pPager); + if( pPager->stmtOpen && !pPager->exclusiveMode ){ sqlite3OsClose(&pPager->stfd); pPager->stmtOpen = 0; } if( pPager->journalOpen ){ - sqlite3OsClose(&pPager->jfd); - pPager->journalOpen = 0; - sqlite3OsDelete(pPager->zJournal); + if( pPager->exclusiveMode + && (rc = sqlite3OsTruncate(pPager->jfd, 0))==SQLITE_OK ){; + sqlite3OsSeek(pPager->jfd, 0); + pPager->journalOff = 0; + pPager->journalStarted = 0; + }else{ + sqlite3OsClose(&pPager->jfd); + pPager->journalOpen = 0; + if( rc==SQLITE_OK ){ + rc = sqlite3OsDelete(pPager->zJournal); + } + } sqliteFree( pPager->aInJournal ); pPager->aInJournal = 0; for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ pPg->inJournal = 0; pPg->dirty = 0; pPg->needSync = 0; + pPg->alwaysRollback = 0; #ifdef SQLITE_CHECK_PAGES pPg->pageHash = pager_pagehash(pPg); #endif @@ -939,14 +974,20 @@ static int pager_unwritelock(Pager *pPag assert( pPager->aInJournal==0 ); assert( pPager->dirtyCache==0 || pPager->useJournal==0 ); } - rc = sqlite3OsUnlock(pPager->fd, SHARED_LOCK); - pPager->state = PAGER_SHARED; + + if( !pPager->exclusiveMode ){ + rc2 = sqlite3OsUnlock(pPager->fd, SHARED_LOCK); + pPager->state = PAGER_SHARED; + }else if( pPager->state==PAGER_SYNCED ){ + pPager->state = PAGER_EXCLUSIVE; + } pPager->origDbSize = 0; pPager->setMaster = 0; pPager->needSync = 0; pPager->pFirstSynced = pPager->pFirst; pPager->dbSize = -1; - return rc; + + return (rc==SQLITE_OK?rc2:rc); } /* @@ -995,17 +1036,17 @@ static int pager_playback_one_page(Pager PgHdr *pPg; /* An existing page in the cache */ Pgno pgno; /* The page number of a page in journal */ u32 cksum; /* Checksum used for sanity checking */ - u8 aData[SQLITE_MAX_PAGE_SIZE]; /* Temp storage for a page */ + u8 *aData = (u8 *)pPager->pTmpSpace; /* Temp storage for a page */ /* useCksum should be true for the main journal and false for ** statement journals. Verify that this is always the case */ assert( jfd == (useCksum ? pPager->jfd : pPager->stfd) ); + assert( aData ); - rc = read32bits(jfd, &pgno); if( rc!=SQLITE_OK ) return rc; - rc = sqlite3OsRead(jfd, &aData, pPager->pageSize); + rc = sqlite3OsRead(jfd, aData, pPager->pageSize); if( rc!=SQLITE_OK ) return rc; pPager->journalOff += pPager->pageSize + 4; @@ -1053,7 +1094,7 @@ static int pager_playback_one_page(Pager */ pPg = pager_lookup(pPager, pgno); assert( pPager->state>=PAGER_EXCLUSIVE || pPg!=0 ); - TRACE3("PLAYBACK %d page %d\n", PAGERID(pPager), pgno); + PAGERTRACE3("PLAYBACK %d page %d\n", PAGERID(pPager), pgno); if( pPager->state>=PAGER_EXCLUSIVE && (pPg==0 || pPg->needSync==0) ){ rc = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize); if( rc==SQLITE_OK ){ @@ -1068,19 +1109,24 @@ static int pager_playback_one_page(Pager ** for page 1 which is held in use in order to keep the lock on the ** database active. However such a page may be rolled back as a result ** of an internal error resulting in an automatic call to - ** sqlite3pager_rollback(). + ** sqlite3PagerRollback(). */ void *pData; /* assert( pPg->nRef==0 || pPg->pgno==1 ); */ pData = PGHDR_TO_DATA(pPg); memcpy(pData, aData, pPager->pageSize); - if( pPager->xDestructor ){ /*** FIX ME: Should this be xReinit? ***/ - pPager->xDestructor(pData, pPager->pageSize); + if( pPager->xReiniter ){ + pPager->xReiniter(pPg, pPager->pageSize); } #ifdef SQLITE_CHECK_PAGES pPg->pageHash = pager_pagehash(pPg); #endif CODEC1(pPager, pData, pPg->pgno, 3); + + /* If this was page 1, then restore the value of Pager.iChangeCount */ + if( pgno==1 ){ + pPager->iChangeCount = retrieve32bits(pPg, 24); + } } return rc; } @@ -1107,6 +1153,7 @@ static int pager_delmaster(const char *z ** is running this routine also. Not that it makes too much difference. */ rc = sqlite3OsOpenReadOnly(zMaster, &master); + assert( rc!=SQLITE_OK || master ); if( rc!=SQLITE_OK ) goto delmaster_out; master_open = 1; rc = sqlite3OsFileSize(master, &nMasterJournal); @@ -1138,6 +1185,7 @@ static int pager_delmaster(const char *z int c; rc = sqlite3OsOpenReadOnly(zJournal, &journal); + assert( rc!=SQLITE_OK || journal ); if( rc!=SQLITE_OK ){ goto delmaster_out; } @@ -1159,7 +1207,7 @@ static int pager_delmaster(const char *z } } - sqlite3OsDelete(zMaster); + rc = sqlite3OsDelete(zMaster); delmaster_out: if( zMasterJournal ){ @@ -1171,6 +1219,7 @@ delmaster_out: return rc; } +#if 0 /* ** Make every page in the cache agree with what is on disk. In other words, ** reread the disk to reset the state of the cache. @@ -1184,14 +1233,14 @@ static int pager_reload_cache(Pager *pPa PgHdr *pPg; int rc = SQLITE_OK; for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ - char zBuf[SQLITE_MAX_PAGE_SIZE]; + char *zBuf = pPager->pTmpSpace; /* Temp storage for one page */ if( !pPg->dirty ) continue; if( (int)pPg->pgno <= pPager->origDbSize ){ rc = sqlite3OsSeek(pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1)); if( rc==SQLITE_OK ){ rc = sqlite3OsRead(pPager->fd, zBuf, pPager->pageSize); } - TRACE3("REFETCH %d page %d\n", PAGERID(pPager), pPg->pgno); + PAGERTRACE3("REFETCH %d page %d\n", PAGERID(pPager), pPg->pgno); if( rc ) break; CODEC1(pPager, zBuf, pPg->pgno, 2); }else{ @@ -1200,7 +1249,7 @@ static int pager_reload_cache(Pager *pPa if( pPg->nRef==0 || memcmp(zBuf, PGHDR_TO_DATA(pPg), pPager->pageSize) ){ memcpy(PGHDR_TO_DATA(pPg), zBuf, pPager->pageSize); if( pPager->xReiniter ){ - pPager->xReiniter(PGHDR_TO_DATA(pPg), pPager->pageSize); + pPager->xReiniter(pPg, pPager->pageSize); }else{ memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra); } @@ -1214,14 +1263,24 @@ static int pager_reload_cache(Pager *pPa pPager->pDirty = 0; return rc; } +#endif +static void pager_truncate_cache(Pager *pPager); + /* ** Truncate the main file of the given pager to the number of pages -** indicated. +** indicated. Also truncate the cached representation of the file. */ static int pager_truncate(Pager *pPager, int nPage){ - assert( pPager->state>=PAGER_EXCLUSIVE ); - return sqlite3OsTruncate(pPager->fd, pPager->pageSize*(i64)nPage); + int rc = SQLITE_OK; + if( pPager->state>=PAGER_EXCLUSIVE ){ + rc = sqlite3OsTruncate(pPager->fd, pPager->pageSize*(i64)nPage); + } + if( rc==SQLITE_OK ){ + pPager->dbSize = nPage; + pager_truncate_cache(pPager); + } + return rc; } /* @@ -1277,7 +1336,7 @@ static int pager_truncate(Pager *pPager, ** If an I/O or malloc() error occurs, the journal-file is not deleted ** and an error code is returned. */ -static int pager_playback(Pager *pPager){ +static int pager_playback(Pager *pPager, int isHot){ i64 szJ; /* Size of the journal file in bytes */ u32 nRec; /* Number of Records in the journal */ int i; /* Loop counter */ @@ -1290,7 +1349,7 @@ static int pager_playback(Pager *pPager) */ assert( pPager->journalOpen ); rc = sqlite3OsFileSize(pPager->jfd, &szJ); - if( rc!=SQLITE_OK ){ + if( rc!=SQLITE_OK || szJ==0 ){ goto end_playback; } @@ -1337,17 +1396,22 @@ static int pager_playback(Pager *pPager) nRec = (szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager); } + /* If nRec is 0 and this rollback is of a transaction created by this + ** process. In this case the rest of the journal file consists of + ** journalled copies of pages that need to be read back into the cache. + */ + if( nRec==0 && !isHot ){ + nRec = (szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager); + } + /* If this is the first header read from the journal, truncate the ** database file back to it's original size. */ - if( pPager->state>=PAGER_EXCLUSIVE && - pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){ - assert( pPager->origDbSize==0 || pPager->origDbSize==mxPg ); + if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){ rc = pager_truncate(pPager, mxPg); if( rc!=SQLITE_OK ){ goto end_playback; } - pPager->dbSize = mxPg; } /* Copy original pages out of the journal and back into the database file. @@ -1360,10 +1424,6 @@ static int pager_playback(Pager *pPager) pPager->journalOff = szJ; break; }else{ - /* If we are unable to rollback a hot journal, then the database - ** is probably not recoverable. Return CORRUPT. - */ - rc = SQLITE_CORRUPT; goto end_playback; } } @@ -1374,10 +1434,10 @@ end_playback: end_playback: if( rc==SQLITE_OK ){ - rc = pager_unwritelock(pPager); + rc = pager_end_transaction(pPager); } if( zMaster ){ - /* If there was a master journal and this routine will return true, + /* If there was a master journal and this routine will return success, ** see if it is possible to delete the master journal. */ if( rc==SQLITE_OK ){ @@ -1387,10 +1447,10 @@ end_playback: } /* The Pager.sectorSize variable may have been updated while rolling - ** back a journal created by a process with a different PAGER_SECTOR_SIZE + ** back a journal created by a process with a different sector size ** value. Reset it to the correct value for this process. */ - pPager->sectorSize = PAGER_SECTOR_SIZE; + pPager->sectorSize = sqlite3OsSectorSize(pPager->fd); return rc; } @@ -1425,8 +1485,9 @@ static int pager_stmt_playback(Pager *pP } #endif - /* Set hdrOff to be the offset to the first journal header written - ** this statement transaction, or the end of the file if no journal + /* Set hdrOff to be the offset just after the end of the last journal + ** page written before the first journal-header for this statement + ** transaction was written, or the end of the file if no journal ** header was written. */ hdrOff = pPager->stmtHdrOff; @@ -1437,11 +1498,8 @@ static int pager_stmt_playback(Pager *pP /* Truncate the database back to its original size. */ - if( pPager->state>=PAGER_EXCLUSIVE ){ - rc = pager_truncate(pPager, pPager->stmtSize); - } + rc = pager_truncate(pPager, pPager->stmtSize); assert( pPager->state>=PAGER_SHARED ); - pPager->dbSize = pPager->stmtSize; /* Figure out how many records are in the statement journal. */ @@ -1474,8 +1532,7 @@ static int pager_stmt_playback(Pager *pP } pPager->journalOff = pPager->stmtJSize; pPager->cksumInit = pPager->stmtCksum; - assert( JOURNAL_HDR_SZ(pPager)<(pPager->pageSize+8) ); - while( pPager->journalOff <= (hdrOff-(pPager->pageSize+8)) ){ + while( pPager->journalOff < hdrOff ){ rc = pager_playback_one_page(pPager, pPager->jfd, 1); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK ) goto end_stmt_playback; @@ -1512,7 +1569,7 @@ end_stmt_playback: /* ** Change the maximum number of in-memory pages that are allowed. */ -void sqlite3pager_set_cachesize(Pager *pPager, int mxPage){ +void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){ if( mxPage>10 ){ pPager->mxPage = mxPage; }else{ @@ -1547,7 +1604,7 @@ void sqlite3pager_set_cachesize(Pager *p ** and FULL=3. */ #ifndef SQLITE_OMIT_PAGER_PRAGMAS -void sqlite3pager_set_safety_level(Pager *pPager, int level, int full_fsync){ +void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int full_fsync){ pPager->noSync = level==1 || pPager->tempFile; pPager->fullSync = level==3 && !pPager->tempFile; pPager->full_fsync = full_fsync; @@ -1565,17 +1622,19 @@ int sqlite3_opentemp_count = 0; #endif /* -** Open a temporary file. Write the name of the file into zFile -** (zFile must be at least SQLITE_TEMPNAME_SIZE bytes long.) Write -** the file descriptor into *fd. Return SQLITE_OK on success or some +** Open a temporary file. +** +** Write the file descriptor into *fd. Return SQLITE_OK on success or some ** other error code if we fail. ** ** The OS will automatically delete the temporary file when it is ** closed. */ -static int sqlite3pager_opentemp(char *zFile, OsFile **pFd){ +static int sqlite3PagerOpentemp(OsFile **pFd){ int cnt = 8; int rc; + char zFile[SQLITE_TEMPNAME_SIZE]; + #ifdef SQLITE_TEST sqlite3_opentemp_count++; /* Used for testing and analysis only */ #endif @@ -1583,6 +1642,7 @@ static int sqlite3pager_opentemp(char *z cnt--; sqlite3OsTempFileName(zFile); rc = sqlite3OsOpenExclusive(zFile, pFd, 1); + assert( rc!=SQLITE_OK || *pFd ); }while( cnt>0 && rc!=SQLITE_OK && rc!=SQLITE_NOMEM ); return rc; } @@ -1590,8 +1650,8 @@ static int sqlite3pager_opentemp(char *z /* ** Create a new page cache and put a pointer to the page cache in *ppPager. ** The file to be cached need not exist. The file is not locked until -** the first call to sqlite3pager_get() and is only held open until the -** last page is released using sqlite3pager_unref(). +** the first call to sqlite3PagerGet() and is only held open until the +** last page is released using sqlite3PagerUnref(). ** ** If zFilename is NULL then a randomly-named temporary file is created ** and used as the file to be cached. The file will be deleted @@ -1601,7 +1661,7 @@ static int sqlite3pager_opentemp(char *z ** It is never written to disk. This can be used to implement an ** in-memory database. */ -int sqlite3pager_open( +int sqlite3PagerOpen( Pager **ppPager, /* Return the Pager structure here */ const char *zFilename, /* Name of the database file to open */ int nExtra, /* Extra bytes append to each in-memory page */ @@ -1610,7 +1670,7 @@ int sqlite3pager_open( Pager *pPager = 0; char *zFullPathname = 0; int nameLen; /* Compiler is wrong. This is always initialized before use */ - OsFile *fd; + OsFile *fd = 0; int rc = SQLITE_OK; int i; int tempFile = 0; @@ -1631,15 +1691,13 @@ int sqlite3pager_open( assert( pTsd ); #endif - /* If malloc() has already failed return SQLITE_NOMEM. Before even - ** testing for this, set *ppPager to NULL so the caller knows the pager - ** structure was never allocated. + /* We used to test if malloc() had already failed before proceeding. + ** But the way this function is used in SQLite means that can never + ** happen. Furthermore, if the malloc-failed flag is already set, + ** either the call to sqliteStrDup() or sqliteMalloc() below will + ** fail shortly and SQLITE_NOMEM returned anyway. */ *ppPager = 0; - if( sqlite3MallocFailed() ){ - return SQLITE_NOMEM; - } - memset(&fd, 0, sizeof(fd)); /* Open the pager file and set zFullPathname to point at malloc()ed ** memory containing the complete filename (i.e. including the directory). @@ -1655,10 +1713,12 @@ int sqlite3pager_open( zFullPathname = sqlite3OsFullPathname(zFilename); if( zFullPathname ){ rc = sqlite3OsOpenReadWrite(zFullPathname, &fd, &readOnly); + assert( rc!=SQLITE_OK || fd ); } } }else{ - rc = sqlite3pager_opentemp(zTemp, &fd); + rc = sqlite3PagerOpentemp(&fd); + sqlite3OsTempFileName(zTemp); zFilename = zTemp; zFullPathname = sqlite3OsFullPathname(zFilename); if( rc==SQLITE_OK ){ @@ -1673,21 +1733,26 @@ int sqlite3pager_open( if( zFullPathname ){ nameLen = strlen(zFullPathname); pPager = sqliteMalloc( sizeof(*pPager) + nameLen*3 + 30 ); + if( pPager && rc==SQLITE_OK ){ + pPager->pTmpSpace = (char *)sqliteMallocRaw(SQLITE_DEFAULT_PAGE_SIZE); + } } + /* If an error occured in either of the blocks above, free the memory ** pointed to by zFullPathname, free the Pager structure and close the ** file. Since the pager is not allocated there is no need to set ** any Pager.errMask variables. */ - if( !pPager || !zFullPathname || rc!=SQLITE_OK ){ + if( !pPager || !zFullPathname || !pPager->pTmpSpace || rc!=SQLITE_OK ){ sqlite3OsClose(&fd); sqliteFree(zFullPathname); sqliteFree(pPager); return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc); } - TRACE3("OPEN %d %s\n", FILEHANDLEID(fd), zFullPathname); + PAGERTRACE3("OPEN %d %s\n", FILEHANDLEID(fd), zFullPathname); + IOTRACE(("OPEN %p %s\n", pPager, zFullPathname)) pPager->zFilename = (char*)&pPager[1]; pPager->zDirectory = &pPager->zFilename[nameLen+1]; pPager->zJournal = &pPager->zDirectory[nameLen+1]; @@ -1717,6 +1782,10 @@ int sqlite3pager_open( /* pPager->state = PAGER_UNLOCK; */ /* pPager->errMask = 0; */ pPager->tempFile = tempFile; + assert( tempFile==PAGER_LOCKINGMODE_NORMAL + || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE ); + assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 ); + pPager->exclusiveMode = tempFile; pPager->memDb = memDb; pPager->readOnly = readOnly; /* pPager->needSync = 0; */ @@ -1726,7 +1795,10 @@ int sqlite3pager_open( /* pPager->pFirstSynced = 0; */ /* pPager->pLast = 0; */ pPager->nExtra = FORCE_ALIGNMENT(nExtra); - pPager->sectorSize = PAGER_SECTOR_SIZE; + assert(fd||memDb); + if( !memDb ){ + pPager->sectorSize = sqlite3OsSectorSize(fd); + } /* pPager->pBusyHandler = 0; */ /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ *ppPager = pPager; @@ -1740,7 +1812,7 @@ int sqlite3pager_open( /* ** Set the busy handler function. */ -void sqlite3pager_set_busyhandler(Pager *pPager, BusyHandler *pBusyHandler){ +void sqlite3PagerSetBusyhandler(Pager *pPager, BusyHandler *pBusyHandler){ pPager->pBusyHandler = pBusyHandler; } @@ -1749,10 +1821,10 @@ void sqlite3pager_set_busyhandler(Pager ** when the reference count on each page reaches zero. The destructor can ** be used to clean up information in the extra segment appended to each page. ** -** The destructor is not called as a result sqlite3pager_close(). -** Destructors are only called by sqlite3pager_unref(). +** The destructor is not called as a result sqlite3PagerClose(). +** Destructors are only called by sqlite3PagerUnref(). */ -void sqlite3pager_set_destructor(Pager *pPager, void (*xDesc)(void*,int)){ +void sqlite3PagerSetDestructor(Pager *pPager, void (*xDesc)(DbPage*,int)){ pPager->xDestructor = xDesc; } @@ -1763,7 +1835,7 @@ void sqlite3pager_set_destructor(Pager * ** an opportunity to restore the EXTRA section to agree with the restored ** page data. */ -void sqlite3pager_set_reiniter(Pager *pPager, void (*xReinit)(void*,int)){ +void sqlite3PagerSetReiniter(Pager *pPager, void (*xReinit)(DbPage*,int)){ pPager->xReiniter = xReinit; } @@ -1772,10 +1844,12 @@ void sqlite3pager_set_reiniter(Pager *pP ** size is inappropriate, then an alternative page size is selected ** and returned. */ -int sqlite3pager_set_pagesize(Pager *pPager, int pageSize){ +int sqlite3PagerSetPagesize(Pager *pPager, int pageSize){ assert( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE ); - if( !pPager->memDb ){ + if( !pPager->memDb && pPager->nRef==0 ){ + pager_reset(pPager); pPager->pageSize = pageSize; + pPager->pTmpSpace = sqlite3ReallocOrFree(pPager->pTmpSpace, pageSize); } return pPager->pageSize; } @@ -1792,9 +1866,6 @@ static int saved_cnt; extern int sqlite3_io_error_pending; extern int sqlite3_io_error_hit; static int saved_cnt; -void clear_simulated_io_error(){ - sqlite3_io_error_hit = 0; -} void disable_simulated_io_errors(void){ saved_cnt = sqlite3_io_error_pending; sqlite3_io_error_pending = -1; @@ -1803,7 +1874,6 @@ void enable_simulated_io_errors(void){ sqlite3_io_error_pending = saved_cnt; } #else -# define clear_simulated_io_error() # define disable_simulated_io_errors() # define enable_simulated_io_errors() #endif @@ -1818,13 +1888,14 @@ void enable_simulated_io_errors(void){ ** response is to zero the memory at pDest and continue. A real IO error ** will presumably recur and be picked up later (Todo: Think about this). */ -int sqlite3pager_read_fileheader(Pager *pPager, int N, unsigned char *pDest){ +int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){ int rc = SQLITE_OK; memset(pDest, 0, N); if( MEMDB==0 ){ disable_simulated_io_errors(); sqlite3OsSeek(pPager->fd, 0); enable_simulated_io_errors(); + IOTRACE(("DBHDR %p 0 %d\n", pPager, N)) rc = sqlite3OsRead(pPager->fd, pDest, N); if( rc==SQLITE_IOERR_SHORT_READ ){ rc = SQLITE_OK; @@ -1842,10 +1913,13 @@ int sqlite3pager_read_fileheader(Pager * ** PENDING_BYTE is byte 4096 (the first byte of page 5) and the size of the ** file is 4096 bytes, 5 is returned instead of 4. */ -int sqlite3pager_pagecount(Pager *pPager){ +int sqlite3PagerPagecount(Pager *pPager){ i64 n; int rc; assert( pPager!=0 ); + if( pPager->errCode ){ + return 0; + } if( pPager->dbSize>=0 ){ n = pPager->dbSize; } else { @@ -1891,7 +1965,7 @@ static int syncJournal(Pager*); /* ** Unlink pPg from it's hash chain. Also set the page number to 0 to indicate ** that the page is not part of any hash chain. This is required because the -** sqlite3pager_movepage() routine can leave a page in the +** sqlite3PagerMovepage() routine can leave a page in the ** pNextFree/pPrevFree list that is not a part of any hash-chain. */ static void unlinkHashChain(Pager *pPager, PgHdr *pPg){ @@ -1949,13 +2023,19 @@ static void unlinkPage(PgHdr *pPg){ unlinkHashChain(pPager, pPg); } -#ifndef SQLITE_OMIT_MEMORYDB /* -** This routine is used to truncate an in-memory database. Delete -** all pages whose pgno is larger than pPager->dbSize and is unreferenced. +** This routine is used to truncate the cache when a database +** is truncated. Drop from the cache all pages whose pgno is +** larger than pPager->dbSize and is unreferenced. +** ** Referenced pages larger than pPager->dbSize are zeroed. +** +** Actually, at the point this routine is called, it would be +** an error to have a referenced page. But rather than delete +** that page and guarantee a subsequent segfault, it seems better +** to zero it and hope that we error out sanely. */ -static void memoryTruncate(Pager *pPager){ +static void pager_truncate_cache(Pager *pPager){ PgHdr *pPg; PgHdr **ppPg; int dbSize = pPager->dbSize; @@ -1976,9 +2056,6 @@ static void memoryTruncate(Pager *pPager } } } -#else -#define memoryTruncate(p) -#endif /* ** Try to obtain a lock on a file. Invoke the busy callback if the lock @@ -2007,6 +2084,7 @@ static int pager_wait_on_lock(Pager *pPa }while( rc==SQLITE_BUSY && sqlite3InvokeBusyHandler(pPager->pBusyHandler) ); if( rc==SQLITE_OK ){ pPager->state = locktype; + IOTRACE(("LOCK %p %d\n", pPager, locktype)) } } return rc; @@ -2015,10 +2093,10 @@ static int pager_wait_on_lock(Pager *pPa /* ** Truncate the file to the number of pages specified. */ -int sqlite3pager_truncate(Pager *pPager, Pgno nPage){ +int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){ int rc; assert( pPager->state>=PAGER_SHARED || MEMDB ); - sqlite3pager_pagecount(pPager); + sqlite3PagerPagecount(pPager); if( pPager->errCode ){ rc = pPager->errCode; return rc; @@ -2028,7 +2106,7 @@ int sqlite3pager_truncate(Pager *pPager, } if( MEMDB ){ pPager->dbSize = nPage; - memoryTruncate(pPager); + pager_truncate_cache(pPager); return SQLITE_OK; } rc = syncJournal(pPager); @@ -2043,9 +2121,6 @@ int sqlite3pager_truncate(Pager *pPager, } rc = pager_truncate(pPager, nPage); - if( rc==SQLITE_OK ){ - pPager->dbSize = nPage; - } return rc; } @@ -2063,7 +2138,7 @@ int sqlite3pager_truncate(Pager *pPager, ** a hot journal may be left in the filesystem but no error is returned ** to the caller. */ -int sqlite3pager_close(Pager *pPager){ +int sqlite3PagerClose(Pager *pPager){ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT /* A malloc() cannot fail in sqlite3ThreadData() as one or more calls to ** malloc() must have already been made by this thread before it gets @@ -2077,9 +2152,12 @@ int sqlite3pager_close(Pager *pPager){ disable_simulated_io_errors(); pPager->errCode = 0; + pPager->exclusiveMode = 0; pager_reset(pPager); + pagerUnlockAndRollback(pPager); enable_simulated_io_errors(); - TRACE2("CLOSE %d\n", PAGERID(pPager)); + PAGERTRACE2("CLOSE %d\n", PAGERID(pPager)); + IOTRACE(("CLOSE %p\n", pPager)) assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) ); if( pPager->journalOpen ){ sqlite3OsClose(&pPager->jfd); @@ -2108,6 +2186,7 @@ int sqlite3pager_close(Pager *pPager){ } #endif sqliteFree(pPager->aHash); + sqliteFree(pPager->pTmpSpace); sqliteFree(pPager); return SQLITE_OK; } @@ -2115,8 +2194,7 @@ int sqlite3pager_close(Pager *pPager){ /* ** Return the page number for the given page data. */ -Pgno sqlite3pager_pagenumber(void *pData){ - PgHdr *p = DATA_TO_PGHDR(pData); +Pgno sqlite3PagerPagenumber(DbPage *p){ return p->pgno; } @@ -2169,8 +2247,7 @@ static void _page_ref(PgHdr *pPg){ ** Increment the reference count for a page. The input pointer is ** a reference to the page data. */ -int sqlite3pager_ref(void *pData){ - PgHdr *pPg = DATA_TO_PGHDR(pData); +int sqlite3PagerRef(DbPage *pPg){ page_ref(pPg); return SQLITE_OK; } @@ -2225,20 +2302,24 @@ static int syncJournal(Pager *pPager){ ** it as a candidate for rollback. */ if( pPager->fullSync ){ - TRACE2("SYNC journal of %d\n", PAGERID(pPager)); + PAGERTRACE2("SYNC journal of %d\n", PAGERID(pPager)); + IOTRACE(("JSYNC %p\n", pPager)) rc = sqlite3OsSync(pPager->jfd, 0); if( rc!=0 ) return rc; } rc = sqlite3OsSeek(pPager->jfd, pPager->journalHdr + sizeof(aJournalMagic)); if( rc ) return rc; + IOTRACE(("JHDR %p %lld %d\n", pPager, + pPager->journalHdr + sizeof(aJournalMagic), 4)) rc = write32bits(pPager->jfd, pPager->nRec); if( rc ) return rc; rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff); if( rc ) return rc; } - TRACE2("SYNC journal of %d\n", PAGERID(pPager)); + PAGERTRACE2("SYNC journal of %d\n", PAGERID(pPager)); + IOTRACE(("JSYNC %d\n", pPager)) rc = sqlite3OsSync(pPager->jfd, pPager->full_fsync); if( rc!=0 ) return rc; pPager->journalStarted = 1; @@ -2302,9 +2383,16 @@ static PgHdr *merge_pagelist(PgHdr *pA, ** connected by pDirty pointers. The pPrevDirty pointers are ** corrupted by this sort. */ -#define N_SORT_BUCKET 25 +#define N_SORT_BUCKET_ALLOC 25 +#define N_SORT_BUCKET 25 +#ifdef SQLITE_TEST + int sqlite3_pager_n_sort_bucket = 0; + #undef N_SORT_BUCKET + #define N_SORT_BUCKET \ + (sqlite3_pager_n_sort_bucket?sqlite3_pager_n_sort_bucket:N_SORT_BUCKET_ALLOC) +#endif static PgHdr *sort_pagelist(PgHdr *pIn){ - PgHdr *a[N_SORT_BUCKET], *p; + PgHdr *a[N_SORT_BUCKET_ALLOC], *p; int i; memset(a, 0, sizeof(a)); while( pIn ){ @@ -2321,6 +2409,11 @@ static PgHdr *sort_pagelist(PgHdr *pIn){ } } if( i==N_SORT_BUCKET-1 ){ + /* Coverage: To get here, there need to be 2^(N_SORT_BUCKET) + ** elements in the input list. This is possible, but impractical. + ** Testing this line is the point of global variable + ** sqlite3_pager_n_sort_bucket. + */ a[i] = merge_pagelist(a[i], p); } } @@ -2370,19 +2463,20 @@ static int pager_write_pagelist(PgHdr *p rc = sqlite3OsSeek(pPager->fd, (pList->pgno-1)*(i64)pPager->pageSize); if( rc ) return rc; /* If there are dirty pages in the page cache with page numbers greater - ** than Pager.dbSize, this means sqlite3pager_truncate() was called to + ** than Pager.dbSize, this means sqlite3PagerTruncate() was called to ** make the file smaller (presumably by auto-vacuum code). Do not write ** any such pages to the file. */ if( pList->pgno<=pPager->dbSize ){ char *pData = CODEC2(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6); - TRACE3("STORE %d page %d\n", PAGERID(pPager), pList->pgno); + PAGERTRACE3("STORE %d page %d\n", PAGERID(pPager), pList->pgno); + IOTRACE(("PGOUT %p %d\n", pPager, pList->pgno)) rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize); TEST_INCR(pPager->nWrite); } #ifndef NDEBUG else{ - TRACE3("NOSTORE %d page %d\n", PAGERID(pPager), pList->pgno); + PAGERTRACE3("NOSTORE %d page %d\n", PAGERID(pPager), pList->pgno); } #endif if( rc ) return rc; @@ -2414,9 +2508,13 @@ static int hasHotJournal(Pager *pPager){ */ static int hasHotJournal(Pager *pPager){ if( !pPager->useJournal ) return 0; - if( !sqlite3OsFileExists(pPager->zJournal) ) return 0; - if( sqlite3OsCheckReservedLock(pPager->fd) ) return 0; - if( sqlite3pager_pagecount(pPager)==0 ){ + if( !sqlite3OsFileExists(pPager->zJournal) ){ + return 0; + } + if( sqlite3OsCheckReservedLock(pPager->fd) ){ + return 0; + } + if( sqlite3PagerPagecount(pPager)==0 ){ sqlite3OsDelete(pPager->zJournal); return 0; }else{ @@ -2434,6 +2532,8 @@ static int pager_recycle(Pager *pPager, PgHdr *pPg; *ppPg = 0; + assert(!MEMDB); + /* Find a page to recycle. Try to locate a page that does not ** require us to do an fsync() on the journal. */ @@ -2458,6 +2558,7 @@ static int pager_recycle(Pager *pPager, */ pPager->nRec = 0; assert( pPager->journalOff > 0 ); + assert( pPager->doNotSync==0 ); rc = writeJournalHdr(pPager); if( rc!=0 ){ return rc; @@ -2488,20 +2589,21 @@ static int pager_recycle(Pager *pPager, /* If the page we are recycling is marked as alwaysRollback, then ** set the global alwaysRollback flag, thus disabling the - ** sqlite_dont_rollback() optimization for the rest of this transaction. + ** sqlite3PagerDontRollback() optimization for the rest of this transaction. ** It is necessary to do this because the page marked alwaysRollback ** might be reloaded at a later time but at that point we won't remember ** that is was marked alwaysRollback. This means that all pages must ** be marked as alwaysRollback from here on out. */ if( pPg->alwaysRollback ){ + IOTRACE(("ALWAYS_ROLLBACK %p\n", pPager)) pPager->alwaysRollback = 1; } /* Unlink the old page from the free list and the hash table */ unlinkPage(pPg); - TEST_INCR(pPager->nOvfl); + assert( pPg->pgno==0 ); *ppPg = pPg; return SQLITE_OK; @@ -2518,9 +2620,8 @@ static int pager_recycle(Pager *pPager, ** of bytes of memory released. */ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT -int sqlite3pager_release_memory(int nReq){ +int sqlite3PagerReleaseMemory(int nReq){ const ThreadData *pTsdro = sqlite3ThreadDataReadOnly(); - Pager *p; int nReleased = 0; int i; @@ -2542,15 +2643,20 @@ int sqlite3pager_release_memory(int nReq for(i=0; i<=1; i++){ /* Loop through all the SQLite pagers opened by the current thread. */ - for(p=pTsdro->pPager; p && (nReq<0 || nReleasedpNext){ + Pager *pPager = pTsdro->pPager; + for( ; pPager && (nReq<0 || nReleasedpNext){ PgHdr *pPg; int rc; + if( MEMDB ){ + continue; + } + /* For each pager, try to free as many pages as possible (without ** calling fsync() if this is the first iteration of the outermost ** loop). */ - while( SQLITE_OK==(rc = pager_recycle(p, i, &pPg)) && pPg) { + while( SQLITE_OK==(rc = pager_recycle(pPager, i, &pPg)) && pPg) { /* We've found a page to free. At this point the page has been ** removed from the page hash-table, free-list and synced-list ** (pFirstSynced). It is still in the all pages (pAll) list. @@ -2561,11 +2667,10 @@ int sqlite3pager_release_memory(int nReq */ PgHdr *pTmp; assert( pPg ); - page_remove_from_stmt_list(pPg); - if( pPg==p->pAll ){ - p->pAll = pPg->pNextAll; + if( pPg==pPager->pAll ){ + pPager->pAll = pPg->pNextAll; }else{ - for( pTmp=p->pAll; pTmp->pNextAll!=pPg; pTmp=pTmp->pNextAll ){} + for( pTmp=pPager->pAll; pTmp->pNextAll!=pPg; pTmp=pTmp->pNextAll ){} pTmp->pNextAll = pPg->pNextAll; } nReleased += sqliteAllocSize(pPg); @@ -2580,8 +2685,8 @@ int sqlite3pager_release_memory(int nReq ** of a shared pager cache) of the pager for which the error occured. */ assert( (rc&0xff)==SQLITE_IOERR || rc==SQLITE_FULL ); - assert( p->state>=PAGER_RESERVED ); - pager_error(p, rc); + assert( pPager->state>=PAGER_RESERVED ); + pager_error(pPager, rc); } } } @@ -2591,6 +2696,247 @@ int sqlite3pager_release_memory(int nReq #endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */ /* +** Read the content of page pPg out of the database file. +*/ +static int readDbPage(Pager *pPager, PgHdr *pPg, Pgno pgno){ + int rc; + assert( MEMDB==0 ); + rc = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize); + if( rc==SQLITE_OK ){ + rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg), + pPager->pageSize); + } + IOTRACE(("PGIN %p %d\n", pPager, pgno)) + PAGERTRACE3("FETCH %d page %d\n", PAGERID(pPager), pPg->pgno); + CODEC1(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3); + return rc; +} + + +/* +** This function is called to obtain the shared lock required before +** data may be read from the pager cache. If the shared lock has already +** been obtained, this function is a no-op. +** +** Immediately after obtaining the shared lock (if required), this function +** checks for a hot-journal file. If one is found, an emergency rollback +** is performed immediately. +*/ +static int pagerSharedLock(Pager *pPager){ + int rc = SQLITE_OK; + + if( pPager->state==PAGER_UNLOCK ){ + if( !MEMDB ){ + assert( pPager->nRef==0 ); + if( !pPager->noReadlock ){ + rc = pager_wait_on_lock(pPager, SHARED_LOCK); + if( rc!=SQLITE_OK ){ + return pager_error(pPager, rc); + } + assert( pPager->state>=SHARED_LOCK ); + } + + /* If a journal file exists, and there is no RESERVED lock on the + ** database file, then it either needs to be played back or deleted. + */ + if( hasHotJournal(pPager) ){ + /* Get an EXCLUSIVE lock on the database file. At this point it is + ** important that a RESERVED lock is not obtained on the way to the + ** EXCLUSIVE lock. If it were, another process might open the + ** database file, detect the RESERVED lock, and conclude that the + ** database is safe to read while this process is still rolling it + ** back. + ** + ** Because the intermediate RESERVED lock is not requested, the + ** second process will get to this point in the code and fail to + ** obtain it's own EXCLUSIVE lock on the database file. + */ + rc = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK); + if( rc!=SQLITE_OK ){ + pager_unlock(pPager); + return pager_error(pPager, rc); + } + pPager->state = PAGER_EXCLUSIVE; + + /* Open the journal for reading only. Return SQLITE_BUSY if + ** we are unable to open the journal file. + ** + ** The journal file does not need to be locked itself. The + ** journal file is never open unless the main database file holds + ** a write lock, so there is never any chance of two or more + ** processes opening the journal at the same time. + ** + ** Open the journal for read/write access. This is because in + ** exclusive-access mode the file descriptor will be kept open and + ** possibly used for a transaction later on. On some systems, the + ** OsTruncate() call used in exclusive-access mode also requires + ** a read/write file handle. + */ + rc = SQLITE_BUSY; + if( sqlite3OsFileExists(pPager->zJournal) ){ + int ro; + assert( !pPager->tempFile ); + rc = sqlite3OsOpenReadWrite(pPager->zJournal, &pPager->jfd, &ro); + assert( rc!=SQLITE_OK || pPager->jfd ); + if( ro ){ + rc = SQLITE_BUSY; + sqlite3OsClose(&pPager->jfd); + } + } + if( rc!=SQLITE_OK ){ + pager_unlock(pPager); + return SQLITE_BUSY; + } + pPager->journalOpen = 1; + pPager->journalStarted = 0; + pPager->journalOff = 0; + pPager->setMaster = 0; + pPager->journalHdr = 0; + + /* Playback and delete the journal. Drop the database write + ** lock and reacquire the read lock. + */ + rc = pager_playback(pPager, 1); + if( rc!=SQLITE_OK ){ + return pager_error(pPager, rc); + } + assert(pPager->state==PAGER_SHARED || + (pPager->exclusiveMode && pPager->state>PAGER_SHARED) + ); + } + + if( pPager->pAll ){ + /* The shared-lock has just been acquired on the database file + ** and there are already pages in the cache (from a previous + ** read or write transaction). If the value of the change-counter + ** stored in Pager.iChangeCount matches that found on page 1 of + ** the database file, then no database changes have occured since + ** the cache was last valid and it is safe to retain the cached + ** pages. Otherwise, if Pager.iChangeCount does not match the + ** change-counter on page 1 of the file, the current cache contents + ** must be discarded. + */ + u8 zC[4]; + u32 iChangeCounter = 0; + sqlite3PagerPagecount(pPager); + + if( pPager->errCode ){ + return pPager->errCode; + } + + if( pPager->dbSize>0 ){ + /* Read the 4-byte change counter directly from the file. */ + rc = sqlite3OsSeek(pPager->fd, 24); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = sqlite3OsRead(pPager->fd, zC, 4); + if( rc!=SQLITE_OK ){ + return rc; + } + iChangeCounter = (zC[0]<<24) + (zC[1]<<16) + (zC[2]<<8) + zC[3]; + } + + if( iChangeCounter!=pPager->iChangeCount ){ + pager_reset(pPager); + } + } + } + assert( pPager->exclusiveMode || pPager->state<=PAGER_SHARED ); + if( pPager->state==PAGER_UNLOCK ){ + pPager->state = PAGER_SHARED; + } + } + + return rc; +} + +/* +** Allocate a PgHdr object. Either create a new one or reuse +** an existing one that is not otherwise in use. +** +** A new PgHdr structure is created if any of the following are +** true: +** +** (1) We have not exceeded our maximum allocated cache size +** as set by the "PRAGMA cache_size" command. +** +** (2) There are no unused PgHdr objects available at this time. +** +** (3) This is an in-memory database. +** +** (4) There are no PgHdr objects that do not require a journal +** file sync and a sync of the journal file is currently +** prohibited. +** +** Otherwise, reuse an existing PgHdr. In other words, reuse an +** existing PgHdr if all of the following are true: +** +** (1) We have reached or exceeded the maximum cache size +** allowed by "PRAGMA cache_size". +** +** (2) There is a PgHdr available with PgHdr->nRef==0 +** +** (3) We are not in an in-memory database +** +** (4) Either there is an available PgHdr that does not need +** to be synced to disk or else disk syncing is currently +** allowed. +*/ +static int pagerAllocatePage(Pager *pPager, PgHdr **ppPg){ + int rc = SQLITE_OK; + PgHdr *pPg; + + /* Create a new PgHdr if any of the four conditions defined + ** above is met: */ + if( pPager->nPagemxPage + || pPager->pFirst==0 + || MEMDB + || (pPager->pFirstSynced==0 && pPager->doNotSync) + ){ + if( pPager->nPage>=pPager->nHash ){ + pager_resize_hash_table(pPager, + pPager->nHash<256 ? 256 : pPager->nHash*2); + if( pPager->nHash==0 ){ + rc = SQLITE_NOMEM; + goto pager_allocate_out; + } + } + pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->pageSize + + sizeof(u32) + pPager->nExtra + + MEMDB*sizeof(PgHistory) ); + if( pPg==0 ){ + rc = SQLITE_NOMEM; + goto pager_allocate_out; + } + memset(pPg, 0, sizeof(*pPg)); + if( MEMDB ){ + memset(PGHDR_TO_HIST(pPg, pPager), 0, sizeof(PgHistory)); + } + pPg->pPager = pPager; + pPg->pNextAll = pPager->pAll; + pPager->pAll = pPg; + pPager->nPage++; + if( pPager->nPage>pPager->nMaxPage ){ + assert( pPager->nMaxPage==(pPager->nPage-1) ); + pPager->nMaxPage++; + } + }else{ + /* Recycle an existing page with a zero ref-count. */ + rc = pager_recycle(pPager, 1, &pPg); + if( rc!=SQLITE_OK ){ + goto pager_allocate_out; + } + assert( pPager->state>=SHARED_LOCK ); + assert(pPg); + } + *ppPg = pPg; + +pager_allocate_out: + return rc; +} + +/* ** Acquire a page. ** ** A read lock on the disk file is obtained when the first page is acquired. @@ -2605,18 +2951,25 @@ int sqlite3pager_release_memory(int nReq ** The acquisition might fail for several reasons. In all cases, ** an appropriate error code is returned and *ppPage is set to NULL. ** -** See also sqlite3pager_lookup(). Both this routine and _lookup() attempt +** See also sqlite3PagerLookup(). Both this routine and _lookup() attempt ** to find a page in the in-memory cache first. If the page is not already ** in memory, this routine goes to disk to read it in whereas _lookup() ** just returns 0. This routine acquires a read-lock the first time it ** has to go to disk, and could also playback an old journal if necessary. ** Since _lookup() never goes to disk, it never has to deal with locks ** or journal files. +** +** If clrFlag is false, the page contents are actually read from disk. +** If clfFlag is true, it means the page is about to be erased and +** rewritten without first being read so there is no point it doing +** the disk I/O. */ -int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ +int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag){ PgHdr *pPg; int rc; + assert( pPager->state==PAGER_UNLOCK || pPager->nRef>0 || pgno==1 ); + /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page ** number greater than this, or zero, is requested. */ @@ -2633,112 +2986,28 @@ int sqlite3pager_get(Pager *pPager, Pgno } /* If this is the first page accessed, then get a SHARED lock - ** on the database file. + ** on the database file. pagerSharedLock() is a no-op if + ** a database lock is already held. */ - if( pPager->nRef==0 && !MEMDB ){ - if( !pPager->noReadlock ){ - rc = pager_wait_on_lock(pPager, SHARED_LOCK); - if( rc!=SQLITE_OK ){ - return pager_error(pPager, rc); - } - } + rc = pagerSharedLock(pPager); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( pPager->state!=PAGER_UNLOCK ); - /* If a journal file exists, and there is no RESERVED lock on the - ** database file, then it either needs to be played back or deleted. - */ - if( hasHotJournal(pPager) ){ - /* Get an EXCLUSIVE lock on the database file. At this point it is - ** important that a RESERVED lock is not obtained on the way to the - ** EXCLUSIVE lock. If it were, another process might open the - ** database file, detect the RESERVED lock, and conclude that the - ** database is safe to read while this process is still rolling it - ** back. - ** - ** Because the intermediate RESERVED lock is not requested, the - ** second process will get to this point in the code and fail to - ** obtain it's own EXCLUSIVE lock on the database file. - */ - rc = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK); - if( rc!=SQLITE_OK ){ - pager_unlock(pPager); - return pager_error(pPager, rc); - } - pPager->state = PAGER_EXCLUSIVE; - - /* Open the journal for reading only. Return SQLITE_BUSY if - ** we are unable to open the journal file. - ** - ** The journal file does not need to be locked itself. The - ** journal file is never open unless the main database file holds - ** a write lock, so there is never any chance of two or more - ** processes opening the journal at the same time. - */ - rc = sqlite3OsOpenReadOnly(pPager->zJournal, &pPager->jfd); - if( rc!=SQLITE_OK ){ - pager_unlock(pPager); - return SQLITE_BUSY; - } - pPager->journalOpen = 1; - pPager->journalStarted = 0; - pPager->journalOff = 0; - pPager->setMaster = 0; - pPager->journalHdr = 0; - - /* Playback and delete the journal. Drop the database write - ** lock and reacquire the read lock. - */ - rc = pager_playback(pPager); - if( rc!=SQLITE_OK ){ - return pager_error(pPager, rc); - } - } - pPg = 0; - }else{ - /* Search for page in cache */ - pPg = pager_lookup(pPager, pgno); - if( MEMDB && pPager->state==PAGER_UNLOCK ){ - pPager->state = PAGER_SHARED; - } - } + pPg = pager_lookup(pPager, pgno); if( pPg==0 ){ /* The requested page is not in the page cache. */ + int nMax; int h; TEST_INCR(pPager->nMiss); - if( pPager->nPagemxPage || pPager->pFirst==0 || MEMDB ){ - /* Create a new page */ - if( pPager->nPage>=pPager->nHash ){ - pager_resize_hash_table(pPager, - pPager->nHash<256 ? 256 : pPager->nHash*2); - if( pPager->nHash==0 ){ - return SQLITE_NOMEM; - } - } - pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->pageSize - + sizeof(u32) + pPager->nExtra - + MEMDB*sizeof(PgHistory) ); - if( pPg==0 ){ - return SQLITE_NOMEM; - } - memset(pPg, 0, sizeof(*pPg)); - if( MEMDB ){ - memset(PGHDR_TO_HIST(pPg, pPager), 0, sizeof(PgHistory)); - } - pPg->pPager = pPager; - pPg->pNextAll = pPager->pAll; - pPager->pAll = pPg; - pPager->nPage++; - if( pPager->nPage>pPager->nMaxPage ){ - assert( pPager->nMaxPage==(pPager->nPage-1) ); - pPager->nMaxPage++; - } - }else{ - rc = pager_recycle(pPager, 1, &pPg); - if( rc!=SQLITE_OK ){ - return rc; - } - assert(pPg) ; + rc = pagerAllocatePage(pPager, &pPg); + if( rc!=SQLITE_OK ){ + return rc; } + pPg->pgno = pgno; + assert( !MEMDB || pgno>pPager->stmtSize ); if( pPager->aInJournal && (int)pgno<=pPager->origDbSize ){ sqlite3CheckMemory(pPager->aInJournal, pgno/8); assert( pPager->journalOpen ); @@ -2748,12 +3017,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pPg->inJournal = 0; pPg->needSync = 0; } - if( pPager->aInStmt && (int)pgno<=pPager->stmtSize - && (pPager->aInStmt[pgno/8] & (1<<(pgno&7)))!=0 ){ - page_add_to_stmt_list(pPg); - }else{ - page_remove_from_stmt_list(pPg); - } + makeClean(pPg); pPg->nRef = 1; REFINFO(pPg); @@ -2762,8 +3026,9 @@ int sqlite3pager_get(Pager *pPager, Pgno if( pPager->nExtra>0 ){ memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra); } + nMax = sqlite3PagerPagecount(pPager); if( pPager->errCode ){ - sqlite3pager_unref(PGHDR_TO_DATA(pPg)); + sqlite3PagerUnref(pPg); rc = pPager->errCode; return rc; } @@ -2771,20 +3036,13 @@ int sqlite3pager_get(Pager *pPager, Pgno /* Populate the page with data, either by reading from the database ** file, or by setting the entire page to zero. */ - if( sqlite3pager_pagecount(pPager)<(int)pgno || MEMDB ){ + if( nMax<(int)pgno || MEMDB || (clrFlag && !pPager->alwaysRollback) ){ memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); }else{ - assert( MEMDB==0 ); - rc = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize); - if( rc==SQLITE_OK ){ - rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg), - pPager->pageSize); - } - TRACE3("FETCH %d page %d\n", PAGERID(pPager), pPg->pgno); - CODEC1(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3); + rc = readDbPage(pPager, pPg, pgno); if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){ pPg->pgno = 0; - sqlite3pager_unref(PGHDR_TO_DATA(pPg)); + sqlite3PagerUnref(pPg); return rc; }else{ TEST_INCR(pPager->nRead); @@ -2806,10 +3064,11 @@ int sqlite3pager_get(Pager *pPager, Pgno #endif }else{ /* The requested page is in the page cache. */ + assert(pPager->nRef>0 || pgno==1); TEST_INCR(pPager->nHit); page_ref(pPg); } - *ppPage = PGHDR_TO_DATA(pPg); + *ppPage = pPg; return SQLITE_OK; } @@ -2818,24 +3077,29 @@ int sqlite3pager_get(Pager *pPager, Pgno ** not read the page from disk. Return a pointer to the page, ** or 0 if the page is not in cache. ** -** See also sqlite3pager_get(). The difference between this routine -** and sqlite3pager_get() is that _get() will go to the disk and read +** See also sqlite3PagerGet(). The difference between this routine +** and sqlite3PagerGet() is that _get() will go to the disk and read ** in the page if the page is not already in cache. This routine ** returns NULL if the page is not in cache or if a disk I/O error ** has ever happened. */ -void *sqlite3pager_lookup(Pager *pPager, Pgno pgno){ +DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ PgHdr *pPg; assert( pPager!=0 ); assert( pgno!=0 ); + + if( pPager->state==PAGER_UNLOCK ){ + assert( !pPager->pAll || pPager->exclusiveMode ); + return 0; + } if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ return 0; } pPg = pager_lookup(pPager, pgno); if( pPg==0 ) return 0; page_ref(pPg); - return PGHDR_TO_DATA(pPg); + return pPg; } /* @@ -2846,12 +3110,10 @@ void *sqlite3pager_lookup(Pager *pPager, ** are released, a rollback occurs and the lock on the database is ** removed. */ -int sqlite3pager_unref(void *pData){ - PgHdr *pPg; +int sqlite3PagerUnref(DbPage *pPg){ /* Decrement the reference count for this page */ - pPg = DATA_TO_PGHDR(pData); assert( pPg->nRef>0 ); pPg->nRef--; REFINFO(pPg); @@ -2876,7 +3138,7 @@ int sqlite3pager_unref(void *pData){ pPager->pFirstSynced = pPg; } if( pPager->xDestructor ){ - pPager->xDestructor(pData, pPager->pageSize); + pPager->xDestructor(pPg, pPager->pageSize); } /* When all pages reach the freelist, drop the read lock from @@ -2884,8 +3146,8 @@ int sqlite3pager_unref(void *pData){ */ pPager->nRef--; assert( pPager->nRef>=0 ); - if( pPager->nRef==0 && !MEMDB ){ - pager_reset(pPager); + if( pPager->nRef==0 && (!pPager->exclusiveMode || pPager->journalOff>0) ){ + pagerUnlockAndRollback(pPager); } } return SQLITE_OK; @@ -2905,7 +3167,7 @@ static int pager_open_journal(Pager *pPa assert( pPager->journalOpen==0 ); assert( pPager->useJournal ); assert( pPager->aInJournal==0 ); - sqlite3pager_pagecount(pPager); + sqlite3PagerPagecount(pPager); pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 ); if( pPager->aInJournal==0 ){ rc = SQLITE_NOMEM; @@ -2913,10 +3175,14 @@ static int pager_open_journal(Pager *pPa } rc = sqlite3OsOpenExclusive(pPager->zJournal, &pPager->jfd, pPager->tempFile); + assert( rc!=SQLITE_OK || pPager->jfd ); pPager->journalOff = 0; pPager->setMaster = 0; pPager->journalHdr = 0; if( rc!=SQLITE_OK ){ + if( rc==SQLITE_NOMEM ){ + sqlite3OsDelete(pPager->zJournal); + } goto failed_to_open_journal; } sqlite3OsSetFullSync(pPager->jfd, pPager->full_fsync); @@ -2936,10 +3202,10 @@ static int pager_open_journal(Pager *pPa rc = writeJournalHdr(pPager); if( pPager->stmtAutoopen && rc==SQLITE_OK ){ - rc = sqlite3pager_stmt_begin(pPager); + rc = sqlite3PagerStmtBegin(pPager); } if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){ - rc = pager_unwritelock(pPager); + rc = pager_end_transaction(pPager); if( rc==SQLITE_OK ){ rc = SQLITE_FULL; } @@ -2949,16 +3215,6 @@ failed_to_open_journal: failed_to_open_journal: sqliteFree(pPager->aInJournal); pPager->aInJournal = 0; - if( rc==SQLITE_NOMEM ){ - /* If this was a malloc() failure, then we will not be closing the pager - ** file. So delete any journal file we may have just created. Otherwise, - ** the system will get confused, we have a read-lock on the file and a - ** mysterious journal has appeared in the filesystem. - */ - sqlite3OsDelete(pPager->zJournal); - }else{ - pager_reset(pPager); - } return rc; } @@ -2966,10 +3222,10 @@ failed_to_open_journal: ** Acquire a write-lock on the database. The lock is removed when ** the any of the following happen: ** -** * sqlite3pager_commit() is called. -** * sqlite3pager_rollback() is called. -** * sqlite3pager_close() is called. -** * sqlite3pager_unref() is called to on every outstanding page. +** * sqlite3PagerCommitPhaseTwo() is called. +** * sqlite3PagerRollback() is called. +** * sqlite3PagerClose() is called. +** * sqlite3PagerUnref() is called to on every outstanding page. ** ** The first parameter to this routine is a pointer to any open page of the ** database file. Nothing changes about the page - it is used merely to @@ -2989,8 +3245,7 @@ failed_to_open_journal: ** immediately instead of waiting until we try to flush the cache. The ** exFlag is ignored if a transaction is already active. */ -int sqlite3pager_begin(void *pData, int exFlag){ - PgHdr *pPg = DATA_TO_PGHDR(pData); +int sqlite3PagerBegin(DbPage *pPg, int exFlag){ Pager *pPager = pPg->pPager; int rc = SQLITE_OK; assert( pPg->nRef>0 ); @@ -3012,12 +3267,30 @@ int sqlite3pager_begin(void *pData, int return rc; } pPager->dirtyCache = 0; - TRACE2("TRANSACTION %d\n", PAGERID(pPager)); + PAGERTRACE2("TRANSACTION %d\n", PAGERID(pPager)); if( pPager->useJournal && !pPager->tempFile ){ rc = pager_open_journal(pPager); } } + }else if( pPager->journalOpen && pPager->journalOff==0 ){ + /* This happens when the pager was in exclusive-access mode last + ** time a (read or write) transaction was successfully concluded + ** by this connection. Instead of deleting the journal file it was + ** kept open and truncated to 0 bytes. + */ + assert( pPager->nRec==0 ); + assert( pPager->origDbSize==0 ); + assert( pPager->aInJournal==0 ); + sqlite3PagerPagecount(pPager); + pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 ); + if( !pPager->aInJournal ){ + rc = SQLITE_NOMEM; + }else{ + pPager->origDbSize = pPager->dbSize; + rc = writeJournalHdr(pPager); + } } + assert( !pPager->journalOpen || pPager->journalOff>0 || rc!=SQLITE_OK ); return rc; } @@ -3071,11 +3344,11 @@ static void makeClean(PgHdr *pPg){ ** If the journal file could not be written because the disk is full, ** then this routine returns SQLITE_FULL and does an immediate rollback. ** All subsequent write attempts also return SQLITE_FULL until there -** is a call to sqlite3pager_commit() or sqlite3pager_rollback() to +** is a call to sqlite3PagerCommit() or sqlite3PagerRollback() to ** reset. */ -int sqlite3pager_write(void *pData){ - PgHdr *pPg = DATA_TO_PGHDR(pData); +static int pager_write(PgHdr *pPg){ + void *pData = PGHDR_TO_DATA(pPg); Pager *pPager = pPg->pPager; int rc = SQLITE_OK; @@ -3096,7 +3369,7 @@ int sqlite3pager_write(void *pData){ ** to the journal then we can return right away. */ makeDirty(pPg); - if( pPg->inJournal && (pPg->inStmt || pPager->stmtInUse==0) ){ + if( pPg->inJournal && (pageInStatement(pPg) || pPager->stmtInUse==0) ){ pPager->dirtyCache = 1; }else{ @@ -3108,7 +3381,7 @@ int sqlite3pager_write(void *pData){ ** create it if it does not. */ assert( pPager->state!=PAGER_UNLOCK ); - rc = sqlite3pager_begin(pData, 0); + rc = sqlite3PagerBegin(pPg, 0); if( rc!=SQLITE_OK ){ return rc; } @@ -3129,7 +3402,7 @@ int sqlite3pager_write(void *pData){ int szPg; if( MEMDB ){ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); - TRACE3("JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); + PAGERTRACE3("JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); assert( pHist->pOrig==0 ); pHist->pOrig = sqliteMallocRaw( pPager->pageSize ); if( pHist->pOrig ){ @@ -3151,8 +3424,10 @@ int sqlite3pager_write(void *pData){ szPg = pPager->pageSize+8; put32bits(pData2, pPg->pgno); rc = sqlite3OsWrite(pPager->jfd, pData2, szPg); + IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno, + pPager->journalOff, szPg)) pPager->journalOff += szPg; - TRACE4("JOURNAL %d page %d needSync=%d\n", + PAGERTRACE4("JOURNAL %d page %d needSync=%d\n", PAGERID(pPager), pPg->pgno, pPg->needSync); *(u32*)pEnd = saved; @@ -3169,12 +3444,11 @@ int sqlite3pager_write(void *pData){ pPg->needSync = !pPager->noSync; if( pPager->stmtInUse ){ pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); - page_add_to_stmt_list(pPg); } } }else{ pPg->needSync = !pPager->journalStarted && !pPager->noSync; - TRACE4("APPEND %d page %d needSync=%d\n", + PAGERTRACE4("APPEND %d page %d needSync=%d\n", PAGERID(pPager), pPg->pgno, pPg->needSync); } if( pPg->needSync ){ @@ -3188,7 +3462,10 @@ int sqlite3pager_write(void *pData){ ** the statement journal format differs from the standard journal format ** in that it omits the checksums and the header. */ - if( pPager->stmtInUse && !pPg->inStmt && (int)pPg->pgno<=pPager->stmtSize ){ + if( pPager->stmtInUse + && !pageInStatement(pPg) + && (int)pPg->pgno<=pPager->stmtSize + ){ assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); if( MEMDB ){ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); @@ -3197,12 +3474,13 @@ int sqlite3pager_write(void *pData){ if( pHist->pStmt ){ memcpy(pHist->pStmt, PGHDR_TO_DATA(pPg), pPager->pageSize); } - TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); + PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); + page_add_to_stmt_list(pPg); }else{ char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7)-4; put32bits(pData2, pPg->pgno); rc = sqlite3OsWrite(pPager->stfd, pData2, pPager->pageSize+4); - TRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); + PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); if( rc!=SQLITE_OK ){ return rc; } @@ -3210,7 +3488,6 @@ int sqlite3pager_write(void *pData){ assert( pPager->aInStmt!=0 ); pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); } - page_add_to_stmt_list(pPg); } } @@ -3227,13 +3504,83 @@ int sqlite3pager_write(void *pData){ } /* +** This function is used to mark a data-page as writable. It uses +** pager_write() to open a journal file (if it is not already open) +** and write the page *pData to the journal. +** +** The difference between this function and pager_write() is that this +** function also deals with the special case where 2 or more pages +** fit on a single disk sector. In this case all co-resident pages +** must have been written to the journal file before returning. +*/ +int sqlite3PagerWrite(DbPage *pDbPage){ + int rc = SQLITE_OK; + + PgHdr *pPg = pDbPage; + Pager *pPager = pPg->pPager; + Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); + + if( !MEMDB && nPagePerSector>1 ){ + Pgno nPageCount; /* Total number of pages in database file */ + Pgno pg1; /* First page of the sector pPg is located on. */ + int nPage; /* Number of pages starting at pg1 to journal */ + int ii; + + /* Set the doNotSync flag to 1. This is because we cannot allow a journal + ** header to be written between the pages journaled by this function. + */ + assert( pPager->doNotSync==0 ); + pPager->doNotSync = 1; + + /* This trick assumes that both the page-size and sector-size are + ** an integer power of 2. It sets variable pg1 to the identifier + ** of the first page of the sector pPg is located on. + */ + pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1; + + nPageCount = sqlite3PagerPagecount(pPager); + if( pPg->pgno>nPageCount ){ + nPage = (pPg->pgno - pg1)+1; + }else if( (pg1+nPagePerSector-1)>nPageCount ){ + nPage = nPageCount+1-pg1; + }else{ + nPage = nPagePerSector; + } + assert(nPage>0); + assert(pg1<=pPg->pgno); + assert((pg1+nPage)>pPg->pgno); + + for(ii=0; iiaInJournal || pg==pPg->pgno || + pg>pPager->origDbSize || !(pPager->aInJournal[pg/8]&(1<<(pg&7))) + ) { + if( pg!=PAGER_MJ_PGNO(pPager) ){ + PgHdr *pPage; + rc = sqlite3PagerGet(pPager, pg, &pPage); + if( rc==SQLITE_OK ){ + rc = pager_write(pPage); + sqlite3PagerUnref(pPage); + } + } + } + } + + assert( pPager->doNotSync==1 ); + pPager->doNotSync = 0; + }else{ + rc = pager_write(pDbPage); + } + return rc; +} + +/* ** Return TRUE if the page given in the argument was previously passed -** to sqlite3pager_write(). In other words, return TRUE if it is ok +** to sqlite3PagerWrite(). In other words, return TRUE if it is ok ** to change the content of the page. */ #ifndef NDEBUG -int sqlite3pager_iswriteable(void *pData){ - PgHdr *pPg = DATA_TO_PGHDR(pData); +int sqlite3PagerIswriteable(DbPage *pPg){ return pPg->dirty; } #endif @@ -3243,17 +3590,17 @@ int sqlite3pager_iswriteable(void *pData ** Replace the content of a single page with the information in the third ** argument. */ -int sqlite3pager_overwrite(Pager *pPager, Pgno pgno, void *pData){ - void *pPage; +int sqlite3PagerOverwrite(Pager *pPager, Pgno pgno, void *pData){ + PgHdr *pPg; int rc; - rc = sqlite3pager_get(pPager, pgno, &pPage); + rc = sqlite3PagerGet(pPager, pgno, &pPg); if( rc==SQLITE_OK ){ - rc = sqlite3pager_write(pPage); + rc = sqlite3PagerWrite(pPg); if( rc==SQLITE_OK ){ - memcpy(pPage, pData, pPager->pageSize); + memcpy(sqlite3PagerGetData(pPg), pData, pPager->pageSize); } - sqlite3pager_unref(pPage); + sqlite3PagerUnref(pPg); } return rc; } @@ -3269,21 +3616,21 @@ int sqlite3pager_overwrite(Pager *pPager ** that it does not get written to disk. ** ** Tests show that this optimization, together with the -** sqlite3pager_dont_rollback() below, more than double the speed +** sqlite3PagerDontRollback() below, more than double the speed ** of large INSERT operations and quadruple the speed of large DELETEs. ** ** When this routine is called, set the alwaysRollback flag to true. -** Subsequent calls to sqlite3pager_dont_rollback() for the same page +** Subsequent calls to sqlite3PagerDontRollback() for the same page ** will thereafter be ignored. This is necessary to avoid a problem ** where a page with data is added to the freelist during one part of ** a transaction then removed from the freelist during a later part ** of the same transaction and reused for some other purpose. When it ** is first added to the freelist, this routine is called. When reused, -** the dont_rollback() routine is called. But because the page contains -** critical data, we still need to be sure it gets rolled back in spite -** of the dont_rollback() call. +** the sqlite3PagerDontRollback() routine is called. But because the +** page contains critical data, we still need to be sure it gets +** rolled back in spite of the sqlite3PagerDontRollback() call. */ -void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){ +void sqlite3PagerDontWrite(Pager *pPager, Pgno pgno){ PgHdr *pPg; if( MEMDB ) return; @@ -3303,7 +3650,8 @@ void sqlite3pager_dont_write(Pager *pPag ** corruption during the next transaction. */ }else{ - TRACE3("DONT_WRITE page %d of %d\n", pgno, PAGERID(pPager)); + PAGERTRACE3("DONT_WRITE page %d of %d\n", pgno, PAGERID(pPager)); + IOTRACE(("CLEAN %p %d\n", pPager, pgno)) makeClean(pPg); #ifdef SQLITE_CHECK_PAGES pPg->pageHash = pager_pagehash(pPg); @@ -3318,8 +3666,7 @@ void sqlite3pager_dont_write(Pager *pPag ** means that the pager does not have to record the given page in the ** rollback journal. */ -void sqlite3pager_dont_rollback(void *pData){ - PgHdr *pPg = DATA_TO_PGHDR(pData); +void sqlite3PagerDontRollback(DbPage *pPg){ Pager *pPager = pPg->pPager; assert( pPager->state>=PAGER_RESERVED ); @@ -3331,27 +3678,153 @@ void sqlite3pager_dont_rollback(void *pD pPg->inJournal = 1; if( pPager->stmtInUse ){ pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); - page_add_to_stmt_list(pPg); } - TRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, PAGERID(pPager)); + PAGERTRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, PAGERID(pPager)); + IOTRACE(("GARBAGE %p %d\n", pPager, pPg->pgno)) } - if( pPager->stmtInUse && !pPg->inStmt && (int)pPg->pgno<=pPager->stmtSize ){ + if( pPager->stmtInUse + && !pageInStatement(pPg) + && (int)pPg->pgno<=pPager->stmtSize + ){ assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); assert( pPager->aInStmt!=0 ); pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); - page_add_to_stmt_list(pPg); } } /* +** This routine is called to increment the database file change-counter, +** stored at byte 24 of the pager file. +*/ +static int pager_incr_changecounter(Pager *pPager){ + PgHdr *pPgHdr; + u32 change_counter; + int rc; + + if( !pPager->changeCountDone ){ + /* Open page 1 of the file for writing. */ + rc = sqlite3PagerGet(pPager, 1, &pPgHdr); + if( rc!=SQLITE_OK ) return rc; + rc = sqlite3PagerWrite(pPgHdr); + if( rc!=SQLITE_OK ) return rc; + + /* Read the current value at byte 24. */ + change_counter = retrieve32bits(pPgHdr, 24); + + /* Increment the value just read and write it back to byte 24. */ + change_counter++; + put32bits(((char*)PGHDR_TO_DATA(pPgHdr))+24, change_counter); + pPager->iChangeCount = change_counter; + + /* Release the page reference. */ + sqlite3PagerUnref(pPgHdr); + pPager->changeCountDone = 1; + } + return SQLITE_OK; +} + +/* +** Sync the database file for the pager pPager. zMaster points to the name +** of a master journal file that should be written into the individual +** journal file. zMaster may be NULL, which is interpreted as no master +** journal (a single database transaction). +** +** This routine ensures that the journal is synced, all dirty pages written +** to the database file and the database file synced. The only thing that +** remains to commit the transaction is to delete the journal file (or +** master journal file if specified). +** +** Note that if zMaster==NULL, this does not overwrite a previous value +** passed to an sqlite3PagerCommitPhaseOne() call. +** +** If parameter nTrunc is non-zero, then the pager file is truncated to +** nTrunc pages (this is used by auto-vacuum databases). +*/ +int sqlite3PagerCommitPhaseOne(Pager *pPager, const char *zMaster, Pgno nTrunc){ + int rc = SQLITE_OK; + + PAGERTRACE4("DATABASE SYNC: File=%s zMaster=%s nTrunc=%d\n", + pPager->zFilename, zMaster, nTrunc); + + /* If this is an in-memory db, or no pages have been written to, or this + ** function has already been called, it is a no-op. + */ + if( pPager->state!=PAGER_SYNCED && !MEMDB && pPager->dirtyCache ){ + PgHdr *pPg; + assert( pPager->journalOpen ); + + /* If a master journal file name has already been written to the + ** journal file, then no sync is required. This happens when it is + ** written, then the process fails to upgrade from a RESERVED to an + ** EXCLUSIVE lock. The next time the process tries to commit the + ** transaction the m-j name will have already been written. + */ + if( !pPager->setMaster ){ + rc = pager_incr_changecounter(pPager); + if( rc!=SQLITE_OK ) goto sync_exit; +#ifndef SQLITE_OMIT_AUTOVACUUM + if( nTrunc!=0 ){ + /* If this transaction has made the database smaller, then all pages + ** being discarded by the truncation must be written to the journal + ** file. + */ + Pgno i; + int iSkip = PAGER_MJ_PGNO(pPager); + for( i=nTrunc+1; i<=pPager->origDbSize; i++ ){ + if( !(pPager->aInJournal[i/8] & (1<<(i&7))) && i!=iSkip ){ + rc = sqlite3PagerGet(pPager, i, &pPg); + if( rc!=SQLITE_OK ) goto sync_exit; + rc = sqlite3PagerWrite(pPg); + sqlite3PagerUnref(pPg); + if( rc!=SQLITE_OK ) goto sync_exit; + } + } + } +#endif + rc = writeMasterJournal(pPager, zMaster); + if( rc!=SQLITE_OK ) goto sync_exit; + rc = syncJournal(pPager); + if( rc!=SQLITE_OK ) goto sync_exit; + } + +#ifndef SQLITE_OMIT_AUTOVACUUM + if( nTrunc!=0 ){ + rc = sqlite3PagerTruncate(pPager, nTrunc); + if( rc!=SQLITE_OK ) goto sync_exit; + } +#endif + + /* Write all dirty pages to the database file */ + pPg = pager_get_all_dirty_pages(pPager); + rc = pager_write_pagelist(pPg); + if( rc!=SQLITE_OK ) goto sync_exit; + pPager->pDirty = 0; + + /* Sync the database file. */ + if( !pPager->noSync ){ + rc = sqlite3OsSync(pPager->fd, 0); + } + IOTRACE(("DBSYNC %p\n", pPager)) + + pPager->state = PAGER_SYNCED; + }else if( MEMDB && nTrunc!=0 ){ + rc = sqlite3PagerTruncate(pPager, nTrunc); + } + +sync_exit: + return rc; +} + + +/* ** Commit all changes to the database and release the write lock. ** ** If the commit fails for any reason, a rollback attempt is made ** and an error code is returned. If the commit worked, SQLITE_OK ** is returned. */ -int sqlite3pager_commit(Pager *pPager){ +int sqlite3PagerCommitPhaseTwo(Pager *pPager){ int rc; PgHdr *pPg; @@ -3361,16 +3834,17 @@ int sqlite3pager_commit(Pager *pPager){ if( pPager->statedirty = 0; pPg->inJournal = 0; - pPg->inStmt = 0; + pHist->inStmt = 0; pPg->needSync = 0; - pPg->pPrevStmt = pPg->pNextStmt = 0; + pHist->pPrevStmt = pHist->pNextStmt = 0; pPg = pPg->pDirty; } pPager->pDirty = 0; @@ -3386,19 +3860,10 @@ int sqlite3pager_commit(Pager *pPager){ pPager->state = PAGER_SHARED; return SQLITE_OK; } - if( pPager->dirtyCache==0 ){ - /* Exit early (without doing the time-consuming sqlite3OsSync() calls) - ** if there have been no changes to the database file. */ - assert( pPager->needSync==0 ); - rc = pager_unwritelock(pPager); - return rc; - } - assert( pPager->journalOpen ); - rc = sqlite3pager_sync(pPager, 0, 0); - if( rc==SQLITE_OK ){ - rc = pager_unwritelock(pPager); - } - return rc; + assert( pPager->journalOpen || !pPager->dirtyCache ); + assert( pPager->state==PAGER_SYNCED || !pPager->dirtyCache ); + rc = pager_end_transaction(pPager); + return pager_error(pPager, rc); } /* @@ -3407,15 +3872,15 @@ int sqlite3pager_commit(Pager *pPager){ ** The journal is deleted. ** ** This routine cannot fail unless some other process is not following -** the correct locking protocol (SQLITE_PROTOCOL) or unless some other +** the correct locking protocol or unless some other ** process is writing trash into the journal file (SQLITE_CORRUPT) or ** unless a prior malloc() failed (SQLITE_NOMEM). Appropriate error ** codes are returned for all these occasions. Otherwise, ** SQLITE_OK is returned. */ -int sqlite3pager_rollback(Pager *pPager){ +int sqlite3PagerRollback(Pager *pPager){ int rc; - TRACE2("ROLLBACK %d\n", PAGERID(pPager)); + PAGERTRACE2("ROLLBACK %d\n", PAGERID(pPager)); if( MEMDB ){ PgHdr *p; for(p=pPager->pAll; p; p=p->pNextAll){ @@ -3430,49 +3895,50 @@ int sqlite3pager_rollback(Pager *pPager) pHist = PGHDR_TO_HIST(p, pPager); if( pHist->pOrig ){ memcpy(PGHDR_TO_DATA(p), pHist->pOrig, pPager->pageSize); - TRACE3("ROLLBACK-PAGE %d of %d\n", p->pgno, PAGERID(pPager)); + PAGERTRACE3("ROLLBACK-PAGE %d of %d\n", p->pgno, PAGERID(pPager)); }else{ - TRACE3("PAGE %d is clean on %d\n", p->pgno, PAGERID(pPager)); + PAGERTRACE3("PAGE %d is clean on %d\n", p->pgno, PAGERID(pPager)); } clearHistory(pHist); p->dirty = 0; p->inJournal = 0; - p->inStmt = 0; - p->pPrevStmt = p->pNextStmt = 0; + pHist->inStmt = 0; + pHist->pPrevStmt = pHist->pNextStmt = 0; if( pPager->xReiniter ){ - pPager->xReiniter(PGHDR_TO_DATA(p), pPager->pageSize); + pPager->xReiniter(p, pPager->pageSize); } } pPager->pDirty = 0; pPager->pStmt = 0; pPager->dbSize = pPager->origDbSize; - memoryTruncate(pPager); + pager_truncate_cache(pPager); pPager->stmtInUse = 0; pPager->state = PAGER_SHARED; return SQLITE_OK; } if( !pPager->dirtyCache || !pPager->journalOpen ){ - rc = pager_unwritelock(pPager); + rc = pager_end_transaction(pPager); return rc; } if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ if( pPager->state>=PAGER_EXCLUSIVE ){ - pager_playback(pPager); + pager_playback(pPager, 0); } return pPager->errCode; } if( pPager->state==PAGER_RESERVED ){ int rc2; - rc = pager_reload_cache(pPager); - rc2 = pager_unwritelock(pPager); + rc = pager_playback(pPager, 0); + rc2 = pager_end_transaction(pPager); if( rc==SQLITE_OK ){ rc = rc2; } }else{ - rc = pager_playback(pPager); + rc = pager_playback(pPager, 0); } + /* pager_reset(pPager); */ pPager->dbSize = -1; /* If an error occurs during a ROLLBACK, we can no longer trust the pager @@ -3486,14 +3952,14 @@ int sqlite3pager_rollback(Pager *pPager) ** Return TRUE if the database file is opened read-only. Return FALSE ** if the database is (in theory) writable. */ -int sqlite3pager_isreadonly(Pager *pPager){ +int sqlite3PagerIsreadonly(Pager *pPager){ return pPager->readOnly; } /* ** Return the number of references to the pager. */ -int sqlite3pager_refcount(Pager *pPager){ +int sqlite3PagerRefcount(Pager *pPager){ return pPager->nRef; } @@ -3501,7 +3967,7 @@ int sqlite3pager_refcount(Pager *pPager) /* ** This routine is used for testing and analysis only. */ -int *sqlite3pager_stats(Pager *pPager){ +int *sqlite3PagerStats(Pager *pPager){ static int a[11]; a[0] = pPager->nRef; a[1] = pPager->nPage; @@ -3511,7 +3977,7 @@ int *sqlite3pager_stats(Pager *pPager){ a[5] = pPager->errCode; a[6] = pPager->nHit; a[7] = pPager->nMiss; - a[8] = pPager->nOvfl; + a[8] = 0; /* Used to be pPager->nOvfl */ a[9] = pPager->nRead; a[10] = pPager->nWrite; return a; @@ -3525,13 +3991,12 @@ int *sqlite3pager_stats(Pager *pPager){ ** open. A new statement journal is created that can be used to rollback ** changes of a single SQL command within a larger transaction. */ -int sqlite3pager_stmt_begin(Pager *pPager){ +int sqlite3PagerStmtBegin(Pager *pPager){ int rc; - char zTemp[SQLITE_TEMPNAME_SIZE]; assert( !pPager->stmtInUse ); assert( pPager->state>=PAGER_SHARED ); assert( pPager->dbSize>=0 ); - TRACE2("STMT-BEGIN %d\n", PAGERID(pPager)); + PAGERTRACE2("STMT-BEGIN %d\n", PAGERID(pPager)); if( MEMDB ){ pPager->stmtInUse = 1; pPager->stmtSize = pPager->dbSize; @@ -3557,7 +4022,7 @@ int sqlite3pager_stmt_begin(Pager *pPage pPager->stmtHdrOff = 0; pPager->stmtCksum = pPager->cksumInit; if( !pPager->stmtOpen ){ - rc = sqlite3pager_opentemp(zTemp, &pPager->stfd); + rc = sqlite3PagerOpentemp(&pPager->stfd); if( rc ) goto stmt_begin_failed; pPager->stmtOpen = 1; pPager->stmtNRec = 0; @@ -3576,23 +4041,22 @@ stmt_begin_failed: /* ** Commit a statement. */ -int sqlite3pager_stmt_commit(Pager *pPager){ +int sqlite3PagerStmtCommit(Pager *pPager){ if( pPager->stmtInUse ){ PgHdr *pPg, *pNext; - TRACE2("STMT-COMMIT %d\n", PAGERID(pPager)); + PAGERTRACE2("STMT-COMMIT %d\n", PAGERID(pPager)); if( !MEMDB ){ sqlite3OsSeek(pPager->stfd, 0); /* sqlite3OsTruncate(pPager->stfd, 0); */ sqliteFree( pPager->aInStmt ); pPager->aInStmt = 0; - } - for(pPg=pPager->pStmt; pPg; pPg=pNext){ - pNext = pPg->pNextStmt; - assert( pPg->inStmt ); - pPg->inStmt = 0; - pPg->pPrevStmt = pPg->pNextStmt = 0; - if( MEMDB ){ + }else{ + for(pPg=pPager->pStmt; pPg; pPg=pNext){ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); + pNext = pHist->pNextStmt; + assert( pHist->inStmt ); + pHist->inStmt = 0; + pHist->pPrevStmt = pHist->pNextStmt = 0; sqliteFree(pHist->pStmt); pHist->pStmt = 0; } @@ -3608,14 +4072,15 @@ int sqlite3pager_stmt_commit(Pager *pPag /* ** Rollback a statement. */ -int sqlite3pager_stmt_rollback(Pager *pPager){ +int sqlite3PagerStmtRollback(Pager *pPager){ int rc; if( pPager->stmtInUse ){ - TRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager)); + PAGERTRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager)); if( MEMDB ){ PgHdr *pPg; - for(pPg=pPager->pStmt; pPg; pPg=pPg->pNextStmt){ - PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); + PgHistory *pHist; + for(pPg=pPager->pStmt; pPg; pPg=pHist->pNextStmt){ + pHist = PGHDR_TO_HIST(pPg, pPager); if( pHist->pStmt ){ memcpy(PGHDR_TO_DATA(pPg), pHist->pStmt, pPager->pageSize); sqliteFree(pHist->pStmt); @@ -3623,12 +4088,12 @@ int sqlite3pager_stmt_rollback(Pager *pP } } pPager->dbSize = pPager->stmtSize; - memoryTruncate(pPager); + pager_truncate_cache(pPager); rc = SQLITE_OK; }else{ rc = pager_stmt_playback(pPager); } - sqlite3pager_stmt_commit(pPager); + sqlite3PagerStmtCommit(pPager); }else{ rc = SQLITE_OK; } @@ -3639,21 +4104,21 @@ int sqlite3pager_stmt_rollback(Pager *pP /* ** Return the full pathname of the database file. */ -const char *sqlite3pager_filename(Pager *pPager){ +const char *sqlite3PagerFilename(Pager *pPager){ return pPager->zFilename; } /* ** Return the directory of the database file. */ -const char *sqlite3pager_dirname(Pager *pPager){ +const char *sqlite3PagerDirname(Pager *pPager){ return pPager->zDirectory; } /* ** Return the full pathname of the journal file. */ -const char *sqlite3pager_journalname(Pager *pPager){ +const char *sqlite3PagerJournalname(Pager *pPager){ return pPager->zJournal; } @@ -3661,14 +4126,15 @@ const char *sqlite3pager_journalname(Pag ** Return true if fsync() calls are disabled for this pager. Return FALSE ** if fsync()s are executed normally. */ -int sqlite3pager_nosync(Pager *pPager){ +int sqlite3PagerNosync(Pager *pPager){ return pPager->noSync; } +#ifdef SQLITE_HAS_CODEC /* ** Set the codec for this pager */ -void sqlite3pager_set_codec( +void sqlite3PagerSetCodec( Pager *pPager, void *(*xCodec)(void*,void*,Pgno,int), void *pCodecArg @@ -3676,128 +4142,9 @@ void sqlite3pager_set_codec( pPager->xCodec = xCodec; pPager->pCodecArg = pCodecArg; } - -/* -** This routine is called to increment the database file change-counter, -** stored at byte 24 of the pager file. -*/ -static int pager_incr_changecounter(Pager *pPager){ - void *pPage; - PgHdr *pPgHdr; - u32 change_counter; - int rc; - - /* Open page 1 of the file for writing. */ - rc = sqlite3pager_get(pPager, 1, &pPage); - if( rc!=SQLITE_OK ) return rc; - rc = sqlite3pager_write(pPage); - if( rc!=SQLITE_OK ) return rc; - - /* Read the current value at byte 24. */ - pPgHdr = DATA_TO_PGHDR(pPage); - change_counter = retrieve32bits(pPgHdr, 24); - - /* Increment the value just read and write it back to byte 24. */ - change_counter++; - put32bits(((char*)PGHDR_TO_DATA(pPgHdr))+24, change_counter); - - /* Release the page reference. */ - sqlite3pager_unref(pPage); - return SQLITE_OK; -} - -/* -** Sync the database file for the pager pPager. zMaster points to the name -** of a master journal file that should be written into the individual -** journal file. zMaster may be NULL, which is interpreted as no master -** journal (a single database transaction). -** -** This routine ensures that the journal is synced, all dirty pages written -** to the database file and the database file synced. The only thing that -** remains to commit the transaction is to delete the journal file (or -** master journal file if specified). -** -** Note that if zMaster==NULL, this does not overwrite a previous value -** passed to an sqlite3pager_sync() call. -** -** If parameter nTrunc is non-zero, then the pager file is truncated to -** nTrunc pages (this is used by auto-vacuum databases). -*/ -int sqlite3pager_sync(Pager *pPager, const char *zMaster, Pgno nTrunc){ - int rc = SQLITE_OK; - - TRACE4("DATABASE SYNC: File=%s zMaster=%s nTrunc=%d\n", - pPager->zFilename, zMaster, nTrunc); - - /* If this is an in-memory db, or no pages have been written to, or this - ** function has already been called, it is a no-op. - */ - if( pPager->state!=PAGER_SYNCED && !MEMDB && pPager->dirtyCache ){ - PgHdr *pPg; - assert( pPager->journalOpen ); - - /* If a master journal file name has already been written to the - ** journal file, then no sync is required. This happens when it is - ** written, then the process fails to upgrade from a RESERVED to an - ** EXCLUSIVE lock. The next time the process tries to commit the - ** transaction the m-j name will have already been written. - */ - if( !pPager->setMaster ){ - rc = pager_incr_changecounter(pPager); - if( rc!=SQLITE_OK ) goto sync_exit; -#ifndef SQLITE_OMIT_AUTOVACUUM - if( nTrunc!=0 ){ - /* If this transaction has made the database smaller, then all pages - ** being discarded by the truncation must be written to the journal - ** file. - */ - Pgno i; - void *pPage; - int iSkip = PAGER_MJ_PGNO(pPager); - for( i=nTrunc+1; i<=pPager->origDbSize; i++ ){ - if( !(pPager->aInJournal[i/8] & (1<<(i&7))) && i!=iSkip ){ - rc = sqlite3pager_get(pPager, i, &pPage); - if( rc!=SQLITE_OK ) goto sync_exit; - rc = sqlite3pager_write(pPage); - sqlite3pager_unref(pPage); - if( rc!=SQLITE_OK ) goto sync_exit; - } - } - } #endif - rc = writeMasterJournal(pPager, zMaster); - if( rc!=SQLITE_OK ) goto sync_exit; - rc = syncJournal(pPager); - if( rc!=SQLITE_OK ) goto sync_exit; - } #ifndef SQLITE_OMIT_AUTOVACUUM - if( nTrunc!=0 ){ - rc = sqlite3pager_truncate(pPager, nTrunc); - if( rc!=SQLITE_OK ) goto sync_exit; - } -#endif - - /* Write all dirty pages to the database file */ - pPg = pager_get_all_dirty_pages(pPager); - rc = pager_write_pagelist(pPg); - if( rc!=SQLITE_OK ) goto sync_exit; - - /* Sync the database file. */ - if( !pPager->noSync ){ - rc = sqlite3OsSync(pPager->fd, 0); - } - - pPager->state = PAGER_SYNCED; - }else if( MEMDB && nTrunc!=0 ){ - rc = sqlite3pager_truncate(pPager, nTrunc); - } - -sync_exit: - return rc; -} - -#ifndef SQLITE_OMIT_AUTOVACUUM /* ** Move the page identified by pData to location pgno in the file. ** @@ -3815,16 +4162,16 @@ sync_exit: ** has been removed (CREATE INDEX needs to move a page when a statement ** transaction is active). */ -int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){ - PgHdr *pPg = DATA_TO_PGHDR(pData); +int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno){ PgHdr *pPgOld; int h; Pgno needSyncPgno = 0; assert( pPg->nRef>0 ); - TRACE5("MOVE %d page %d (needSync=%d) moves to %d\n", + PAGERTRACE5("MOVE %d page %d (needSync=%d) moves to %d\n", PAGERID(pPager), pPg->pgno, pPg->needSync, pgno); + IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno)) if( pPg->needSync ){ needSyncPgno = pPg->pgno; @@ -3876,32 +4223,70 @@ int sqlite3pager_movepage(Pager *pPager, ** Pager.aInJournal bit has been set. This needs to be remedied by loading ** the page into the pager-cache and setting the PgHdr.needSync flag. ** - ** The sqlite3pager_get() call may cause the journal to sync. So make + ** The sqlite3PagerGet() call may cause the journal to sync. So make ** sure the Pager.needSync flag is set too. */ int rc; - void *pNeedSync; + PgHdr *pPgHdr; assert( pPager->needSync ); - rc = sqlite3pager_get(pPager, needSyncPgno, &pNeedSync); + rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr); if( rc!=SQLITE_OK ) return rc; pPager->needSync = 1; - DATA_TO_PGHDR(pNeedSync)->needSync = 1; - DATA_TO_PGHDR(pNeedSync)->inJournal = 1; - makeDirty(DATA_TO_PGHDR(pNeedSync)); - sqlite3pager_unref(pNeedSync); + pPgHdr->needSync = 1; + pPgHdr->inJournal = 1; + makeDirty(pPgHdr); + sqlite3PagerUnref(pPgHdr); } return SQLITE_OK; } #endif +/* +** Return a pointer to the data for the specified page. +*/ +void *sqlite3PagerGetData(DbPage *pPg){ + return PGHDR_TO_DATA(pPg); +} + +/* +** Return a pointer to the Pager.nExtra bytes of "extra" space +** allocated along with the specified page. +*/ +void *sqlite3PagerGetExtra(DbPage *pPg){ + Pager *pPager = pPg->pPager; + return (pPager?PGHDR_TO_EXTRA(pPg, pPager):0); +} + +/* +** Get/set the locking-mode for this pager. Parameter eMode must be one +** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or +** PAGER_LOCKINGMODE_EXCLUSIVE. If the parameter is not _QUERY, then +** the locking-mode is set to the value specified. +** +** The returned value is either PAGER_LOCKINGMODE_NORMAL or +** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated) +** locking-mode. +*/ +int sqlite3PagerLockingMode(Pager *pPager, int eMode){ + assert( eMode==PAGER_LOCKINGMODE_QUERY + || eMode==PAGER_LOCKINGMODE_NORMAL + || eMode==PAGER_LOCKINGMODE_EXCLUSIVE ); + assert( PAGER_LOCKINGMODE_QUERY<0 ); + assert( PAGER_LOCKINGMODE_NORMAL>=0 && PAGER_LOCKINGMODE_EXCLUSIVE>=0 ); + if( eMode>=0 && !pPager->tempFile ){ + pPager->exclusiveMode = eMode; + } + return (int)pPager->exclusiveMode; +} + #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) /* ** Return the current state of the file lock for the given pager. ** The return value is one of NO_LOCK, SHARED_LOCK, RESERVED_LOCK, ** PENDING_LOCK, or EXCLUSIVE_LOCK. */ -int sqlite3pager_lockstate(Pager *pPager){ +int sqlite3PagerLockstate(Pager *pPager){ return sqlite3OsLockState(pPager->fd); } #endif @@ -3910,7 +4295,7 @@ int sqlite3pager_lockstate(Pager *pPager /* ** Print a listing of all referenced pages and their ref count. */ -void sqlite3pager_refdump(Pager *pPager){ +void sqlite3PagerRefdump(Pager *pPager){ PgHdr *pPg; for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ if( pPg->nRef<=0 ) continue; ============================================================ --- sqlite/pager.h 2e6d42f4ae004ae748a037b8468112b851c447a7 +++ sqlite/pager.h e79a24cf200b8771366217f5bca414f5b7823f42 @@ -13,7 +13,7 @@ ** 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.52 2006/11/06 21:20:26 drh Exp $ +** @(#) $Id: pager.h,v 1.57 2007/03/30 14:06:34 drh Exp $ */ #ifndef _PAGER_H_ @@ -57,67 +57,91 @@ typedef struct Pager Pager; typedef struct Pager Pager; /* -** Allowed values for the flags parameter to sqlite3pager_open(). +** Handle type for pages. +*/ +typedef struct PgHdr DbPage; + +/* +** Allowed values for the flags parameter to sqlite3PagerOpen(). ** ** NOTE: This values must match the corresponding BTREE_ values in btree.h. */ #define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */ #define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */ +/* +** Valid values for the second argument to sqlite3PagerLockingMode(). +*/ +#define PAGER_LOCKINGMODE_QUERY -1 +#define PAGER_LOCKINGMODE_NORMAL 0 +#define PAGER_LOCKINGMODE_EXCLUSIVE 1 /* ** See source code comments for a detailed description of the following ** routines: */ -int sqlite3pager_open(Pager **ppPager, const char *zFilename, +int sqlite3PagerOpen(Pager **ppPager, const char *zFilename, int nExtra, int flags); -void sqlite3pager_set_busyhandler(Pager*, BusyHandler *pBusyHandler); -void sqlite3pager_set_destructor(Pager*, void(*)(void*,int)); -void sqlite3pager_set_reiniter(Pager*, void(*)(void*,int)); -int sqlite3pager_set_pagesize(Pager*, int); -int sqlite3pager_read_fileheader(Pager*, int, unsigned char*); -void sqlite3pager_set_cachesize(Pager*, int); -int sqlite3pager_close(Pager *pPager); -int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage); -void *sqlite3pager_lookup(Pager *pPager, Pgno pgno); -int sqlite3pager_ref(void*); -int sqlite3pager_unref(void*); -Pgno sqlite3pager_pagenumber(void*); -int sqlite3pager_write(void*); -int sqlite3pager_iswriteable(void*); -int sqlite3pager_overwrite(Pager *pPager, Pgno pgno, void*); -int sqlite3pager_pagecount(Pager*); -int sqlite3pager_truncate(Pager*,Pgno); -int sqlite3pager_begin(void*, int exFlag); -int sqlite3pager_commit(Pager*); -int sqlite3pager_sync(Pager*,const char *zMaster, Pgno); -int sqlite3pager_rollback(Pager*); -int sqlite3pager_isreadonly(Pager*); -int sqlite3pager_stmt_begin(Pager*); -int sqlite3pager_stmt_commit(Pager*); -int sqlite3pager_stmt_rollback(Pager*); -void sqlite3pager_dont_rollback(void*); -void sqlite3pager_dont_write(Pager*, Pgno); -int sqlite3pager_refcount(Pager*); -int *sqlite3pager_stats(Pager*); -void sqlite3pager_set_safety_level(Pager*,int,int); -const char *sqlite3pager_filename(Pager*); -const char *sqlite3pager_dirname(Pager*); -const char *sqlite3pager_journalname(Pager*); -int sqlite3pager_nosync(Pager*); -int sqlite3pager_rename(Pager*, const char *zNewName); -void sqlite3pager_set_codec(Pager*,void*(*)(void*,void*,Pgno,int),void*); -int sqlite3pager_movepage(Pager*,void*,Pgno); -int sqlite3pager_reset(Pager*); -int sqlite3pager_release_memory(int); +void sqlite3PagerSetBusyhandler(Pager*, BusyHandler *pBusyHandler); +void sqlite3PagerSetDestructor(Pager*, void(*)(DbPage*,int)); +void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*,int)); +int sqlite3PagerSetPagesize(Pager*, int); +int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); +void sqlite3PagerSetCachesize(Pager*, int); +int sqlite3PagerClose(Pager *pPager); +int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); +#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0) +DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); +int sqlite3PagerRef(DbPage*); +int sqlite3PagerUnref(DbPage*); +Pgno sqlite3PagerPagenumber(DbPage*); +int sqlite3PagerWrite(DbPage*); +int sqlite3PagerIswriteable(DbPage*); +int sqlite3PagerOverwrite(Pager *pPager, Pgno pgno, void*); +int sqlite3PagerPagecount(Pager*); +int sqlite3PagerTruncate(Pager*,Pgno); +int sqlite3PagerBegin(DbPage*, int exFlag); +int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, Pgno); +int sqlite3PagerCommitPhaseTwo(Pager*); +int sqlite3PagerRollback(Pager*); +int sqlite3PagerIsreadonly(Pager*); +int sqlite3PagerStmtBegin(Pager*); +int sqlite3PagerStmtCommit(Pager*); +int sqlite3PagerStmtRollback(Pager*); +void sqlite3PagerDontRollback(DbPage*); +void sqlite3PagerDontWrite(Pager*, Pgno); +int sqlite3PagerRefcount(Pager*); +int *sqlite3PagerStats(Pager*); +void sqlite3PagerSetSafetyLevel(Pager*,int,int); +const char *sqlite3PagerFilename(Pager*); +const char *sqlite3PagerDirname(Pager*); +const char *sqlite3PagerJournalname(Pager*); +int sqlite3PagerNosync(Pager*); +int sqlite3PagerRename(Pager*, const char *zNewName); +void sqlite3PagerSetCodec(Pager*,void*(*)(void*,void*,Pgno,int),void*); +int sqlite3PagerMovepage(Pager*,DbPage*,Pgno); +int sqlite3PagerReset(Pager*); +int sqlite3PagerReleaseMemory(int); +void *sqlite3PagerGetData(DbPage *); +void *sqlite3PagerGetExtra(DbPage *); +int sqlite3PagerLockingMode(Pager *, int); + #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) -int sqlite3pager_lockstate(Pager*); +int sqlite3PagerLockstate(Pager*); #endif #ifdef SQLITE_TEST -void sqlite3pager_refdump(Pager*); +void sqlite3PagerRefdump(Pager*); int pager3_refinfo_enable; #endif +#ifdef SQLITE_TEST +void disable_simulated_io_errors(void); +void enable_simulated_io_errors(void); +#else +# define disable_simulated_io_errors() +# define enable_simulated_io_errors() +#endif + #endif /* _PAGER_H_ */ ============================================================ --- sqlite/parse.c c0428566a80239da0b429390988f0fec4351e148 +++ sqlite/parse.c b29e3203362be291200999d2e91d01187473f551 @@ -82,7 +82,8 @@ struct AttachKey { int type; Token key; ** This is typically a union of many types, one of ** which is sqlite3ParserTOKENTYPE. The entry in the union ** for base tokens is called "yy0". -** YYSTACKDEPTH is the maximum depth of the parser's stack. +** YYSTACKDEPTH is the maximum depth of the parser's stack. If +** zero the stack is dynamically sized using realloc() ** sqlite3ParserARG_SDECL A static variable declaration for the %extra_argument ** sqlite3ParserARG_PDECL A parameter declaration for the %extra_argument ** sqlite3ParserARG_STORE Code to store %extra_argument into yypParser @@ -93,36 +94,38 @@ struct AttachKey { int type; Token key; ** defined, then do no error processing. */ #define YYCODETYPE unsigned char -#define YYNOCODE 249 +#define YYNOCODE 248 #define YYACTIONTYPE unsigned short int -#define YYWILDCARD 60 +#define YYWILDCARD 59 #define sqlite3ParserTOKENTYPE Token typedef union { sqlite3ParserTOKENTYPE yy0; - Select* yy43; - TriggerStep* yy75; - struct LimitVal yy84; - struct LikeOp yy86; - Expr * yy158; - Token yy178; - struct {int value; int mask;} yy207; - ExprList* yy242; - int yy316; - IdList* yy352; - struct TrigEvent yy354; - SrcList* yy419; - Expr* yy450; - int yy497; + int yy46; + struct LikeOp yy72; + Expr* yy172; + ExprList* yy174; + Select* yy219; + struct LimitVal yy234; + TriggerStep* yy243; + struct TrigEvent yy370; + SrcList* yy373; + Expr * yy386; + struct {int value; int mask;} yy405; + Token yy410; + IdList* yy432; + int yy495; } YYMINORTYPE; +#ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 +#endif #define sqlite3ParserARG_SDECL Parse *pParse; #define sqlite3ParserARG_PDECL ,Parse *pParse #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse #define sqlite3ParserARG_STORE yypParser->pParse = pParse -#define YYNSTATE 587 -#define YYNRULE 312 -#define YYERRORSYMBOL 139 -#define YYERRSYMDT yy497 +#define YYNSTATE 586 +#define YYNRULE 311 +#define YYERRORSYMBOL 138 +#define YYERRSYMDT yy495 #define YYFALLBACK 1 #define YY_NO_ACTION (YYNSTATE+YYNRULE+2) #define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1) @@ -176,415 +179,415 @@ static const YYACTIONTYPE yy_action[] = ** yy_default[] Default action for each state. */ static const YYACTIONTYPE yy_action[] = { - /* 0 */ 289, 900, 121, 586, 205, 169, 2, 435, 61, 61, - /* 10 */ 61, 61, 435, 63, 63, 63, 63, 64, 64, 65, - /* 20 */ 65, 65, 66, 230, 198, 299, 420, 426, 68, 63, + /* 0 */ 289, 898, 121, 585, 405, 169, 2, 435, 61, 61, + /* 10 */ 61, 61, 517, 63, 63, 63, 63, 64, 64, 65, + /* 20 */ 65, 65, 66, 230, 387, 384, 420, 426, 68, 63, /* 30 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 230, - /* 40 */ 67, 447, 69, 151, 230, 60, 59, 294, 430, 431, - /* 50 */ 427, 427, 62, 62, 61, 61, 61, 61, 411, 63, - /* 60 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 230, - /* 70 */ 289, 487, 515, 435, 570, 415, 80, 67, 435, 69, - /* 80 */ 151, 63, 63, 63, 63, 64, 64, 65, 65, 65, - /* 90 */ 66, 230, 569, 568, 248, 386, 420, 426, 2, 572, - /* 100 */ 58, 115, 238, 340, 243, 341, 173, 417, 417, 417, - /* 110 */ 570, 387, 384, 249, 289, 60, 59, 294, 430, 431, - /* 120 */ 427, 427, 62, 62, 61, 61, 61, 61, 569, 63, - /* 130 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 230, - /* 140 */ 420, 426, 92, 64, 64, 65, 65, 65, 66, 230, - /* 150 */ 245, 392, 56, 171, 566, 207, 406, 443, 208, 60, - /* 160 */ 59, 294, 430, 431, 427, 427, 62, 62, 61, 61, - /* 170 */ 61, 61, 205, 63, 63, 63, 63, 64, 64, 65, - /* 180 */ 65, 65, 66, 230, 289, 368, 522, 411, 522, 111, - /* 190 */ 378, 207, 447, 467, 223, 403, 21, 532, 21, 172, - /* 200 */ 157, 317, 66, 230, 336, 404, 520, 443, 208, 486, - /* 210 */ 420, 426, 146, 147, 517, 488, 489, 393, 394, 148, - /* 220 */ 531, 224, 487, 410, 41, 407, 415, 567, 289, 60, - /* 230 */ 59, 294, 430, 431, 427, 427, 62, 62, 61, 61, - /* 240 */ 61, 61, 476, 63, 63, 63, 63, 64, 64, 65, - /* 250 */ 65, 65, 66, 230, 420, 426, 491, 492, 417, 417, - /* 260 */ 417, 155, 549, 331, 211, 65, 65, 65, 66, 230, - /* 270 */ 546, 492, 289, 60, 59, 294, 430, 431, 427, 427, - /* 280 */ 62, 62, 61, 61, 61, 61, 467, 63, 63, 63, - /* 290 */ 63, 64, 64, 65, 65, 65, 66, 230, 420, 426, - /* 300 */ 548, 299, 178, 297, 522, 342, 345, 346, 472, 67, - /* 310 */ 460, 69, 151, 577, 21, 338, 347, 60, 59, 294, - /* 320 */ 430, 431, 427, 427, 62, 62, 61, 61, 61, 61, - /* 330 */ 530, 63, 63, 63, 63, 64, 64, 65, 65, 65, - /* 340 */ 66, 230, 409, 523, 76, 289, 408, 478, 452, 482, - /* 350 */ 392, 369, 266, 265, 283, 149, 405, 445, 521, 165, - /* 360 */ 453, 317, 205, 67, 517, 69, 151, 529, 503, 152, - /* 370 */ 248, 420, 426, 454, 528, 493, 161, 115, 238, 340, - /* 380 */ 243, 341, 173, 410, 35, 494, 580, 288, 79, 249, - /* 390 */ 60, 59, 294, 430, 431, 427, 427, 62, 62, 61, - /* 400 */ 61, 61, 61, 411, 63, 63, 63, 63, 64, 64, - /* 410 */ 65, 65, 65, 66, 230, 289, 393, 394, 178, 485, - /* 420 */ 508, 342, 345, 346, 178, 296, 317, 342, 345, 346, - /* 430 */ 366, 317, 347, 20, 317, 141, 317, 457, 347, 150, - /* 440 */ 509, 420, 426, 22, 295, 438, 439, 435, 410, 35, - /* 450 */ 328, 260, 472, 410, 28, 232, 410, 35, 410, 36, - /* 460 */ 60, 59, 294, 430, 431, 427, 427, 62, 62, 61, - /* 470 */ 61, 61, 61, 411, 63, 63, 63, 63, 64, 64, - /* 480 */ 65, 65, 65, 66, 230, 289, 436, 481, 23, 502, - /* 490 */ 298, 234, 380, 301, 317, 217, 317, 476, 333, 317, - /* 500 */ 392, 317, 457, 337, 168, 157, 421, 422, 207, 231, - /* 510 */ 457, 420, 426, 435, 313, 388, 410, 35, 410, 49, - /* 520 */ 204, 410, 41, 410, 49, 410, 3, 197, 424, 425, - /* 530 */ 60, 59, 294, 430, 431, 427, 427, 62, 62, 61, - /* 540 */ 61, 61, 61, 382, 63, 63, 63, 63, 64, 64, - /* 550 */ 65, 65, 65, 66, 230, 289, 443, 423, 357, 252, - /* 560 */ 434, 411, 210, 292, 308, 350, 393, 394, 448, 309, - /* 570 */ 456, 322, 438, 439, 320, 1, 433, 433, 19, 392, - /* 580 */ 541, 420, 426, 191, 540, 375, 584, 891, 543, 891, - /* 590 */ 584, 890, 174, 890, 472, 392, 358, 445, 323, 165, - /* 600 */ 60, 59, 294, 430, 431, 427, 427, 62, 62, 61, - /* 610 */ 61, 61, 61, 383, 63, 63, 63, 63, 64, 64, - /* 620 */ 65, 65, 65, 66, 230, 289, 370, 581, 9, 452, - /* 630 */ 91, 581, 10, 236, 409, 207, 392, 359, 408, 392, - /* 640 */ 156, 453, 169, 362, 435, 393, 394, 320, 291, 433, - /* 650 */ 433, 420, 426, 249, 454, 320, 327, 433, 433, 260, - /* 660 */ 462, 393, 394, 515, 515, 545, 515, 463, 270, 289, - /* 670 */ 60, 59, 294, 430, 431, 427, 427, 62, 62, 61, - /* 680 */ 61, 61, 61, 82, 63, 63, 63, 63, 64, 64, - /* 690 */ 65, 65, 65, 66, 230, 420, 426, 480, 302, 216, - /* 700 */ 261, 303, 393, 394, 822, 393, 394, 273, 515, 271, - /* 710 */ 435, 515, 334, 289, 60, 59, 294, 430, 431, 427, - /* 720 */ 427, 62, 62, 61, 61, 61, 61, 233, 63, 63, - /* 730 */ 63, 63, 64, 64, 65, 65, 65, 66, 230, 420, - /* 740 */ 426, 247, 247, 304, 247, 318, 306, 587, 387, 384, - /* 750 */ 395, 396, 397, 320, 219, 433, 433, 289, 60, 70, - /* 760 */ 294, 430, 431, 427, 427, 62, 62, 61, 61, 61, - /* 770 */ 61, 317, 63, 63, 63, 63, 64, 64, 65, 65, - /* 780 */ 65, 66, 230, 420, 426, 476, 247, 391, 272, 247, - /* 790 */ 539, 356, 539, 410, 29, 175, 176, 177, 162, 260, - /* 800 */ 260, 289, 5, 59, 294, 430, 431, 427, 427, 62, - /* 810 */ 62, 61, 61, 61, 61, 377, 63, 63, 63, 63, - /* 820 */ 64, 64, 65, 65, 65, 66, 230, 420, 426, 392, - /* 830 */ 311, 120, 392, 319, 205, 260, 366, 465, 254, 189, - /* 840 */ 556, 558, 260, 75, 260, 77, 307, 376, 294, 430, - /* 850 */ 431, 427, 427, 62, 62, 61, 61, 61, 61, 260, - /* 860 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66, - /* 870 */ 230, 72, 324, 411, 4, 260, 559, 258, 293, 256, - /* 880 */ 174, 125, 317, 560, 317, 274, 321, 72, 324, 193, - /* 890 */ 4, 153, 621, 180, 293, 393, 394, 367, 393, 394, - /* 900 */ 374, 218, 321, 326, 410, 24, 410, 33, 183, 317, - /* 910 */ 428, 206, 441, 441, 447, 317, 276, 317, 55, 326, - /* 920 */ 363, 468, 239, 411, 469, 411, 455, 411, 13, 144, - /* 930 */ 447, 410, 53, 240, 74, 73, 291, 410, 52, 410, - /* 940 */ 96, 116, 411, 72, 315, 316, 582, 474, 415, 170, - /* 950 */ 74, 73, 479, 317, 507, 506, 317, 500, 416, 72, - /* 960 */ 315, 316, 72, 324, 415, 4, 205, 317, 329, 293, - /* 970 */ 317, 458, 483, 444, 13, 410, 94, 321, 410, 99, - /* 980 */ 417, 417, 417, 418, 419, 12, 583, 466, 317, 410, - /* 990 */ 100, 471, 410, 110, 326, 475, 417, 417, 417, 418, - /* 1000 */ 419, 12, 497, 498, 512, 447, 125, 159, 244, 317, - /* 1010 */ 410, 112, 220, 221, 222, 102, 537, 538, 317, 251, - /* 1020 */ 317, 125, 317, 504, 505, 74, 73, 349, 202, 125, - /* 1030 */ 278, 410, 17, 510, 72, 315, 316, 279, 524, 415, - /* 1040 */ 410, 97, 410, 34, 410, 95, 317, 511, 544, 200, - /* 1050 */ 125, 548, 552, 253, 170, 317, 199, 255, 317, 201, - /* 1060 */ 553, 257, 89, 317, 259, 563, 317, 89, 410, 25, - /* 1070 */ 317, 417, 417, 417, 418, 419, 12, 410, 54, 186, - /* 1080 */ 410, 113, 354, 317, 264, 410, 114, 317, 410, 26, - /* 1090 */ 361, 364, 410, 37, 579, 365, 287, 317, 267, 317, - /* 1100 */ 143, 317, 373, 275, 265, 410, 38, 268, 290, 410, - /* 1110 */ 27, 317, 269, 205, 555, 565, 317, 277, 317, 410, - /* 1120 */ 39, 410, 40, 410, 42, 317, 280, 317, 281, 317, - /* 1130 */ 576, 317, 225, 410, 43, 401, 503, 379, 410, 44, - /* 1140 */ 410, 30, 317, 325, 440, 317, 461, 410, 31, 410, - /* 1150 */ 45, 410, 46, 410, 47, 442, 317, 551, 317, 464, - /* 1160 */ 317, 241, 513, 516, 410, 48, 344, 410, 32, 562, - /* 1170 */ 160, 390, 398, 399, 400, 8, 314, 412, 410, 11, - /* 1180 */ 410, 50, 410, 51, 82, 332, 226, 81, 330, 227, - /* 1190 */ 57, 406, 414, 228, 78, 167, 229, 209, 83, 413, - /* 1200 */ 459, 122, 335, 339, 500, 490, 235, 495, 242, 473, - /* 1210 */ 237, 300, 477, 499, 496, 501, 103, 284, 246, 514, - /* 1220 */ 518, 519, 525, 526, 527, 351, 533, 181, 285, 182, - /* 1230 */ 184, 214, 353, 185, 535, 187, 215, 355, 86, 118, - /* 1240 */ 360, 547, 190, 129, 139, 371, 262, 372, 130, 536, - /* 1250 */ 554, 310, 131, 132, 573, 90, 133, 135, 93, 138, - /* 1260 */ 578, 574, 575, 109, 213, 561, 101, 119, 389, 18, - /* 1270 */ 98, 402, 622, 623, 163, 164, 429, 312, 432, 71, - /* 1280 */ 449, 437, 446, 140, 154, 166, 450, 6, 451, 470, - /* 1290 */ 7, 123, 14, 13, 124, 158, 484, 212, 84, 343, - /* 1300 */ 104, 348, 250, 105, 85, 117, 106, 240, 179, 352, - /* 1310 */ 142, 534, 126, 305, 170, 263, 188, 107, 286, 550, - /* 1320 */ 127, 128, 15, 542, 192, 87, 194, 88, 195, 557, - /* 1330 */ 196, 136, 137, 134, 16, 108, 571, 282, 381, 564, - /* 1340 */ 203, 145, 385, 901, 585, + /* 40 */ 443, 208, 392, 447, 60, 59, 294, 430, 431, 427, + /* 50 */ 427, 62, 62, 61, 61, 61, 61, 205, 63, 63, + /* 60 */ 63, 63, 64, 64, 65, 65, 65, 66, 230, 289, + /* 70 */ 368, 316, 435, 487, 205, 80, 67, 415, 69, 151, + /* 80 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66, + /* 90 */ 230, 515, 162, 410, 35, 420, 426, 443, 571, 58, + /* 100 */ 64, 64, 65, 65, 65, 66, 230, 393, 394, 417, + /* 110 */ 417, 417, 289, 60, 59, 294, 430, 431, 427, 427, + /* 120 */ 62, 62, 61, 61, 61, 61, 302, 63, 63, 63, + /* 130 */ 63, 64, 64, 65, 65, 65, 66, 230, 420, 426, + /* 140 */ 92, 65, 65, 65, 66, 230, 392, 456, 472, 67, + /* 150 */ 56, 69, 151, 169, 406, 435, 60, 59, 294, 430, + /* 160 */ 431, 427, 427, 62, 62, 61, 61, 61, 61, 247, + /* 170 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66, + /* 180 */ 230, 289, 569, 522, 292, 620, 111, 478, 515, 447, + /* 190 */ 230, 316, 403, 21, 67, 460, 69, 151, 66, 230, + /* 200 */ 568, 443, 208, 67, 224, 69, 151, 420, 426, 146, + /* 210 */ 147, 393, 394, 410, 41, 386, 148, 531, 2, 487, + /* 220 */ 435, 566, 232, 415, 289, 60, 59, 294, 430, 431, + /* 230 */ 427, 427, 62, 62, 61, 61, 61, 61, 316, 63, + /* 240 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 230, + /* 250 */ 420, 426, 486, 330, 211, 417, 417, 417, 359, 270, + /* 260 */ 410, 41, 378, 207, 362, 542, 245, 289, 60, 59, + /* 270 */ 294, 430, 431, 427, 427, 62, 62, 61, 61, 61, + /* 280 */ 61, 392, 63, 63, 63, 63, 64, 64, 65, 65, + /* 290 */ 65, 66, 230, 420, 426, 260, 299, 273, 522, 271, + /* 300 */ 522, 210, 370, 319, 223, 433, 433, 532, 21, 576, + /* 310 */ 21, 60, 59, 294, 430, 431, 427, 427, 62, 62, + /* 320 */ 61, 61, 61, 61, 191, 63, 63, 63, 63, 64, + /* 330 */ 64, 65, 65, 65, 66, 230, 261, 316, 239, 76, + /* 340 */ 289, 544, 299, 149, 482, 150, 393, 394, 178, 240, + /* 350 */ 569, 341, 344, 345, 404, 520, 445, 322, 165, 410, + /* 360 */ 28, 540, 346, 517, 248, 539, 420, 426, 568, 567, + /* 370 */ 161, 115, 238, 339, 243, 340, 173, 358, 272, 411, + /* 380 */ 821, 488, 79, 249, 60, 59, 294, 430, 431, 427, + /* 390 */ 427, 62, 62, 61, 61, 61, 61, 530, 63, 63, + /* 400 */ 63, 63, 64, 64, 65, 65, 65, 66, 230, 289, + /* 410 */ 248, 178, 465, 485, 341, 344, 345, 115, 238, 339, + /* 420 */ 243, 340, 173, 82, 316, 346, 316, 491, 492, 249, + /* 430 */ 565, 207, 152, 523, 489, 420, 426, 178, 529, 503, + /* 440 */ 341, 344, 345, 407, 472, 528, 410, 35, 410, 35, + /* 450 */ 171, 346, 198, 60, 59, 294, 430, 431, 427, 427, + /* 460 */ 62, 62, 61, 61, 61, 61, 411, 63, 63, 63, + /* 470 */ 63, 64, 64, 65, 65, 65, 66, 230, 289, 548, + /* 480 */ 579, 288, 502, 234, 411, 316, 411, 316, 296, 283, + /* 490 */ 298, 316, 445, 521, 165, 476, 172, 157, 421, 422, + /* 500 */ 457, 335, 457, 144, 420, 426, 366, 410, 35, 410, + /* 510 */ 36, 435, 1, 410, 49, 327, 392, 547, 193, 424, + /* 520 */ 425, 156, 60, 59, 294, 430, 431, 427, 427, 62, + /* 530 */ 62, 61, 61, 61, 61, 333, 63, 63, 63, 63, + /* 540 */ 64, 64, 65, 65, 65, 66, 230, 289, 423, 332, + /* 550 */ 452, 252, 411, 295, 438, 439, 297, 316, 349, 307, + /* 560 */ 231, 457, 453, 321, 438, 439, 392, 369, 266, 265, + /* 570 */ 189, 217, 392, 420, 426, 454, 435, 493, 205, 410, + /* 580 */ 49, 393, 394, 583, 889, 174, 889, 494, 545, 492, + /* 590 */ 392, 60, 59, 294, 430, 431, 427, 427, 62, 62, + /* 600 */ 61, 61, 61, 61, 411, 63, 63, 63, 63, 64, + /* 610 */ 64, 65, 65, 65, 66, 230, 289, 207, 586, 387, + /* 620 */ 384, 91, 10, 580, 336, 308, 392, 207, 367, 480, + /* 630 */ 316, 393, 394, 583, 888, 219, 888, 393, 394, 476, + /* 640 */ 291, 233, 420, 426, 481, 249, 410, 3, 434, 260, + /* 650 */ 317, 363, 410, 29, 448, 393, 394, 468, 260, 289, + /* 660 */ 60, 59, 294, 430, 431, 427, 427, 62, 62, 61, + /* 670 */ 61, 61, 61, 580, 63, 63, 63, 63, 64, 64, + /* 680 */ 65, 65, 65, 66, 230, 420, 426, 391, 312, 388, + /* 690 */ 555, 393, 394, 75, 204, 77, 395, 396, 397, 557, + /* 700 */ 357, 197, 289, 60, 59, 294, 430, 431, 427, 427, + /* 710 */ 62, 62, 61, 61, 61, 61, 316, 63, 63, 63, + /* 720 */ 63, 64, 64, 65, 65, 65, 66, 230, 420, 426, + /* 730 */ 319, 116, 433, 433, 319, 411, 433, 433, 410, 24, + /* 740 */ 319, 515, 433, 433, 515, 289, 60, 70, 294, 430, + /* 750 */ 431, 427, 427, 62, 62, 61, 61, 61, 61, 375, + /* 760 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66, + /* 770 */ 230, 420, 426, 538, 356, 538, 216, 260, 472, 303, + /* 780 */ 175, 176, 177, 254, 476, 515, 260, 383, 289, 5, + /* 790 */ 59, 294, 430, 431, 427, 427, 62, 62, 61, 61, + /* 800 */ 61, 61, 316, 63, 63, 63, 63, 64, 64, 65, + /* 810 */ 65, 65, 66, 230, 420, 426, 392, 236, 380, 247, + /* 820 */ 304, 258, 247, 256, 410, 33, 260, 558, 125, 467, + /* 830 */ 515, 416, 168, 157, 294, 430, 431, 427, 427, 62, + /* 840 */ 62, 61, 61, 61, 61, 306, 63, 63, 63, 63, + /* 850 */ 64, 64, 65, 65, 65, 66, 230, 72, 323, 452, + /* 860 */ 4, 153, 22, 247, 293, 305, 435, 559, 316, 382, + /* 870 */ 316, 453, 320, 72, 323, 316, 4, 366, 316, 180, + /* 880 */ 293, 393, 394, 20, 454, 141, 326, 316, 320, 325, + /* 890 */ 410, 53, 410, 52, 316, 411, 155, 410, 96, 447, + /* 900 */ 410, 94, 316, 500, 316, 325, 328, 469, 247, 410, + /* 910 */ 99, 444, 260, 411, 318, 447, 410, 100, 316, 74, + /* 920 */ 73, 467, 183, 260, 410, 110, 410, 112, 72, 314, + /* 930 */ 315, 435, 337, 415, 458, 74, 73, 479, 316, 377, + /* 940 */ 410, 17, 218, 19, 72, 314, 315, 72, 323, 415, + /* 950 */ 4, 205, 316, 274, 293, 316, 411, 466, 205, 409, + /* 960 */ 410, 97, 320, 408, 374, 417, 417, 417, 418, 419, + /* 970 */ 12, 376, 316, 206, 410, 34, 174, 410, 95, 325, + /* 980 */ 55, 417, 417, 417, 418, 419, 12, 310, 120, 447, + /* 990 */ 428, 159, 9, 260, 410, 25, 220, 221, 222, 102, + /* 1000 */ 441, 441, 316, 471, 409, 316, 475, 316, 408, 74, + /* 1010 */ 73, 436, 202, 23, 278, 455, 244, 13, 72, 314, + /* 1020 */ 315, 279, 316, 415, 410, 54, 316, 410, 113, 410, + /* 1030 */ 114, 291, 581, 200, 276, 547, 462, 497, 498, 199, + /* 1040 */ 316, 504, 201, 463, 410, 26, 316, 524, 410, 37, + /* 1050 */ 316, 474, 316, 170, 253, 417, 417, 417, 418, 419, + /* 1060 */ 12, 505, 410, 38, 510, 483, 316, 13, 410, 27, + /* 1070 */ 508, 582, 410, 39, 410, 40, 316, 255, 507, 506, + /* 1080 */ 512, 316, 125, 316, 511, 373, 275, 265, 410, 42, + /* 1090 */ 509, 290, 316, 251, 316, 125, 205, 257, 410, 43, + /* 1100 */ 316, 259, 316, 410, 44, 410, 30, 348, 316, 125, + /* 1110 */ 316, 353, 186, 316, 410, 31, 410, 45, 316, 543, + /* 1120 */ 379, 125, 410, 46, 410, 47, 316, 551, 264, 170, + /* 1130 */ 410, 48, 410, 32, 401, 410, 11, 552, 440, 89, + /* 1140 */ 410, 50, 301, 562, 578, 89, 287, 361, 410, 51, + /* 1150 */ 364, 365, 267, 268, 269, 554, 143, 564, 277, 324, + /* 1160 */ 280, 281, 575, 225, 442, 461, 464, 503, 241, 513, + /* 1170 */ 516, 550, 343, 160, 561, 390, 8, 313, 398, 399, + /* 1180 */ 400, 412, 82, 226, 331, 329, 81, 406, 57, 78, + /* 1190 */ 209, 167, 83, 459, 122, 414, 227, 334, 228, 338, + /* 1200 */ 300, 500, 103, 496, 246, 519, 514, 490, 495, 242, + /* 1210 */ 214, 518, 499, 229, 501, 413, 350, 533, 284, 525, + /* 1220 */ 526, 527, 235, 181, 473, 237, 285, 477, 182, 354, + /* 1230 */ 352, 184, 86, 185, 118, 535, 187, 546, 360, 190, + /* 1240 */ 129, 553, 139, 371, 372, 130, 215, 309, 560, 131, + /* 1250 */ 132, 133, 572, 577, 135, 573, 98, 574, 389, 262, + /* 1260 */ 402, 621, 536, 213, 101, 622, 432, 163, 164, 429, + /* 1270 */ 138, 71, 449, 437, 446, 140, 470, 154, 6, 450, + /* 1280 */ 7, 158, 166, 451, 14, 123, 13, 124, 484, 212, + /* 1290 */ 84, 342, 104, 105, 90, 250, 85, 117, 106, 347, + /* 1300 */ 179, 240, 351, 142, 534, 126, 18, 170, 93, 263, + /* 1310 */ 188, 107, 355, 286, 109, 127, 549, 541, 128, 119, + /* 1320 */ 537, 192, 15, 194, 195, 136, 196, 134, 556, 563, + /* 1330 */ 311, 137, 16, 108, 570, 203, 145, 385, 381, 282, + /* 1340 */ 584, 899, 899, 899, 899, 899, 87, 899, 88, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 16, 140, 141, 142, 111, 21, 145, 23, 70, 71, - /* 10 */ 72, 73, 23, 75, 76, 77, 78, 79, 80, 81, - /* 20 */ 82, 83, 84, 85, 156, 16, 42, 43, 74, 75, - /* 30 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - /* 40 */ 217, 59, 219, 220, 85, 61, 62, 63, 64, 65, - /* 50 */ 66, 67, 68, 69, 70, 71, 72, 73, 190, 75, - /* 60 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - /* 70 */ 16, 89, 148, 89, 148, 93, 22, 217, 89, 219, - /* 80 */ 220, 75, 76, 77, 78, 79, 80, 81, 82, 83, - /* 90 */ 84, 85, 166, 167, 85, 142, 42, 43, 145, 239, - /* 100 */ 46, 92, 93, 94, 95, 96, 97, 125, 126, 127, - /* 110 */ 148, 1, 2, 104, 16, 61, 62, 63, 64, 65, - /* 120 */ 66, 67, 68, 69, 70, 71, 72, 73, 166, 75, - /* 130 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - /* 140 */ 42, 43, 44, 79, 80, 81, 82, 83, 84, 85, - /* 150 */ 226, 23, 19, 156, 228, 229, 23, 79, 80, 61, - /* 160 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - /* 170 */ 72, 73, 111, 75, 76, 77, 78, 79, 80, 81, - /* 180 */ 82, 83, 84, 85, 16, 124, 148, 190, 148, 21, - /* 190 */ 228, 229, 59, 22, 154, 157, 158, 157, 158, 202, - /* 200 */ 203, 148, 84, 85, 207, 168, 169, 79, 80, 170, - /* 210 */ 42, 43, 79, 80, 177, 170, 161, 89, 90, 181, - /* 220 */ 182, 191, 89, 170, 171, 170, 93, 99, 16, 61, - /* 230 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - /* 240 */ 72, 73, 148, 75, 76, 77, 78, 79, 80, 81, - /* 250 */ 82, 83, 84, 85, 42, 43, 186, 187, 125, 126, - /* 260 */ 127, 90, 11, 210, 211, 81, 82, 83, 84, 85, - /* 270 */ 186, 187, 16, 61, 62, 63, 64, 65, 66, 67, - /* 280 */ 68, 69, 70, 71, 72, 73, 115, 75, 76, 77, - /* 290 */ 78, 79, 80, 81, 82, 83, 84, 85, 42, 43, - /* 300 */ 49, 16, 91, 209, 148, 94, 95, 96, 162, 217, - /* 310 */ 218, 219, 220, 157, 158, 81, 105, 61, 62, 63, - /* 320 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - /* 330 */ 182, 75, 76, 77, 78, 79, 80, 81, 82, 83, - /* 340 */ 84, 85, 108, 182, 132, 16, 112, 201, 12, 20, - /* 350 */ 23, 100, 101, 102, 159, 22, 169, 162, 163, 164, - /* 360 */ 24, 148, 111, 217, 177, 219, 220, 177, 178, 156, - /* 370 */ 85, 42, 43, 37, 184, 39, 91, 92, 93, 94, - /* 380 */ 95, 96, 97, 170, 171, 49, 245, 246, 132, 104, - /* 390 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - /* 400 */ 71, 72, 73, 190, 75, 76, 77, 78, 79, 80, - /* 410 */ 81, 82, 83, 84, 85, 16, 89, 90, 91, 20, - /* 420 */ 30, 94, 95, 96, 91, 212, 148, 94, 95, 96, - /* 430 */ 148, 148, 105, 19, 148, 21, 148, 224, 105, 156, - /* 440 */ 50, 42, 43, 19, 165, 166, 167, 23, 170, 171, - /* 450 */ 187, 148, 162, 170, 171, 148, 170, 171, 170, 171, - /* 460 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - /* 470 */ 71, 72, 73, 190, 75, 76, 77, 78, 79, 80, - /* 480 */ 81, 82, 83, 84, 85, 16, 20, 20, 22, 20, - /* 490 */ 212, 201, 189, 103, 148, 213, 148, 148, 212, 148, - /* 500 */ 23, 148, 224, 148, 202, 203, 42, 43, 229, 221, - /* 510 */ 224, 42, 43, 89, 143, 144, 170, 171, 170, 171, - /* 520 */ 149, 170, 171, 170, 171, 170, 171, 156, 64, 65, - /* 530 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - /* 540 */ 71, 72, 73, 240, 75, 76, 77, 78, 79, 80, - /* 550 */ 81, 82, 83, 84, 85, 16, 79, 93, 209, 20, - /* 560 */ 20, 190, 211, 151, 216, 16, 89, 90, 20, 216, - /* 570 */ 224, 165, 166, 167, 107, 19, 109, 110, 19, 23, - /* 580 */ 25, 42, 43, 22, 29, 214, 19, 20, 18, 22, - /* 590 */ 19, 20, 43, 22, 162, 23, 41, 162, 163, 164, - /* 600 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - /* 610 */ 71, 72, 73, 242, 75, 76, 77, 78, 79, 80, - /* 620 */ 81, 82, 83, 84, 85, 16, 56, 60, 69, 12, - /* 630 */ 21, 60, 19, 201, 108, 229, 23, 225, 112, 23, - /* 640 */ 148, 24, 21, 231, 23, 89, 90, 107, 99, 109, - /* 650 */ 110, 42, 43, 104, 37, 107, 39, 109, 110, 148, - /* 660 */ 27, 89, 90, 148, 148, 95, 148, 34, 14, 16, - /* 670 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - /* 680 */ 71, 72, 73, 122, 75, 76, 77, 78, 79, 80, - /* 690 */ 81, 82, 83, 84, 85, 42, 43, 81, 183, 183, - /* 700 */ 189, 183, 89, 90, 134, 89, 90, 53, 148, 55, - /* 710 */ 89, 148, 148, 16, 61, 62, 63, 64, 65, 66, - /* 720 */ 67, 68, 69, 70, 71, 72, 73, 148, 75, 76, - /* 730 */ 77, 78, 79, 80, 81, 82, 83, 84, 85, 42, - /* 740 */ 43, 226, 226, 183, 226, 148, 183, 0, 1, 2, - /* 750 */ 7, 8, 9, 107, 146, 109, 110, 16, 61, 62, - /* 760 */ 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - /* 770 */ 73, 148, 75, 76, 77, 78, 79, 80, 81, 82, - /* 780 */ 83, 84, 85, 42, 43, 148, 226, 148, 134, 226, - /* 790 */ 100, 101, 102, 170, 171, 100, 101, 102, 19, 148, - /* 800 */ 148, 16, 192, 62, 63, 64, 65, 66, 67, 68, - /* 810 */ 69, 70, 71, 72, 73, 92, 75, 76, 77, 78, - /* 820 */ 79, 80, 81, 82, 83, 84, 85, 42, 43, 23, - /* 830 */ 243, 244, 23, 16, 111, 148, 148, 22, 14, 156, - /* 840 */ 189, 189, 148, 131, 148, 133, 209, 124, 63, 64, - /* 850 */ 65, 66, 67, 68, 69, 70, 71, 72, 73, 148, - /* 860 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - /* 870 */ 85, 16, 17, 190, 19, 148, 189, 53, 23, 55, - /* 880 */ 43, 22, 148, 189, 148, 189, 31, 16, 17, 156, - /* 890 */ 19, 156, 113, 156, 23, 89, 90, 214, 89, 90, - /* 900 */ 189, 213, 31, 48, 170, 171, 170, 171, 156, 148, - /* 910 */ 93, 193, 125, 126, 59, 148, 189, 148, 200, 48, - /* 920 */ 237, 115, 93, 190, 115, 190, 20, 190, 22, 114, - /* 930 */ 59, 170, 171, 104, 79, 80, 99, 170, 171, 170, - /* 940 */ 171, 148, 190, 88, 89, 90, 20, 20, 93, 22, - /* 950 */ 79, 80, 81, 148, 92, 93, 148, 98, 148, 88, - /* 960 */ 89, 90, 16, 17, 93, 19, 111, 148, 148, 23, - /* 970 */ 148, 148, 20, 162, 22, 170, 171, 31, 170, 171, - /* 980 */ 125, 126, 127, 128, 129, 130, 60, 204, 148, 170, - /* 990 */ 171, 148, 170, 171, 48, 148, 125, 126, 127, 128, - /* 1000 */ 129, 130, 7, 8, 20, 59, 22, 5, 148, 148, - /* 1010 */ 170, 171, 10, 11, 12, 13, 51, 52, 148, 20, - /* 1020 */ 148, 22, 148, 148, 179, 79, 80, 20, 26, 22, - /* 1030 */ 28, 170, 171, 179, 88, 89, 90, 35, 148, 93, - /* 1040 */ 170, 171, 170, 171, 170, 171, 148, 179, 20, 47, - /* 1050 */ 22, 49, 20, 148, 22, 148, 54, 148, 148, 57, - /* 1060 */ 20, 148, 22, 148, 148, 20, 148, 22, 170, 171, - /* 1070 */ 148, 125, 126, 127, 128, 129, 130, 170, 171, 233, - /* 1080 */ 170, 171, 234, 148, 148, 170, 171, 148, 170, 171, - /* 1090 */ 148, 148, 170, 171, 20, 148, 22, 148, 148, 148, - /* 1100 */ 192, 148, 100, 101, 102, 170, 171, 148, 106, 170, - /* 1110 */ 171, 148, 148, 111, 148, 148, 148, 148, 148, 170, - /* 1120 */ 171, 170, 171, 170, 171, 148, 148, 148, 148, 148, - /* 1130 */ 148, 148, 194, 170, 171, 150, 178, 135, 170, 171, - /* 1140 */ 170, 171, 148, 223, 230, 148, 173, 170, 171, 170, - /* 1150 */ 171, 170, 171, 170, 171, 230, 148, 195, 148, 173, - /* 1160 */ 148, 173, 173, 173, 170, 171, 174, 170, 171, 195, - /* 1170 */ 6, 147, 147, 147, 147, 22, 155, 190, 170, 171, - /* 1180 */ 170, 171, 170, 171, 122, 119, 195, 120, 117, 196, - /* 1190 */ 121, 23, 161, 197, 131, 113, 198, 222, 99, 199, - /* 1200 */ 153, 153, 116, 99, 98, 172, 205, 172, 172, 206, - /* 1210 */ 205, 40, 206, 174, 180, 172, 19, 175, 85, 161, - /* 1220 */ 161, 180, 172, 172, 172, 15, 153, 152, 175, 152, - /* 1230 */ 152, 227, 153, 153, 153, 152, 227, 38, 131, 61, - /* 1240 */ 153, 185, 185, 19, 215, 153, 235, 15, 188, 236, - /* 1250 */ 195, 153, 188, 188, 33, 238, 188, 185, 238, 215, - /* 1260 */ 138, 153, 153, 241, 176, 195, 176, 244, 1, 232, - /* 1270 */ 160, 20, 113, 113, 113, 113, 93, 247, 108, 19, - /* 1280 */ 11, 20, 20, 19, 19, 22, 20, 118, 20, 115, - /* 1290 */ 118, 19, 22, 22, 20, 113, 20, 44, 19, 44, - /* 1300 */ 19, 44, 20, 19, 19, 32, 19, 104, 97, 16, - /* 1310 */ 21, 17, 99, 36, 22, 134, 99, 19, 5, 1, - /* 1320 */ 45, 103, 19, 45, 123, 69, 114, 69, 14, 17, - /* 1330 */ 116, 103, 123, 114, 19, 14, 20, 137, 58, 124, - /* 1340 */ 136, 19, 3, 248, 4, + /* 0 */ 16, 139, 140, 141, 168, 21, 144, 23, 69, 70, + /* 10 */ 71, 72, 176, 74, 75, 76, 77, 78, 79, 80, + /* 20 */ 81, 82, 83, 84, 1, 2, 42, 43, 73, 74, + /* 30 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + /* 40 */ 78, 79, 23, 58, 60, 61, 62, 63, 64, 65, + /* 50 */ 66, 67, 68, 69, 70, 71, 72, 110, 74, 75, + /* 60 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 16, + /* 70 */ 123, 147, 88, 88, 110, 22, 216, 92, 218, 219, + /* 80 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + /* 90 */ 84, 147, 19, 169, 170, 42, 43, 78, 238, 46, + /* 100 */ 78, 79, 80, 81, 82, 83, 84, 88, 89, 124, + /* 110 */ 125, 126, 16, 60, 61, 62, 63, 64, 65, 66, + /* 120 */ 67, 68, 69, 70, 71, 72, 182, 74, 75, 76, + /* 130 */ 77, 78, 79, 80, 81, 82, 83, 84, 42, 43, + /* 140 */ 44, 80, 81, 82, 83, 84, 23, 223, 161, 216, + /* 150 */ 19, 218, 219, 21, 23, 23, 60, 61, 62, 63, + /* 160 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 225, + /* 170 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + /* 180 */ 84, 16, 147, 147, 150, 112, 21, 200, 147, 58, + /* 190 */ 84, 147, 156, 157, 216, 217, 218, 219, 83, 84, + /* 200 */ 165, 78, 79, 216, 190, 218, 219, 42, 43, 78, + /* 210 */ 79, 88, 89, 169, 170, 141, 180, 181, 144, 88, + /* 220 */ 88, 98, 147, 92, 16, 60, 61, 62, 63, 64, + /* 230 */ 65, 66, 67, 68, 69, 70, 71, 72, 147, 74, + /* 240 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + /* 250 */ 42, 43, 169, 209, 210, 124, 125, 126, 224, 14, + /* 260 */ 169, 170, 227, 228, 230, 18, 225, 16, 60, 61, + /* 270 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + /* 280 */ 72, 23, 74, 75, 76, 77, 78, 79, 80, 81, + /* 290 */ 82, 83, 84, 42, 43, 147, 16, 52, 147, 54, + /* 300 */ 147, 210, 55, 106, 153, 108, 109, 156, 157, 156, + /* 310 */ 157, 60, 61, 62, 63, 64, 65, 66, 67, 68, + /* 320 */ 69, 70, 71, 72, 22, 74, 75, 76, 77, 78, + /* 330 */ 79, 80, 81, 82, 83, 84, 188, 147, 92, 131, + /* 340 */ 16, 94, 16, 22, 20, 155, 88, 89, 90, 103, + /* 350 */ 147, 93, 94, 95, 167, 168, 161, 162, 163, 169, + /* 360 */ 170, 25, 104, 176, 84, 29, 42, 43, 165, 166, + /* 370 */ 90, 91, 92, 93, 94, 95, 96, 41, 133, 189, + /* 380 */ 133, 169, 131, 103, 60, 61, 62, 63, 64, 65, + /* 390 */ 66, 67, 68, 69, 70, 71, 72, 181, 74, 75, + /* 400 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 16, + /* 410 */ 84, 90, 22, 20, 93, 94, 95, 91, 92, 93, + /* 420 */ 94, 95, 96, 121, 147, 104, 147, 185, 186, 103, + /* 430 */ 227, 228, 155, 181, 160, 42, 43, 90, 176, 177, + /* 440 */ 93, 94, 95, 169, 161, 183, 169, 170, 169, 170, + /* 450 */ 155, 104, 155, 60, 61, 62, 63, 64, 65, 66, + /* 460 */ 67, 68, 69, 70, 71, 72, 189, 74, 75, 76, + /* 470 */ 77, 78, 79, 80, 81, 82, 83, 84, 16, 11, + /* 480 */ 244, 245, 20, 200, 189, 147, 189, 147, 211, 158, + /* 490 */ 211, 147, 161, 162, 163, 147, 201, 202, 42, 43, + /* 500 */ 223, 206, 223, 113, 42, 43, 147, 169, 170, 169, + /* 510 */ 170, 23, 19, 169, 170, 186, 23, 49, 155, 63, + /* 520 */ 64, 147, 60, 61, 62, 63, 64, 65, 66, 67, + /* 530 */ 68, 69, 70, 71, 72, 147, 74, 75, 76, 77, + /* 540 */ 78, 79, 80, 81, 82, 83, 84, 16, 92, 211, + /* 550 */ 12, 20, 189, 164, 165, 166, 208, 147, 16, 215, + /* 560 */ 220, 223, 24, 164, 165, 166, 23, 99, 100, 101, + /* 570 */ 155, 212, 23, 42, 43, 37, 88, 39, 110, 169, + /* 580 */ 170, 88, 89, 19, 20, 43, 22, 49, 185, 186, + /* 590 */ 23, 60, 61, 62, 63, 64, 65, 66, 67, 68, + /* 600 */ 69, 70, 71, 72, 189, 74, 75, 76, 77, 78, + /* 610 */ 79, 80, 81, 82, 83, 84, 16, 228, 0, 1, + /* 620 */ 2, 21, 19, 59, 147, 215, 23, 228, 213, 80, + /* 630 */ 147, 88, 89, 19, 20, 145, 22, 88, 89, 147, + /* 640 */ 98, 147, 42, 43, 20, 103, 169, 170, 20, 147, + /* 650 */ 147, 236, 169, 170, 20, 88, 89, 114, 147, 16, + /* 660 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + /* 670 */ 70, 71, 72, 59, 74, 75, 76, 77, 78, 79, + /* 680 */ 80, 81, 82, 83, 84, 42, 43, 147, 142, 143, + /* 690 */ 188, 88, 89, 130, 148, 132, 7, 8, 9, 188, + /* 700 */ 208, 155, 16, 60, 61, 62, 63, 64, 65, 66, + /* 710 */ 67, 68, 69, 70, 71, 72, 147, 74, 75, 76, + /* 720 */ 77, 78, 79, 80, 81, 82, 83, 84, 42, 43, + /* 730 */ 106, 147, 108, 109, 106, 189, 108, 109, 169, 170, + /* 740 */ 106, 147, 108, 109, 147, 16, 60, 61, 62, 63, + /* 750 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 213, + /* 760 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + /* 770 */ 84, 42, 43, 99, 100, 101, 182, 147, 161, 182, + /* 780 */ 99, 100, 101, 14, 147, 147, 147, 241, 16, 191, + /* 790 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + /* 800 */ 71, 72, 147, 74, 75, 76, 77, 78, 79, 80, + /* 810 */ 81, 82, 83, 84, 42, 43, 23, 200, 188, 225, + /* 820 */ 182, 52, 225, 54, 169, 170, 147, 188, 22, 22, + /* 830 */ 147, 147, 201, 202, 62, 63, 64, 65, 66, 67, + /* 840 */ 68, 69, 70, 71, 72, 208, 74, 75, 76, 77, + /* 850 */ 78, 79, 80, 81, 82, 83, 84, 16, 17, 12, + /* 860 */ 19, 155, 19, 225, 23, 182, 23, 188, 147, 239, + /* 870 */ 147, 24, 31, 16, 17, 147, 19, 147, 147, 155, + /* 880 */ 23, 88, 89, 19, 37, 21, 39, 147, 31, 48, + /* 890 */ 169, 170, 169, 170, 147, 189, 89, 169, 170, 58, + /* 900 */ 169, 170, 147, 97, 147, 48, 147, 114, 225, 169, + /* 910 */ 170, 161, 147, 189, 16, 58, 169, 170, 147, 78, + /* 920 */ 79, 114, 155, 147, 169, 170, 169, 170, 87, 88, + /* 930 */ 89, 88, 80, 92, 147, 78, 79, 80, 147, 91, + /* 940 */ 169, 170, 212, 19, 87, 88, 89, 16, 17, 92, + /* 950 */ 19, 110, 147, 188, 23, 147, 189, 203, 110, 107, + /* 960 */ 169, 170, 31, 111, 188, 124, 125, 126, 127, 128, + /* 970 */ 129, 123, 147, 192, 169, 170, 43, 169, 170, 48, + /* 980 */ 199, 124, 125, 126, 127, 128, 129, 242, 243, 58, + /* 990 */ 92, 5, 68, 147, 169, 170, 10, 11, 12, 13, + /* 1000 */ 124, 125, 147, 147, 107, 147, 147, 147, 111, 78, + /* 1010 */ 79, 20, 26, 22, 28, 20, 147, 22, 87, 88, + /* 1020 */ 89, 35, 147, 92, 169, 170, 147, 169, 170, 169, + /* 1030 */ 170, 98, 20, 47, 188, 49, 27, 7, 8, 53, + /* 1040 */ 147, 147, 56, 34, 169, 170, 147, 147, 169, 170, + /* 1050 */ 147, 20, 147, 22, 147, 124, 125, 126, 127, 128, + /* 1060 */ 129, 178, 169, 170, 178, 20, 147, 22, 169, 170, + /* 1070 */ 30, 59, 169, 170, 169, 170, 147, 147, 91, 92, + /* 1080 */ 20, 147, 22, 147, 178, 99, 100, 101, 169, 170, + /* 1090 */ 50, 105, 147, 20, 147, 22, 110, 147, 169, 170, + /* 1100 */ 147, 147, 147, 169, 170, 169, 170, 20, 147, 22, + /* 1110 */ 147, 233, 232, 147, 169, 170, 169, 170, 147, 20, + /* 1120 */ 134, 22, 169, 170, 169, 170, 147, 20, 147, 22, + /* 1130 */ 169, 170, 169, 170, 149, 169, 170, 20, 229, 22, + /* 1140 */ 169, 170, 102, 20, 20, 22, 22, 147, 169, 170, + /* 1150 */ 147, 147, 147, 147, 147, 147, 191, 147, 147, 222, + /* 1160 */ 147, 147, 147, 193, 229, 172, 172, 177, 172, 172, + /* 1170 */ 172, 194, 173, 6, 194, 146, 22, 154, 146, 146, + /* 1180 */ 146, 189, 121, 194, 118, 116, 119, 23, 120, 130, + /* 1190 */ 221, 112, 98, 152, 152, 160, 195, 115, 196, 98, + /* 1200 */ 40, 97, 19, 179, 84, 179, 160, 171, 171, 171, + /* 1210 */ 226, 160, 173, 197, 171, 198, 15, 152, 174, 171, + /* 1220 */ 171, 171, 204, 151, 205, 204, 174, 205, 151, 38, + /* 1230 */ 152, 151, 130, 152, 60, 152, 151, 184, 152, 184, + /* 1240 */ 19, 194, 214, 152, 15, 187, 226, 152, 194, 187, + /* 1250 */ 187, 187, 33, 137, 184, 152, 159, 152, 1, 234, + /* 1260 */ 20, 112, 235, 175, 175, 112, 107, 112, 112, 92, + /* 1270 */ 214, 19, 11, 20, 20, 19, 114, 19, 117, 20, + /* 1280 */ 117, 112, 22, 20, 22, 19, 22, 20, 20, 44, + /* 1290 */ 19, 44, 19, 19, 237, 20, 19, 32, 19, 44, + /* 1300 */ 96, 103, 16, 21, 17, 98, 231, 22, 237, 133, + /* 1310 */ 98, 19, 36, 5, 240, 45, 1, 45, 102, 243, + /* 1320 */ 51, 122, 19, 113, 14, 102, 115, 113, 17, 123, + /* 1330 */ 246, 122, 19, 14, 20, 135, 19, 3, 57, 136, + /* 1340 */ 4, 247, 247, 247, 247, 247, 68, 247, 68, }; -#define YY_SHIFT_USE_DFLT (-108) +#define YY_SHIFT_USE_DFLT (-62) #define YY_SHIFT_MAX 385 static const short yy_shift_ofst[] = { - /* 0 */ 110, 855, 1002, -16, 855, 946, 946, 946, 327, 128, - /* 10 */ -107, 98, 946, 946, 946, 946, 946, -46, 251, 477, - /* 20 */ 572, -11, 78, 78, 54, 168, 212, 256, 329, 399, - /* 30 */ 469, 539, 609, 653, 697, 653, 653, 653, 653, 653, - /* 40 */ 653, 653, 653, 653, 653, 653, 653, 653, 653, 653, - /* 50 */ 653, 653, 741, 785, 785, 871, 946, 946, 946, 946, - /* 60 */ 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, - /* 70 */ 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, - /* 80 */ 946, 946, 946, 946, 946, 946, 946, 946, 946, 946, - /* 90 */ 946, 946, 946, 946, -62, -62, 6, 6, 285, 64, - /* 100 */ 184, 549, 570, 572, 572, 572, 572, 572, 572, 572, - /* 110 */ 118, -11, -41, -108, -108, 133, 9, 336, 336, 567, - /* 120 */ 571, 747, 621, 572, 621, 572, 572, 572, 572, 572, - /* 130 */ 572, 572, 572, 572, 572, 572, 572, 572, 723, 61, - /* 140 */ -107, -107, -107, -108, -108, -108, -18, -18, 333, 211, - /* 150 */ 467, 556, 540, 548, 617, 806, 809, 613, 616, 743, - /* 160 */ 572, 572, 234, 572, 572, 424, 572, 572, 171, 572, - /* 170 */ 572, 646, 171, 572, 572, 390, 390, 390, 572, 572, - /* 180 */ 646, 572, 572, 646, 572, 555, 690, 572, 572, 646, - /* 190 */ 572, 572, 572, 646, 572, 572, 572, 646, 646, 572, - /* 200 */ 572, 572, 572, 572, 414, 526, 815, 787, 787, 712, - /* 210 */ 633, 633, 633, 837, 633, 633, 859, 561, 561, 1164, - /* 220 */ 1164, 1164, 1164, 1153, -107, 1062, 1066, 1067, 1071, 1069, - /* 230 */ 1168, 1063, 1082, 1082, 1099, 1086, 1099, 1086, 1104, 1104, - /* 240 */ 1171, 1104, 1106, 1104, 1197, 1133, 1168, 1133, 1168, 1171, - /* 250 */ 1104, 1104, 1104, 1197, 1210, 1082, 1210, 1082, 1210, 1082, - /* 260 */ 1082, 1199, 1107, 1210, 1082, 1178, 1178, 1224, 1062, 1082, - /* 270 */ 1232, 1232, 1232, 1232, 1062, 1178, 1224, 1082, 1221, 1221, - /* 280 */ 1082, 1082, 1122, -108, -108, -108, -108, -108, -108, 464, - /* 290 */ 654, 695, 824, 779, 817, 466, 906, 927, 952, 829, - /* 300 */ 995, 862, 984, 999, 1007, 965, 1028, 1032, 1040, 1045, - /* 310 */ 559, 1074, 926, 1267, 1251, 1159, 1160, 1161, 1162, 1183, - /* 320 */ 1170, 1260, 1261, 1262, 1264, 1269, 1265, 1266, 1263, 1268, - /* 330 */ 1169, 1270, 1172, 1271, 1174, 1272, 1274, 1182, 1276, 1273, - /* 340 */ 1253, 1279, 1255, 1281, 1282, 1284, 1285, 1257, 1287, 1211, - /* 350 */ 1203, 1293, 1294, 1289, 1213, 1277, 1275, 1292, 1278, 1181, - /* 360 */ 1217, 1298, 1313, 1318, 1218, 1256, 1258, 1201, 1303, 1212, - /* 370 */ 1314, 1214, 1312, 1219, 1228, 1209, 1315, 1215, 1316, 1321, - /* 380 */ 1280, 1204, 1200, 1322, 1339, 1340, + /* 0 */ 23, 841, 986, -16, 841, 931, 931, 931, 258, 123, + /* 10 */ -36, 96, 931, 931, 931, 931, 931, -45, 468, 19, + /* 20 */ 567, 488, -38, -38, 53, 165, 208, 251, 324, 393, + /* 30 */ 462, 531, 600, 643, 686, 643, 643, 643, 643, 643, + /* 40 */ 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, + /* 50 */ 643, 643, 729, 772, 772, 857, 931, 931, 931, 931, + /* 60 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, + /* 70 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, + /* 80 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, + /* 90 */ 931, 931, 931, 931, -61, -61, 6, 6, 280, 22, + /* 100 */ 61, 542, 247, 567, 567, 567, 567, 567, 567, 567, + /* 110 */ 115, 488, 106, -62, -62, 131, 326, 538, 538, 564, + /* 120 */ 614, 618, 132, 567, 132, 567, 567, 567, 567, 567, + /* 130 */ 567, 567, 567, 567, 567, 567, 567, 567, 848, -53, + /* 140 */ -36, -36, -36, -62, -62, -62, -15, -15, 321, 347, + /* 150 */ 624, 493, 628, 634, 847, 543, 793, 603, 549, 689, + /* 160 */ 567, 567, 852, 567, 567, 843, 567, 567, 807, 567, + /* 170 */ 567, 197, 807, 567, 567, 1040, 1040, 1040, 567, 567, + /* 180 */ 197, 567, 567, 197, 567, 336, 674, 567, 567, 197, + /* 190 */ 567, 567, 567, 197, 567, 567, 567, 197, 197, 567, + /* 200 */ 567, 567, 567, 567, 864, 897, 390, 876, 876, 563, + /* 210 */ 1009, 1009, 1009, 933, 1009, 1009, 806, 302, 302, 1167, + /* 220 */ 1167, 1167, 1167, 1154, -36, 1061, 1066, 1067, 1069, 1068, + /* 230 */ 1164, 1059, 1079, 1079, 1094, 1082, 1094, 1082, 1101, 1101, + /* 240 */ 1160, 1101, 1104, 1101, 1183, 1120, 1164, 1120, 1164, 1160, + /* 250 */ 1101, 1101, 1101, 1183, 1201, 1079, 1201, 1079, 1201, 1079, + /* 260 */ 1079, 1191, 1102, 1201, 1079, 1174, 1174, 1221, 1061, 1079, + /* 270 */ 1229, 1229, 1229, 1229, 1061, 1174, 1221, 1079, 1219, 1219, + /* 280 */ 1079, 1079, 1116, -62, -62, -62, -62, -62, -62, 456, + /* 290 */ 245, 681, 769, 73, 898, 991, 995, 1031, 1045, 246, + /* 300 */ 1030, 987, 1060, 1073, 1087, 1099, 1107, 1117, 1123, 924, + /* 310 */ 1124, 1012, 1257, 1240, 1149, 1153, 1155, 1156, 1177, 1159, + /* 320 */ 1252, 1253, 1254, 1256, 1261, 1258, 1259, 1260, 1263, 1161, + /* 330 */ 1262, 1163, 1264, 1162, 1266, 1267, 1169, 1268, 1265, 1245, + /* 340 */ 1271, 1247, 1273, 1275, 1274, 1277, 1255, 1279, 1204, 1198, + /* 350 */ 1286, 1287, 1282, 1207, 1276, 1269, 1270, 1285, 1272, 1176, + /* 360 */ 1212, 1292, 1308, 1315, 1216, 1278, 1280, 1199, 1303, 1210, + /* 370 */ 1310, 1211, 1311, 1214, 1223, 1209, 1313, 1206, 1314, 1319, + /* 380 */ 1281, 1200, 1203, 1317, 1334, 1336, }; -#define YY_REDUCE_USE_DFLT (-178) +#define YY_REDUCE_USE_DFLT (-165) #define YY_REDUCE_MAX 288 static const short yy_reduce_ofst[] = { - /* 0 */ -139, 213, 371, 146, 283, 278, 53, 286, 38, -74, - /* 10 */ -3, -140, 288, 346, 351, 348, 353, 92, 683, -38, - /* 20 */ 40, 195, 279, 406, -177, -177, -177, -177, -177, -177, - /* 30 */ -177, -177, -177, -177, -177, -177, -177, -177, -177, -177, - /* 40 */ -177, -177, -177, -177, -177, -177, -177, -177, -177, -177, - /* 50 */ -177, -177, -177, -177, -177, 355, 623, 734, 736, 761, - /* 60 */ 767, 769, 805, 808, 819, 822, 840, 861, 870, 872, - /* 70 */ 874, 898, 907, 910, 915, 918, 922, 935, 939, 949, - /* 80 */ 951, 953, 963, 968, 970, 977, 979, 981, 983, 994, - /* 90 */ 997, 1008, 1010, 1012, -177, -177, -177, -177, 37, -177, - /* 100 */ -177, 190, 412, 515, 516, 518, 560, 563, 303, 156, - /* 110 */ -177, 435, -177, -177, -177, 55, 187, 70, 84, 141, - /* 120 */ 141, -47, 290, 94, 432, -76, 511, 349, 282, 637, - /* 130 */ 651, 652, 687, 694, 696, 711, 688, 727, -132, 733, - /* 140 */ 735, 737, 752, 718, 302, 587, 39, 45, 148, 161, - /* 150 */ 30, 307, 30, 30, 263, 492, 564, 579, 597, 608, - /* 160 */ 639, 793, 610, 597, 810, 811, 820, 823, 783, 843, - /* 170 */ 847, 30, 783, 860, 875, 845, 854, 868, 890, 905, - /* 180 */ 30, 909, 913, 30, 916, 846, 848, 936, 942, 30, - /* 190 */ 943, 947, 950, 30, 959, 964, 966, 30, 30, 967, - /* 200 */ 969, 978, 980, 982, 985, 908, 938, 914, 925, 920, - /* 210 */ 973, 986, 988, 958, 989, 990, 992, 962, 974, 1024, - /* 220 */ 1025, 1026, 1027, 1021, 987, 991, 993, 996, 998, 1000, - /* 230 */ 1031, 975, 1047, 1048, 1001, 1003, 1005, 1006, 1033, 1035, - /* 240 */ 1034, 1036, 1039, 1043, 1042, 1004, 1058, 1009, 1059, 1041, - /* 250 */ 1050, 1051, 1052, 1053, 1075, 1073, 1077, 1079, 1078, 1080, - /* 260 */ 1081, 1011, 1013, 1083, 1087, 1056, 1057, 1029, 1055, 1092, - /* 270 */ 1060, 1064, 1065, 1068, 1070, 1072, 1044, 1098, 1017, 1020, - /* 280 */ 1108, 1109, 1022, 1110, 1088, 1090, 1037, 1023, 1030, + /* 0 */ -138, 277, 546, -13, 190, 279, 44, 338, 36, 203, + /* 10 */ 295, -140, 340, -76, 91, 344, 410, -22, 415, 35, + /* 20 */ 151, 331, 389, 399, -67, -67, -67, -67, -67, -67, + /* 30 */ -67, -67, -67, -67, -67, -67, -67, -67, -67, -67, + /* 40 */ -67, -67, -67, -67, -67, -67, -67, -67, -67, -67, + /* 50 */ -67, -67, -67, -67, -67, 477, 483, 569, 655, 721, + /* 60 */ 723, 728, 731, 740, 747, 755, 757, 771, 791, 805, + /* 70 */ 808, 825, 855, 858, 860, 875, 879, 893, 899, 903, + /* 80 */ 905, 919, 929, 934, 936, 945, 947, 953, 955, 961, + /* 90 */ 963, 966, 971, 979, -67, -67, -67, -67, 187, -67, + /* 100 */ -67, 262, 34, -56, 594, 597, 638, 683, 630, 153, + /* 110 */ -67, 195, -67, -67, -67, 274, -164, 242, 403, 236, + /* 120 */ 236, 74, 283, 348, 617, 41, 148, 492, 359, 637, + /* 130 */ 502, 511, 639, 679, 765, 776, 730, 846, 297, 363, + /* 140 */ 706, 724, 767, 781, 631, 745, 83, 212, 216, 252, + /* 150 */ 14, 75, 14, 14, 329, 374, 388, 494, 503, 490, + /* 160 */ 540, 584, 598, 503, 684, 750, 759, 787, 754, 856, + /* 170 */ 859, 14, 754, 869, 894, 883, 886, 906, 900, 907, + /* 180 */ 14, 930, 950, 14, 954, 880, 878, 981, 1000, 14, + /* 190 */ 1003, 1004, 1005, 14, 1006, 1007, 1008, 14, 14, 1010, + /* 200 */ 1011, 1013, 1014, 1015, 985, 965, 970, 909, 935, 937, + /* 210 */ 993, 994, 996, 990, 997, 998, 999, 977, 980, 1029, + /* 220 */ 1032, 1033, 1034, 1023, 992, 989, 1001, 1002, 1016, 1017, + /* 230 */ 1035, 969, 1041, 1042, 1018, 1019, 1021, 1022, 1036, 1037, + /* 240 */ 1024, 1038, 1039, 1043, 1044, 984, 1046, 1020, 1051, 1026, + /* 250 */ 1048, 1049, 1050, 1052, 1072, 1065, 1077, 1078, 1080, 1081, + /* 260 */ 1083, 1025, 1027, 1085, 1086, 1053, 1055, 1028, 1047, 1091, + /* 270 */ 1058, 1062, 1063, 1064, 1054, 1070, 1056, 1095, 1057, 1071, + /* 280 */ 1103, 1105, 1074, 1097, 1088, 1089, 1075, 1076, 1084, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 593, 819, 899, 708, 899, 819, 899, 819, 899, 844, - /* 10 */ 712, 873, 815, 819, 899, 899, 899, 790, 899, 844, - /* 20 */ 899, 624, 844, 844, 741, 899, 899, 899, 899, 899, - /* 30 */ 899, 899, 899, 742, 899, 818, 814, 810, 812, 811, - /* 40 */ 743, 732, 739, 746, 724, 858, 748, 749, 755, 756, - /* 50 */ 874, 877, 778, 777, 796, 899, 899, 899, 899, 899, - /* 60 */ 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, - /* 70 */ 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, - /* 80 */ 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, - /* 90 */ 899, 899, 899, 899, 780, 801, 779, 789, 617, 781, - /* 100 */ 782, 677, 612, 899, 899, 899, 899, 899, 899, 899, - /* 110 */ 783, 899, 784, 797, 798, 899, 899, 899, 899, 899, - /* 120 */ 899, 593, 708, 899, 708, 899, 899, 899, 899, 899, - /* 130 */ 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, - /* 140 */ 899, 899, 899, 702, 712, 892, 899, 899, 668, 899, - /* 150 */ 899, 899, 899, 899, 899, 899, 899, 899, 899, 600, - /* 160 */ 598, 899, 700, 899, 899, 626, 899, 899, 710, 899, - /* 170 */ 899, 715, 716, 899, 899, 899, 899, 899, 899, 899, - /* 180 */ 614, 899, 899, 689, 899, 850, 899, 899, 899, 865, - /* 190 */ 899, 899, 899, 863, 899, 899, 899, 691, 751, 831, - /* 200 */ 899, 878, 880, 899, 899, 700, 709, 899, 899, 813, - /* 210 */ 735, 735, 735, 647, 735, 735, 650, 745, 745, 597, - /* 220 */ 597, 597, 597, 667, 899, 745, 736, 738, 728, 740, - /* 230 */ 899, 899, 717, 717, 725, 727, 725, 727, 679, 679, - /* 240 */ 664, 679, 650, 679, 823, 828, 899, 828, 899, 664, - /* 250 */ 679, 679, 679, 823, 609, 717, 609, 717, 609, 717, - /* 260 */ 717, 854, 857, 609, 717, 681, 681, 757, 745, 717, - /* 270 */ 688, 688, 688, 688, 745, 681, 757, 717, 876, 876, - /* 280 */ 717, 717, 885, 634, 652, 652, 860, 892, 897, 899, - /* 290 */ 899, 899, 899, 764, 899, 899, 899, 899, 899, 899, - /* 300 */ 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, - /* 310 */ 837, 899, 899, 899, 899, 769, 765, 899, 766, 899, - /* 320 */ 694, 899, 899, 899, 899, 899, 899, 899, 899, 899, - /* 330 */ 899, 729, 899, 737, 899, 899, 899, 899, 899, 899, - /* 340 */ 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, - /* 350 */ 899, 899, 899, 899, 899, 899, 852, 853, 899, 899, - /* 360 */ 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, - /* 370 */ 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, - /* 380 */ 884, 899, 899, 887, 594, 899, 588, 591, 590, 592, - /* 390 */ 596, 599, 621, 622, 623, 601, 602, 603, 604, 605, - /* 400 */ 606, 607, 613, 615, 633, 635, 619, 637, 698, 699, - /* 410 */ 761, 692, 693, 697, 772, 763, 767, 768, 770, 771, - /* 420 */ 785, 786, 788, 794, 800, 803, 787, 792, 793, 795, - /* 430 */ 799, 802, 695, 696, 806, 620, 627, 628, 631, 632, - /* 440 */ 840, 842, 841, 843, 630, 629, 773, 776, 808, 809, - /* 450 */ 866, 867, 868, 869, 870, 804, 816, 817, 718, 807, - /* 460 */ 791, 730, 733, 734, 731, 701, 711, 720, 721, 722, - /* 470 */ 723, 706, 707, 713, 726, 759, 760, 714, 703, 704, - /* 480 */ 705, 805, 762, 774, 775, 638, 639, 769, 640, 641, - /* 490 */ 642, 680, 683, 684, 685, 643, 662, 665, 666, 644, - /* 500 */ 651, 645, 646, 653, 654, 655, 658, 659, 660, 661, - /* 510 */ 656, 657, 824, 825, 829, 827, 826, 648, 649, 663, - /* 520 */ 636, 625, 618, 669, 672, 673, 674, 675, 676, 678, - /* 530 */ 670, 671, 616, 608, 610, 719, 846, 855, 856, 851, - /* 540 */ 847, 848, 849, 611, 820, 821, 682, 753, 754, 845, - /* 550 */ 859, 861, 758, 862, 864, 889, 686, 687, 690, 830, - /* 560 */ 871, 744, 747, 750, 752, 832, 833, 834, 835, 838, - /* 570 */ 839, 836, 872, 875, 879, 881, 882, 883, 886, 888, - /* 580 */ 893, 894, 895, 898, 896, 595, 589, + /* 0 */ 592, 818, 897, 707, 897, 818, 897, 818, 897, 843, + /* 10 */ 711, 872, 814, 818, 897, 897, 897, 789, 897, 843, + /* 20 */ 897, 623, 843, 843, 740, 897, 897, 897, 897, 897, + /* 30 */ 897, 897, 897, 741, 897, 817, 813, 809, 811, 810, + /* 40 */ 742, 731, 738, 745, 723, 856, 747, 748, 754, 755, + /* 50 */ 873, 871, 777, 776, 795, 897, 897, 897, 897, 897, + /* 60 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, + /* 70 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, + /* 80 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, + /* 90 */ 897, 897, 897, 897, 779, 800, 778, 788, 616, 780, + /* 100 */ 781, 676, 611, 897, 897, 897, 897, 897, 897, 897, + /* 110 */ 782, 897, 783, 796, 797, 897, 897, 897, 897, 897, + /* 120 */ 897, 592, 707, 897, 707, 897, 897, 897, 897, 897, + /* 130 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, + /* 140 */ 897, 897, 897, 701, 711, 890, 897, 897, 667, 897, + /* 150 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 599, + /* 160 */ 597, 897, 699, 897, 897, 625, 897, 897, 709, 897, + /* 170 */ 897, 714, 715, 897, 897, 897, 897, 897, 897, 897, + /* 180 */ 613, 897, 897, 688, 897, 849, 897, 897, 897, 863, + /* 190 */ 897, 897, 897, 861, 897, 897, 897, 690, 750, 830, + /* 200 */ 897, 876, 878, 897, 897, 699, 708, 897, 897, 812, + /* 210 */ 734, 734, 734, 646, 734, 734, 649, 744, 744, 596, + /* 220 */ 596, 596, 596, 666, 897, 744, 735, 737, 727, 739, + /* 230 */ 897, 897, 716, 716, 724, 726, 724, 726, 678, 678, + /* 240 */ 663, 678, 649, 678, 822, 827, 897, 827, 897, 663, + /* 250 */ 678, 678, 678, 822, 608, 716, 608, 716, 608, 716, + /* 260 */ 716, 853, 855, 608, 716, 680, 680, 756, 744, 716, + /* 270 */ 687, 687, 687, 687, 744, 680, 756, 716, 875, 875, + /* 280 */ 716, 716, 883, 633, 651, 651, 858, 890, 895, 897, + /* 290 */ 897, 897, 897, 763, 897, 897, 897, 897, 897, 897, + /* 300 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 836, + /* 310 */ 897, 897, 897, 897, 768, 764, 897, 765, 897, 693, + /* 320 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, + /* 330 */ 728, 897, 736, 897, 897, 897, 897, 897, 897, 897, + /* 340 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, + /* 350 */ 897, 897, 897, 897, 897, 897, 851, 852, 897, 897, + /* 360 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, + /* 370 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, + /* 380 */ 882, 897, 897, 885, 593, 897, 587, 590, 589, 591, + /* 390 */ 595, 598, 620, 621, 622, 600, 601, 602, 603, 604, + /* 400 */ 605, 606, 612, 614, 632, 634, 618, 636, 697, 698, + /* 410 */ 760, 691, 692, 696, 771, 762, 766, 767, 769, 770, + /* 420 */ 784, 785, 787, 793, 799, 802, 786, 791, 792, 794, + /* 430 */ 798, 801, 694, 695, 805, 619, 626, 627, 630, 631, + /* 440 */ 839, 841, 840, 842, 629, 628, 772, 775, 807, 808, + /* 450 */ 864, 865, 866, 867, 868, 803, 815, 816, 717, 806, + /* 460 */ 790, 729, 732, 733, 730, 700, 710, 719, 720, 721, + /* 470 */ 722, 705, 706, 712, 725, 758, 759, 713, 702, 703, + /* 480 */ 704, 804, 761, 773, 774, 637, 638, 768, 639, 640, + /* 490 */ 641, 679, 682, 683, 684, 642, 661, 664, 665, 643, + /* 500 */ 650, 644, 645, 652, 653, 654, 657, 658, 659, 660, + /* 510 */ 655, 656, 823, 824, 828, 826, 825, 647, 648, 662, + /* 520 */ 635, 624, 617, 668, 671, 672, 673, 674, 675, 677, + /* 530 */ 669, 670, 615, 607, 609, 718, 845, 854, 850, 846, + /* 540 */ 847, 848, 610, 819, 820, 681, 752, 753, 844, 857, + /* 550 */ 859, 757, 860, 862, 887, 685, 686, 689, 829, 869, + /* 560 */ 743, 746, 749, 751, 831, 832, 833, 834, 837, 838, + /* 570 */ 835, 870, 874, 877, 879, 880, 881, 884, 886, 891, + /* 580 */ 892, 893, 896, 894, 594, 588, }; #define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0])) @@ -652,7 +655,6 @@ static const YYCODETYPE yyFallback[] = { 23, /* REPLACE => ID */ 23, /* RESTRICT => ID */ 23, /* ROW => ID */ - 23, /* STATEMENT => ID */ 23, /* TRIGGER => ID */ 23, /* VACUUM => ID */ 23, /* VIEW => ID */ @@ -769,7 +771,12 @@ struct yyParser { int yyidx; /* Index of top element in stack */ int yyerrcnt; /* Shifts left before out of the error */ sqlite3ParserARG_SDECL /* A place to hold %extra_argument */ +#if YYSTACKDEPTH<=0 + int yystksz; /* Current side of the stack */ + yyStackEntry *yystack; /* The parser's stack */ +#else yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ +#endif }; typedef struct yyParser yyParser; @@ -822,55 +829,55 @@ static const char *const yyTokenName[] = "INITIALLY", "INSTEAD", "LIKE_KW", "MATCH", "KEY", "OF", "OFFSET", "PRAGMA", "RAISE", "REPLACE", "RESTRICT", "ROW", - "STATEMENT", "TRIGGER", "VACUUM", "VIEW", - "VIRTUAL", "REINDEX", "RENAME", "CTIME_KW", - "ANY", "OR", "AND", "IS", - "BETWEEN", "IN", "ISNULL", "NOTNULL", - "NE", "EQ", "GT", "LE", - "LT", "GE", "ESCAPE", "BITAND", - "BITOR", "LSHIFT", "RSHIFT", "PLUS", - "MINUS", "STAR", "SLASH", "REM", - "CONCAT", "COLLATE", "UMINUS", "UPLUS", - "BITNOT", "STRING", "JOIN_KW", "CONSTRAINT", - "DEFAULT", "NULL", "PRIMARY", "UNIQUE", - "CHECK", "REFERENCES", "AUTOINCR", "ON", - "DELETE", "UPDATE", "INSERT", "SET", - "DEFERRABLE", "FOREIGN", "DROP", "UNION", - "ALL", "EXCEPT", "INTERSECT", "SELECT", - "DISTINCT", "DOT", "FROM", "JOIN", - "USING", "ORDER", "BY", "GROUP", - "HAVING", "LIMIT", "WHERE", "INTO", - "VALUES", "INTEGER", "FLOAT", "BLOB", - "REGISTER", "VARIABLE", "CASE", "WHEN", - "THEN", "ELSE", "INDEX", "ALTER", - "TO", "ADD", "COLUMNKW", "error", - "input", "cmdlist", "ecmd", "cmdx", - "cmd", "explain", "transtype", "trans_opt", - "nm", "create_table", "create_table_args", "temp", - "ifnotexists", "dbnm", "columnlist", "conslist_opt", - "select", "column", "columnid", "type", - "carglist", "id", "ids", "typetoken", - "typename", "signed", "plus_num", "minus_num", - "carg", "ccons", "term", "expr", - "onconf", "sortorder", "autoinc", "idxlist_opt", - "refargs", "defer_subclause", "refarg", "refact", - "init_deferred_pred_opt", "conslist", "tcons", "idxlist", - "defer_subclause_opt", "orconf", "resolvetype", "raisetype", - "ifexists", "fullname", "oneselect", "multiselect_op", - "distinct", "selcollist", "from", "where_opt", - "groupby_opt", "having_opt", "orderby_opt", "limit_opt", - "sclp", "as", "seltablist", "stl_prefix", - "joinop", "on_opt", "using_opt", "seltablist_paren", - "joinop2", "inscollist", "sortlist", "sortitem", - "exprlist", "setlist", "insert_cmd", "inscollist_opt", - "itemlist", "likeop", "escape", "between_op", - "in_op", "case_operand", "case_exprlist", "case_else", - "expritem", "uniqueflag", "idxitem", "collate", - "nmnum", "plus_opt", "number", "trigger_decl", - "trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause", - "when_clause", "trigger_cmd", "database_kw_opt", "key_opt", - "add_column_fullname", "kwcolumn_opt", "create_vtab", "vtabarglist", - "vtabarg", "vtabargtoken", "lp", "anylist", + "TRIGGER", "VACUUM", "VIEW", "VIRTUAL", + "REINDEX", "RENAME", "CTIME_KW", "ANY", + "OR", "AND", "IS", "BETWEEN", + "IN", "ISNULL", "NOTNULL", "NE", + "EQ", "GT", "LE", "LT", + "GE", "ESCAPE", "BITAND", "BITOR", + "LSHIFT", "RSHIFT", "PLUS", "MINUS", + "STAR", "SLASH", "REM", "CONCAT", + "COLLATE", "UMINUS", "UPLUS", "BITNOT", + "STRING", "JOIN_KW", "CONSTRAINT", "DEFAULT", + "NULL", "PRIMARY", "UNIQUE", "CHECK", + "REFERENCES", "AUTOINCR", "ON", "DELETE", + "UPDATE", "INSERT", "SET", "DEFERRABLE", + "FOREIGN", "DROP", "UNION", "ALL", + "EXCEPT", "INTERSECT", "SELECT", "DISTINCT", + "DOT", "FROM", "JOIN", "USING", + "ORDER", "BY", "GROUP", "HAVING", + "LIMIT", "WHERE", "INTO", "VALUES", + "INTEGER", "FLOAT", "BLOB", "REGISTER", + "VARIABLE", "CASE", "WHEN", "THEN", + "ELSE", "INDEX", "ALTER", "TO", + "ADD", "COLUMNKW", "error", "input", + "cmdlist", "ecmd", "cmdx", "cmd", + "explain", "transtype", "trans_opt", "nm", + "create_table", "create_table_args", "temp", "ifnotexists", + "dbnm", "columnlist", "conslist_opt", "select", + "column", "columnid", "type", "carglist", + "id", "ids", "typetoken", "typename", + "signed", "plus_num", "minus_num", "carg", + "ccons", "term", "expr", "onconf", + "sortorder", "autoinc", "idxlist_opt", "refargs", + "defer_subclause", "refarg", "refact", "init_deferred_pred_opt", + "conslist", "tcons", "idxlist", "defer_subclause_opt", + "orconf", "resolvetype", "raisetype", "ifexists", + "fullname", "oneselect", "multiselect_op", "distinct", + "selcollist", "from", "where_opt", "groupby_opt", + "having_opt", "orderby_opt", "limit_opt", "sclp", + "as", "seltablist", "stl_prefix", "joinop", + "on_opt", "using_opt", "seltablist_paren", "joinop2", + "inscollist", "sortlist", "sortitem", "exprlist", + "setlist", "insert_cmd", "inscollist_opt", "itemlist", + "likeop", "escape", "between_op", "in_op", + "case_operand", "case_exprlist", "case_else", "expritem", + "uniqueflag", "idxitem", "collate", "nmnum", + "plus_opt", "number", "trigger_decl", "trigger_cmd_list", + "trigger_time", "trigger_event", "foreach_clause", "when_clause", + "trigger_cmd", "database_kw_opt", "key_opt", "add_column_fullname", + "kwcolumn_opt", "create_vtab", "vtabarglist", "vtabarg", + "vtabargtoken", "lp", "anylist", }; #endif /* NDEBUG */ @@ -1147,67 +1154,74 @@ static const char *const yyRuleName[] = /* 266 */ "trigger_event ::= UPDATE OF inscollist", /* 267 */ "foreach_clause ::=", /* 268 */ "foreach_clause ::= FOR EACH ROW", - /* 269 */ "foreach_clause ::= FOR EACH STATEMENT", - /* 270 */ "when_clause ::=", - /* 271 */ "when_clause ::= WHEN expr", - /* 272 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", - /* 273 */ "trigger_cmd_list ::=", - /* 274 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt", - /* 275 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP", - /* 276 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select", - /* 277 */ "trigger_cmd ::= DELETE FROM nm where_opt", - /* 278 */ "trigger_cmd ::= select", - /* 279 */ "expr ::= RAISE LP IGNORE RP", - /* 280 */ "expr ::= RAISE LP raisetype COMMA nm RP", - /* 281 */ "raisetype ::= ROLLBACK", - /* 282 */ "raisetype ::= ABORT", - /* 283 */ "raisetype ::= FAIL", - /* 284 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 285 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 269 */ "when_clause ::=", + /* 270 */ "when_clause ::= WHEN expr", + /* 271 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", + /* 272 */ "trigger_cmd_list ::=", + /* 273 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt", + /* 274 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP", + /* 275 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select", + /* 276 */ "trigger_cmd ::= DELETE FROM nm where_opt", + /* 277 */ "trigger_cmd ::= select", + /* 278 */ "expr ::= RAISE LP IGNORE RP", + /* 279 */ "expr ::= RAISE LP raisetype COMMA nm RP", + /* 280 */ "raisetype ::= ROLLBACK", + /* 281 */ "raisetype ::= ABORT", + /* 282 */ "raisetype ::= FAIL", + /* 283 */ "cmd ::= DROP TRIGGER ifexists fullname", + /* 284 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 285 */ "cmd ::= DETACH database_kw_opt expr", /* 286 */ "key_opt ::=", /* 287 */ "key_opt ::= KEY expr", /* 288 */ "database_kw_opt ::= DATABASE", /* 289 */ "database_kw_opt ::=", - /* 290 */ "cmd ::= DETACH database_kw_opt expr", - /* 291 */ "cmd ::= REINDEX", - /* 292 */ "cmd ::= REINDEX nm dbnm", - /* 293 */ "cmd ::= ANALYZE", - /* 294 */ "cmd ::= ANALYZE nm dbnm", - /* 295 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 296 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column", - /* 297 */ "add_column_fullname ::= fullname", - /* 298 */ "kwcolumn_opt ::=", - /* 299 */ "kwcolumn_opt ::= COLUMNKW", - /* 300 */ "cmd ::= create_vtab", - /* 301 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 302 */ "create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm", - /* 303 */ "vtabarglist ::= vtabarg", - /* 304 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 305 */ "vtabarg ::=", - /* 306 */ "vtabarg ::= vtabarg vtabargtoken", - /* 307 */ "vtabargtoken ::= ANY", - /* 308 */ "vtabargtoken ::= lp anylist RP", - /* 309 */ "lp ::= LP", - /* 310 */ "anylist ::=", - /* 311 */ "anylist ::= anylist ANY", + /* 290 */ "cmd ::= REINDEX", + /* 291 */ "cmd ::= REINDEX nm dbnm", + /* 292 */ "cmd ::= ANALYZE", + /* 293 */ "cmd ::= ANALYZE nm dbnm", + /* 294 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", + /* 295 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column", + /* 296 */ "add_column_fullname ::= fullname", + /* 297 */ "kwcolumn_opt ::=", + /* 298 */ "kwcolumn_opt ::= COLUMNKW", + /* 299 */ "cmd ::= create_vtab", + /* 300 */ "cmd ::= create_vtab LP vtabarglist RP", + /* 301 */ "create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm", + /* 302 */ "vtabarglist ::= vtabarg", + /* 303 */ "vtabarglist ::= vtabarglist COMMA vtabarg", + /* 304 */ "vtabarg ::=", + /* 305 */ "vtabarg ::= vtabarg vtabargtoken", + /* 306 */ "vtabargtoken ::= ANY", + /* 307 */ "vtabargtoken ::= lp anylist RP", + /* 308 */ "lp ::= LP", + /* 309 */ "anylist ::=", + /* 310 */ "anylist ::= anylist ANY", }; #endif /* NDEBUG */ + +#if YYSTACKDEPTH<=0 /* -** This function returns the symbolic name associated with a token -** value. +** Try to increase the size of the parser stack. */ -const char *sqlite3ParserTokenName(int tokenType){ +static void yyGrowStack(yyParser *p){ + int newSize; + yyStackEntry *pNew; + + newSize = p->yystksz*2 + 100; + pNew = realloc(p->yystack, newSize*sizeof(pNew[0])); + if( pNew ){ + p->yystack = pNew; + p->yystksz = newSize; #ifndef NDEBUG - if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){ - return yyTokenName[tokenType]; - }else{ - return "Unknown"; + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sStack grows to %d entries!\n", + yyTracePrompt, p->yystksz); + } +#endif } -#else - return ""; +} #endif -} /* ** This function allocates a new parser. @@ -1226,6 +1240,9 @@ void *sqlite3ParserAlloc(void *(*mallocP pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) ); if( pParser ){ pParser->yyidx = -1; +#if YYSTACKDEPTH<=0 + yyGrowStack(pParser); +#endif } return pParser; } @@ -1247,82 +1264,74 @@ static void yy_destructor(YYCODETYPE yym ** which appear on the RHS of the rule, but which are not used ** inside the C code. */ - case 156: - case 190: - case 207: -#line 375 "parse.y" -{sqlite3SelectDelete((yypminor->yy43));} -#line 1257 "parse.c" + case 155: + case 189: + case 206: +#line 374 "parse.y" +{sqlite3SelectDelete((yypminor->yy219));} +#line 1274 "parse.c" break; + case 169: case 170: - case 171: + case 194: + case 196: + case 204: + case 210: + case 217: + case 220: + case 222: + case 223: + case 235: +#line 623 "parse.y" +{sqlite3ExprDelete((yypminor->yy172));} +#line 1289 "parse.c" + break; + case 174: + case 182: + case 192: case 195: case 197: - case 205: + case 199: + case 209: case 211: - case 218: + case 212: + case 215: case 221: - case 223: - case 224: - case 236: -#line 616 "parse.y" -{sqlite3ExprDelete((yypminor->yy450));} -#line 1272 "parse.c" +#line 863 "parse.y" +{sqlite3ExprListDelete((yypminor->yy174));} +#line 1304 "parse.c" break; - case 175: - case 183: + case 188: case 193: - case 196: - case 198: - case 200: - case 210: - case 212: - case 213: - case 216: - case 222: -#line 856 "parse.y" -{sqlite3ExprListDelete((yypminor->yy242));} -#line 1287 "parse.c" - break; - case 189: - case 194: + case 201: case 202: - case 203: -#line 488 "parse.y" -{sqlite3SrcListDelete((yypminor->yy419));} -#line 1295 "parse.c" +#line 487 "parse.y" +{sqlite3SrcListDelete((yypminor->yy373));} +#line 1312 "parse.c" break; - case 199: -#line 546 "parse.y" -{ - sqlite3ExprDelete((yypminor->yy84).pLimit); - sqlite3ExprDelete((yypminor->yy84).pOffset); -} -#line 1303 "parse.c" + case 205: + case 208: + case 214: +#line 504 "parse.y" +{sqlite3IdListDelete((yypminor->yy432));} +#line 1319 "parse.c" break; - case 206: - case 209: - case 215: -#line 505 "parse.y" -{sqlite3IdListDelete((yypminor->yy352));} -#line 1310 "parse.c" + case 231: + case 236: +#line 964 "parse.y" +{sqlite3DeleteTriggerStep((yypminor->yy243));} +#line 1325 "parse.c" break; - case 232: - case 237: -#line 957 "parse.y" -{sqlite3DeleteTriggerStep((yypminor->yy75));} -#line 1316 "parse.c" + case 233: +#line 950 "parse.y" +{sqlite3IdListDelete((yypminor->yy370).b);} +#line 1330 "parse.c" break; - case 234: -#line 941 "parse.y" -{sqlite3IdListDelete((yypminor->yy354).b);} -#line 1321 "parse.c" + case 238: +#line 1037 "parse.y" +{sqlite3ExprDelete((yypminor->yy386));} +#line 1335 "parse.c" break; - case 239: -#line 1025 "parse.y" -{sqlite3ExprDelete((yypminor->yy158));} -#line 1326 "parse.c" - break; default: break; /* If no destructor action specified: do nothing */ } } @@ -1372,6 +1381,9 @@ void sqlite3ParserFree( yyParser *pParser = (yyParser*)p; if( pParser==0 ) return; while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser); +#if YYSTACKDEPTH<=0 + free(pParser->yystack); +#endif (*freeProc)((void*)pParser); } @@ -1464,6 +1476,28 @@ static int yy_find_reduce_action( } /* +** The following routine is called if the stack overflows. +*/ +static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){ + sqlite3ParserARG_FETCH; + yypParser->yyidx--; +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); + } +#endif + while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); + /* Here code is inserted which will execute if the parser + ** stack every overflows */ +#line 44 "parse.y" + + sqlite3ErrorMsg(pParse, "parser stack overflow"); + pParse->parseError = 1; +#line 1499 "parse.c" + sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument var */ +} + +/* ** Perform a shift action. */ static void yy_shift( @@ -1474,25 +1508,20 @@ static void yy_shift( ){ yyStackEntry *yytos; yypParser->yyidx++; +#if YYSTACKDEPTH>0 if( yypParser->yyidx>=YYSTACKDEPTH ){ - sqlite3ParserARG_FETCH; - yypParser->yyidx--; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); - } -#endif - while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); - /* Here code is inserted which will execute if the parser - ** stack every overflows */ -#line 44 "parse.y" - - sqlite3ErrorMsg(pParse, "parser stack overflow"); - pParse->parseError = 1; -#line 1495 "parse.c" - sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument var */ - return; + yyStackOverflow(yypParser, yypMinor); + return; } +#else + if( yypParser->yyidx>=yypParser->yystksz ){ + yyGrowStack(yypParser); + if( yypParser->yyidx>=yypParser->yystksz ){ + yyStackOverflow(yypParser, yypMinor); + return; + } + } +#endif yytos = &yypParser->yystack[yypParser->yyidx]; yytos->stateno = yyNewState; yytos->major = yyMajor; @@ -1516,318 +1545,317 @@ static const struct { YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ unsigned char nrhs; /* Number of right-hand side symbols in the rule */ } yyRuleInfo[] = { + { 139, 1 }, + { 140, 2 }, { 140, 1 }, - { 141, 2 }, - { 141, 1 }, - { 143, 1 }, { 142, 1 }, - { 142, 3 }, - { 145, 0 }, - { 145, 1 }, - { 145, 3 }, + { 141, 1 }, + { 141, 3 }, + { 144, 0 }, + { 144, 1 }, { 144, 3 }, - { 147, 0 }, - { 147, 1 }, - { 147, 2 }, + { 143, 3 }, { 146, 0 }, { 146, 1 }, - { 146, 1 }, - { 146, 1 }, - { 144, 2 }, - { 144, 2 }, - { 144, 2 }, - { 144, 2 }, - { 149, 6 }, - { 152, 0 }, - { 152, 3 }, - { 151, 1 }, + { 146, 2 }, + { 145, 0 }, + { 145, 1 }, + { 145, 1 }, + { 145, 1 }, + { 143, 2 }, + { 143, 2 }, + { 143, 2 }, + { 143, 2 }, + { 148, 6 }, { 151, 0 }, - { 150, 4 }, - { 150, 2 }, - { 154, 3 }, - { 154, 1 }, - { 157, 3 }, - { 158, 1 }, + { 151, 3 }, + { 150, 1 }, + { 150, 0 }, + { 149, 4 }, + { 149, 2 }, + { 153, 3 }, + { 153, 1 }, + { 156, 3 }, + { 157, 1 }, + { 160, 1 }, { 161, 1 }, + { 147, 1 }, + { 147, 1 }, + { 147, 1 }, + { 158, 0 }, + { 158, 1 }, { 162, 1 }, - { 148, 1 }, - { 148, 1 }, - { 148, 1 }, - { 159, 0 }, - { 159, 1 }, + { 162, 4 }, + { 162, 6 }, { 163, 1 }, - { 163, 4 }, - { 163, 6 }, + { 163, 2 }, { 164, 1 }, - { 164, 2 }, - { 165, 1 }, - { 165, 1 }, - { 160, 2 }, - { 160, 0 }, + { 164, 1 }, + { 159, 2 }, + { 159, 0 }, + { 167, 3 }, + { 167, 1 }, + { 168, 2 }, + { 168, 4 }, { 168, 3 }, + { 168, 3 }, + { 168, 2 }, + { 168, 2 }, + { 168, 3 }, + { 168, 5 }, + { 168, 2 }, + { 168, 4 }, + { 168, 4 }, { 168, 1 }, - { 169, 2 }, - { 169, 4 }, - { 169, 3 }, - { 169, 3 }, - { 169, 2 }, - { 169, 2 }, - { 169, 3 }, - { 169, 5 }, - { 169, 2 }, - { 169, 4 }, - { 169, 4 }, - { 169, 1 }, - { 169, 2 }, - { 174, 0 }, - { 174, 1 }, - { 176, 0 }, - { 176, 2 }, + { 168, 2 }, + { 173, 0 }, + { 173, 1 }, + { 175, 0 }, + { 175, 2 }, + { 177, 2 }, + { 177, 3 }, + { 177, 3 }, + { 177, 3 }, { 178, 2 }, - { 178, 3 }, - { 178, 3 }, - { 178, 3 }, + { 178, 2 }, + { 178, 1 }, + { 178, 1 }, + { 176, 3 }, + { 176, 2 }, + { 179, 0 }, { 179, 2 }, { 179, 2 }, - { 179, 1 }, - { 179, 1 }, - { 177, 3 }, - { 177, 2 }, - { 180, 0 }, + { 154, 0 }, + { 154, 2 }, + { 180, 3 }, { 180, 2 }, - { 180, 2 }, - { 155, 0 }, - { 155, 2 }, - { 181, 3 }, + { 180, 1 }, { 181, 2 }, - { 181, 1 }, - { 182, 2 }, - { 182, 7 }, - { 182, 5 }, - { 182, 5 }, - { 182, 10 }, + { 181, 7 }, + { 181, 5 }, + { 181, 5 }, + { 181, 10 }, + { 183, 0 }, + { 183, 1 }, + { 171, 0 }, + { 171, 3 }, { 184, 0 }, - { 184, 1 }, - { 172, 0 }, - { 172, 3 }, - { 185, 0 }, - { 185, 2 }, - { 186, 1 }, - { 186, 1 }, - { 186, 1 }, - { 144, 4 }, - { 188, 2 }, - { 188, 0 }, - { 144, 8 }, - { 144, 4 }, - { 144, 1 }, - { 156, 1 }, - { 156, 3 }, + { 184, 2 }, + { 185, 1 }, + { 185, 1 }, + { 185, 1 }, + { 143, 4 }, + { 187, 2 }, + { 187, 0 }, + { 143, 8 }, + { 143, 4 }, + { 143, 1 }, + { 155, 1 }, + { 155, 3 }, + { 190, 1 }, + { 190, 2 }, + { 190, 1 }, + { 189, 9 }, { 191, 1 }, - { 191, 2 }, { 191, 1 }, - { 190, 9 }, - { 192, 1 }, - { 192, 1 }, - { 192, 0 }, + { 191, 0 }, + { 199, 2 }, + { 199, 0 }, + { 192, 3 }, + { 192, 2 }, + { 192, 4 }, { 200, 2 }, + { 200, 1 }, { 200, 0 }, - { 193, 3 }, + { 193, 0 }, { 193, 2 }, - { 193, 4 }, - { 201, 2 }, - { 201, 1 }, - { 201, 0 }, - { 194, 0 }, - { 194, 2 }, + { 202, 2 }, + { 202, 0 }, + { 201, 6 }, + { 201, 7 }, + { 206, 1 }, + { 206, 1 }, + { 152, 0 }, + { 152, 2 }, + { 188, 2 }, + { 203, 1 }, { 203, 2 }, - { 203, 0 }, - { 202, 6 }, - { 202, 7 }, - { 207, 1 }, - { 207, 1 }, - { 153, 0 }, - { 153, 2 }, - { 189, 2 }, - { 204, 1 }, + { 203, 3 }, + { 203, 4 }, { 204, 2 }, - { 204, 3 }, - { 204, 4 }, - { 205, 2 }, + { 204, 0 }, + { 205, 4 }, { 205, 0 }, - { 206, 4 }, - { 206, 0 }, - { 198, 0 }, - { 198, 3 }, - { 210, 4 }, - { 210, 2 }, - { 211, 1 }, - { 173, 1 }, - { 173, 1 }, - { 173, 0 }, - { 196, 0 }, - { 196, 3 }, { 197, 0 }, - { 197, 2 }, - { 199, 0 }, - { 199, 2 }, - { 199, 4 }, - { 199, 4 }, - { 144, 4 }, + { 197, 3 }, + { 209, 4 }, + { 209, 2 }, + { 210, 1 }, + { 172, 1 }, + { 172, 1 }, + { 172, 0 }, { 195, 0 }, - { 195, 2 }, - { 144, 6 }, - { 213, 5 }, - { 213, 3 }, - { 144, 8 }, - { 144, 5 }, - { 144, 6 }, - { 214, 2 }, - { 214, 1 }, - { 216, 3 }, - { 216, 1 }, - { 215, 0 }, + { 195, 3 }, + { 196, 0 }, + { 196, 2 }, + { 198, 0 }, + { 198, 2 }, + { 198, 4 }, + { 198, 4 }, + { 143, 4 }, + { 194, 0 }, + { 194, 2 }, + { 143, 6 }, + { 212, 5 }, + { 212, 3 }, + { 143, 8 }, + { 143, 5 }, + { 143, 6 }, + { 213, 2 }, + { 213, 1 }, { 215, 3 }, - { 209, 3 }, - { 209, 1 }, - { 171, 1 }, - { 171, 3 }, + { 215, 1 }, + { 214, 0 }, + { 214, 3 }, + { 208, 3 }, + { 208, 1 }, { 170, 1 }, - { 171, 1 }, - { 171, 1 }, - { 171, 3 }, - { 171, 5 }, + { 170, 3 }, + { 169, 1 }, { 170, 1 }, { 170, 1 }, - { 171, 1 }, - { 171, 1 }, - { 171, 3 }, - { 171, 6 }, - { 171, 5 }, - { 171, 4 }, + { 170, 3 }, + { 170, 5 }, + { 169, 1 }, + { 169, 1 }, { 170, 1 }, - { 171, 3 }, - { 171, 3 }, - { 171, 3 }, - { 171, 3 }, - { 171, 3 }, - { 171, 3 }, - { 171, 3 }, - { 171, 3 }, - { 217, 1 }, + { 170, 1 }, + { 170, 3 }, + { 170, 6 }, + { 170, 5 }, + { 170, 4 }, + { 169, 1 }, + { 170, 3 }, + { 170, 3 }, + { 170, 3 }, + { 170, 3 }, + { 170, 3 }, + { 170, 3 }, + { 170, 3 }, + { 170, 3 }, + { 216, 1 }, + { 216, 2 }, + { 216, 1 }, + { 216, 2 }, { 217, 2 }, - { 217, 1 }, - { 217, 2 }, + { 217, 0 }, + { 170, 4 }, + { 170, 2 }, + { 170, 3 }, + { 170, 3 }, + { 170, 4 }, + { 170, 2 }, + { 170, 2 }, + { 170, 2 }, + { 218, 1 }, { 218, 2 }, - { 218, 0 }, - { 171, 4 }, - { 171, 2 }, - { 171, 3 }, - { 171, 3 }, - { 171, 4 }, - { 171, 2 }, - { 171, 2 }, - { 171, 2 }, + { 170, 5 }, { 219, 1 }, { 219, 2 }, - { 171, 5 }, + { 170, 5 }, + { 170, 3 }, + { 170, 5 }, + { 170, 4 }, + { 170, 4 }, + { 170, 5 }, + { 221, 5 }, + { 221, 4 }, + { 222, 2 }, + { 222, 0 }, { 220, 1 }, - { 220, 2 }, - { 171, 5 }, - { 171, 3 }, - { 171, 5 }, - { 171, 4 }, - { 171, 4 }, - { 171, 5 }, - { 222, 5 }, - { 222, 4 }, - { 223, 2 }, + { 220, 0 }, + { 211, 3 }, + { 211, 1 }, + { 223, 1 }, { 223, 0 }, - { 221, 1 }, - { 221, 0 }, - { 212, 3 }, - { 212, 1 }, + { 143, 11 }, { 224, 1 }, { 224, 0 }, - { 144, 11 }, + { 174, 0 }, + { 174, 3 }, + { 182, 5 }, + { 182, 3 }, { 225, 1 }, - { 225, 0 }, - { 175, 0 }, - { 175, 3 }, - { 183, 5 }, - { 183, 3 }, - { 226, 1 }, - { 227, 0 }, - { 227, 2 }, - { 144, 4 }, - { 144, 1 }, - { 144, 2 }, - { 144, 5 }, - { 144, 5 }, - { 144, 5 }, - { 144, 6 }, - { 144, 3 }, - { 228, 1 }, - { 228, 1 }, + { 226, 0 }, + { 226, 2 }, + { 143, 4 }, + { 143, 1 }, + { 143, 2 }, + { 143, 5 }, + { 143, 5 }, + { 143, 5 }, + { 143, 6 }, + { 143, 3 }, + { 227, 1 }, + { 227, 1 }, + { 165, 2 }, { 166, 2 }, - { 167, 2 }, - { 230, 1 }, { 229, 1 }, - { 229, 0 }, - { 144, 5 }, - { 231, 11 }, + { 228, 1 }, + { 228, 0 }, + { 143, 5 }, + { 230, 11 }, + { 232, 1 }, + { 232, 1 }, + { 232, 2 }, + { 232, 0 }, { 233, 1 }, { 233, 1 }, - { 233, 2 }, - { 233, 0 }, - { 234, 1 }, - { 234, 1 }, + { 233, 3 }, + { 234, 0 }, { 234, 3 }, { 235, 0 }, - { 235, 3 }, - { 235, 3 }, - { 236, 0 }, - { 236, 2 }, - { 232, 3 }, - { 232, 0 }, - { 237, 6 }, - { 237, 8 }, - { 237, 5 }, - { 237, 4 }, + { 235, 2 }, + { 231, 3 }, + { 231, 0 }, + { 236, 6 }, + { 236, 8 }, + { 236, 5 }, + { 236, 4 }, + { 236, 1 }, + { 170, 4 }, + { 170, 6 }, + { 186, 1 }, + { 186, 1 }, + { 186, 1 }, + { 143, 4 }, + { 143, 6 }, + { 143, 3 }, + { 238, 0 }, + { 238, 2 }, { 237, 1 }, - { 171, 4 }, - { 171, 6 }, - { 187, 1 }, - { 187, 1 }, - { 187, 1 }, - { 144, 4 }, - { 144, 6 }, - { 239, 0 }, - { 239, 2 }, - { 238, 1 }, - { 238, 0 }, - { 144, 3 }, - { 144, 1 }, - { 144, 3 }, - { 144, 1 }, - { 144, 3 }, - { 144, 6 }, - { 144, 6 }, + { 237, 0 }, + { 143, 1 }, + { 143, 3 }, + { 143, 1 }, + { 143, 3 }, + { 143, 6 }, + { 143, 6 }, + { 239, 1 }, + { 240, 0 }, { 240, 1 }, - { 241, 0 }, - { 241, 1 }, - { 144, 1 }, - { 144, 4 }, - { 242, 7 }, - { 243, 1 }, - { 243, 3 }, - { 244, 0 }, - { 244, 2 }, + { 143, 1 }, + { 143, 4 }, + { 241, 7 }, + { 242, 1 }, + { 242, 3 }, + { 243, 0 }, + { 243, 2 }, + { 244, 1 }, + { 244, 3 }, { 245, 1 }, - { 245, 3 }, - { 246, 1 }, - { 247, 0 }, - { 247, 2 }, + { 246, 0 }, + { 246, 2 }, }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -1881,35 +1909,75 @@ static void yy_reduce( ** #line ** break; */ + case 0: + case 1: + case 2: + case 4: + case 5: + case 10: + case 11: + case 12: + case 20: + case 28: + case 29: + case 37: + case 44: + case 45: + case 46: + case 47: + case 48: + case 49: + case 55: + case 82: + case 83: + case 84: + case 85: + case 256: + case 257: + case 267: + case 268: + case 288: + case 289: + case 297: + case 298: + case 302: + case 303: + case 305: + case 309: +#line 97 "parse.y" +{ +} +#line 1953 "parse.c" + break; case 3: #line 100 "parse.y" { sqlite3FinishCoding(pParse); } -#line 1890 "parse.c" +#line 1958 "parse.c" break; case 6: #line 103 "parse.y" { sqlite3BeginParse(pParse, 0); } -#line 1895 "parse.c" +#line 1963 "parse.c" break; case 7: #line 105 "parse.y" { sqlite3BeginParse(pParse, 1); } -#line 1900 "parse.c" +#line 1968 "parse.c" break; case 8: #line 106 "parse.y" { sqlite3BeginParse(pParse, 2); } -#line 1905 "parse.c" +#line 1973 "parse.c" break; case 9: #line 112 "parse.y" -{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy316);} -#line 1910 "parse.c" +{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy46);} +#line 1978 "parse.c" break; case 13: #line 117 "parse.y" -{yygotominor.yy316 = TK_DEFERRED;} -#line 1915 "parse.c" +{yygotominor.yy46 = TK_DEFERRED;} +#line 1983 "parse.c" break; case 14: case 15: @@ -1917,26 +1985,26 @@ static void yy_reduce( case 107: case 109: #line 118 "parse.y" -{yygotominor.yy316 = yymsp[0].major;} -#line 1924 "parse.c" +{yygotominor.yy46 = yymsp[0].major;} +#line 1992 "parse.c" break; case 17: case 18: #line 121 "parse.y" {sqlite3CommitTransaction(pParse);} -#line 1930 "parse.c" +#line 1998 "parse.c" break; case 19: #line 123 "parse.y" {sqlite3RollbackTransaction(pParse);} -#line 1935 "parse.c" +#line 2003 "parse.c" break; case 21: #line 128 "parse.y" { - sqlite3StartTable(pParse,&yymsp[-1].minor.yy178,&yymsp[0].minor.yy178,yymsp[-4].minor.yy316,0,0,yymsp[-2].minor.yy316); + sqlite3StartTable(pParse,&yymsp[-1].minor.yy410,&yymsp[0].minor.yy410,yymsp[-4].minor.yy46,0,0,yymsp[-2].minor.yy46); } -#line 1942 "parse.c" +#line 2010 "parse.c" break; case 22: case 25: @@ -1950,8 +2018,8 @@ static void yy_reduce( case 212: case 215: #line 132 "parse.y" -{yygotominor.yy316 = 0;} -#line 1957 "parse.c" +{yygotominor.yy46 = 0;} +#line 2025 "parse.c" break; case 23: case 24: @@ -1962,39 +2030,39 @@ static void yy_reduce( case 213: case 216: #line 133 "parse.y" -{yygotominor.yy316 = 1;} -#line 1969 "parse.c" +{yygotominor.yy46 = 1;} +#line 2037 "parse.c" break; case 26: #line 139 "parse.y" { - sqlite3EndTable(pParse,&yymsp[-1].minor.yy178,&yymsp[0].minor.yy0,0); + sqlite3EndTable(pParse,&yymsp[-1].minor.yy410,&yymsp[0].minor.yy0,0); } -#line 1976 "parse.c" +#line 2044 "parse.c" break; case 27: #line 142 "parse.y" { - sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy43); - sqlite3SelectDelete(yymsp[0].minor.yy43); + sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy219); + sqlite3SelectDelete(yymsp[0].minor.yy219); } -#line 1984 "parse.c" +#line 2052 "parse.c" break; case 30: #line 154 "parse.y" { - yygotominor.yy178.z = yymsp[-2].minor.yy178.z; - yygotominor.yy178.n = (pParse->sLastToken.z-yymsp[-2].minor.yy178.z) + pParse->sLastToken.n; + yygotominor.yy410.z = yymsp[-2].minor.yy410.z; + yygotominor.yy410.n = (pParse->sLastToken.z-yymsp[-2].minor.yy410.z) + pParse->sLastToken.n; } -#line 1992 "parse.c" +#line 2060 "parse.c" break; case 31: #line 158 "parse.y" { - sqlite3AddColumn(pParse,&yymsp[0].minor.yy178); - yygotominor.yy178 = yymsp[0].minor.yy178; + sqlite3AddColumn(pParse,&yymsp[0].minor.yy410); + yygotominor.yy410 = yymsp[0].minor.yy410; } -#line 2000 "parse.c" +#line 2068 "parse.c" break; case 32: case 33: @@ -2003,13 +2071,13 @@ static void yy_reduce( case 36: case 255: #line 168 "parse.y" -{yygotominor.yy178 = yymsp[0].minor.yy0;} -#line 2010 "parse.c" +{yygotominor.yy410 = yymsp[0].minor.yy0;} +#line 2078 "parse.c" break; case 38: #line 229 "parse.y" -{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy178);} -#line 2015 "parse.c" +{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy410);} +#line 2083 "parse.c" break; case 39: case 42: @@ -2023,151 +2091,141 @@ static void yy_reduce( case 253: case 254: #line 230 "parse.y" -{yygotominor.yy178 = yymsp[0].minor.yy178;} -#line 2030 "parse.c" +{yygotominor.yy410 = yymsp[0].minor.yy410;} +#line 2098 "parse.c" break; case 40: #line 231 "parse.y" { - yygotominor.yy178.z = yymsp[-3].minor.yy178.z; - yygotominor.yy178.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy178.z; + yygotominor.yy410.z = yymsp[-3].minor.yy410.z; + yygotominor.yy410.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy410.z; } -#line 2038 "parse.c" +#line 2106 "parse.c" break; case 41: #line 235 "parse.y" { - yygotominor.yy178.z = yymsp[-5].minor.yy178.z; - yygotominor.yy178.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy178.z; + yygotominor.yy410.z = yymsp[-5].minor.yy410.z; + yygotominor.yy410.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy410.z; } -#line 2046 "parse.c" +#line 2114 "parse.c" break; case 43: #line 241 "parse.y" -{yygotominor.yy178.z=yymsp[-1].minor.yy178.z; yygotominor.yy178.n=yymsp[0].minor.yy178.n+(yymsp[0].minor.yy178.z-yymsp[-1].minor.yy178.z);} -#line 2051 "parse.c" +{yygotominor.yy410.z=yymsp[-1].minor.yy410.z; yygotominor.yy410.n=yymsp[0].minor.yy410.n+(yymsp[0].minor.yy410.z-yymsp[-1].minor.yy410.z);} +#line 2119 "parse.c" break; - case 44: -#line 243 "parse.y" -{ yygotominor.yy316 = atoi((char*)yymsp[0].minor.yy178.z); } -#line 2056 "parse.c" - break; - case 45: -#line 244 "parse.y" -{ yygotominor.yy316 = -atoi((char*)yymsp[0].minor.yy178.z); } -#line 2061 "parse.c" - break; case 50: case 52: -#line 253 "parse.y" -{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy450);} -#line 2067 "parse.c" +#line 252 "parse.y" +{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy172);} +#line 2125 "parse.c" break; case 51: -#line 254 "parse.y" -{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy450);} -#line 2072 "parse.c" +#line 253 "parse.y" +{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy172);} +#line 2130 "parse.c" break; case 53: -#line 256 "parse.y" +#line 255 "parse.y" { - Expr *p = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy450, 0, 0); + Expr *p = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy172, 0, 0); sqlite3AddDefaultValue(pParse,p); } -#line 2080 "parse.c" +#line 2138 "parse.c" break; case 54: -#line 260 "parse.y" +#line 259 "parse.y" { - Expr *p = sqlite3Expr(TK_STRING, 0, 0, &yymsp[0].minor.yy178); + Expr *p = sqlite3Expr(TK_STRING, 0, 0, &yymsp[0].minor.yy410); sqlite3AddDefaultValue(pParse,p); } -#line 2088 "parse.c" +#line 2146 "parse.c" break; case 56: -#line 269 "parse.y" -{sqlite3AddNotNull(pParse, yymsp[0].minor.yy316);} -#line 2093 "parse.c" +#line 268 "parse.y" +{sqlite3AddNotNull(pParse, yymsp[0].minor.yy46);} +#line 2151 "parse.c" break; case 57: -#line 271 "parse.y" -{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy316,yymsp[0].minor.yy316,yymsp[-2].minor.yy316);} -#line 2098 "parse.c" +#line 270 "parse.y" +{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy46,yymsp[0].minor.yy46,yymsp[-2].minor.yy46);} +#line 2156 "parse.c" break; case 58: -#line 272 "parse.y" -{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy316,0,0,0,0);} -#line 2103 "parse.c" +#line 271 "parse.y" +{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy46,0,0,0,0);} +#line 2161 "parse.c" break; case 59: -#line 273 "parse.y" -{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy450);} -#line 2108 "parse.c" +#line 272 "parse.y" +{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy172);} +#line 2166 "parse.c" break; case 60: -#line 275 "parse.y" -{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy178,yymsp[-1].minor.yy242,yymsp[0].minor.yy316);} -#line 2113 "parse.c" +#line 274 "parse.y" +{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy410,yymsp[-1].minor.yy174,yymsp[0].minor.yy46);} +#line 2171 "parse.c" break; case 61: -#line 276 "parse.y" -{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy316);} -#line 2118 "parse.c" +#line 275 "parse.y" +{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy46);} +#line 2176 "parse.c" break; case 62: -#line 277 "parse.y" -{sqlite3AddCollateType(pParse, (char*)yymsp[0].minor.yy178.z, yymsp[0].minor.yy178.n);} -#line 2123 "parse.c" +#line 276 "parse.y" +{sqlite3AddCollateType(pParse, (char*)yymsp[0].minor.yy410.z, yymsp[0].minor.yy410.n);} +#line 2181 "parse.c" break; case 65: -#line 290 "parse.y" -{ yygotominor.yy316 = OE_Restrict * 0x010101; } -#line 2128 "parse.c" +#line 289 "parse.y" +{ yygotominor.yy46 = OE_Restrict * 0x010101; } +#line 2186 "parse.c" break; case 66: -#line 291 "parse.y" -{ yygotominor.yy316 = (yymsp[-1].minor.yy316 & yymsp[0].minor.yy207.mask) | yymsp[0].minor.yy207.value; } -#line 2133 "parse.c" +#line 290 "parse.y" +{ yygotominor.yy46 = (yymsp[-1].minor.yy46 & yymsp[0].minor.yy405.mask) | yymsp[0].minor.yy405.value; } +#line 2191 "parse.c" break; case 67: -#line 293 "parse.y" -{ yygotominor.yy207.value = 0; yygotominor.yy207.mask = 0x000000; } -#line 2138 "parse.c" +#line 292 "parse.y" +{ yygotominor.yy405.value = 0; yygotominor.yy405.mask = 0x000000; } +#line 2196 "parse.c" break; case 68: -#line 294 "parse.y" -{ yygotominor.yy207.value = yymsp[0].minor.yy316; yygotominor.yy207.mask = 0x0000ff; } -#line 2143 "parse.c" +#line 293 "parse.y" +{ yygotominor.yy405.value = yymsp[0].minor.yy46; yygotominor.yy405.mask = 0x0000ff; } +#line 2201 "parse.c" break; case 69: -#line 295 "parse.y" -{ yygotominor.yy207.value = yymsp[0].minor.yy316<<8; yygotominor.yy207.mask = 0x00ff00; } -#line 2148 "parse.c" +#line 294 "parse.y" +{ yygotominor.yy405.value = yymsp[0].minor.yy46<<8; yygotominor.yy405.mask = 0x00ff00; } +#line 2206 "parse.c" break; case 70: -#line 296 "parse.y" -{ yygotominor.yy207.value = yymsp[0].minor.yy316<<16; yygotominor.yy207.mask = 0xff0000; } -#line 2153 "parse.c" +#line 295 "parse.y" +{ yygotominor.yy405.value = yymsp[0].minor.yy46<<16; yygotominor.yy405.mask = 0xff0000; } +#line 2211 "parse.c" break; case 71: -#line 298 "parse.y" -{ yygotominor.yy316 = OE_SetNull; } -#line 2158 "parse.c" +#line 297 "parse.y" +{ yygotominor.yy46 = OE_SetNull; } +#line 2216 "parse.c" break; case 72: -#line 299 "parse.y" -{ yygotominor.yy316 = OE_SetDflt; } -#line 2163 "parse.c" +#line 298 "parse.y" +{ yygotominor.yy46 = OE_SetDflt; } +#line 2221 "parse.c" break; case 73: -#line 300 "parse.y" -{ yygotominor.yy316 = OE_Cascade; } -#line 2168 "parse.c" +#line 299 "parse.y" +{ yygotominor.yy46 = OE_Cascade; } +#line 2226 "parse.c" break; case 74: -#line 301 "parse.y" -{ yygotominor.yy316 = OE_Restrict; } -#line 2173 "parse.c" +#line 300 "parse.y" +{ yygotominor.yy46 = OE_Restrict; } +#line 2231 "parse.c" break; case 75: case 76: @@ -2176,237 +2234,237 @@ static void yy_reduce( case 95: case 96: case 166: -#line 303 "parse.y" -{yygotominor.yy316 = yymsp[0].minor.yy316;} -#line 2184 "parse.c" +#line 302 "parse.y" +{yygotominor.yy46 = yymsp[0].minor.yy46;} +#line 2242 "parse.c" break; case 80: -#line 313 "parse.y" -{yygotominor.yy178.n = 0; yygotominor.yy178.z = 0;} -#line 2189 "parse.c" +#line 312 "parse.y" +{yygotominor.yy410.n = 0; yygotominor.yy410.z = 0;} +#line 2247 "parse.c" break; case 81: -#line 314 "parse.y" -{yygotominor.yy178 = yymsp[-1].minor.yy0;} -#line 2194 "parse.c" +#line 313 "parse.y" +{yygotominor.yy410 = yymsp[-1].minor.yy0;} +#line 2252 "parse.c" break; case 86: -#line 320 "parse.y" -{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy242,yymsp[0].minor.yy316,yymsp[-2].minor.yy316,0);} -#line 2199 "parse.c" +#line 319 "parse.y" +{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy174,yymsp[0].minor.yy46,yymsp[-2].minor.yy46,0);} +#line 2257 "parse.c" break; case 87: -#line 322 "parse.y" -{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy242,yymsp[0].minor.yy316,0,0,0,0);} -#line 2204 "parse.c" +#line 321 "parse.y" +{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy174,yymsp[0].minor.yy46,0,0,0,0);} +#line 2262 "parse.c" break; case 88: -#line 323 "parse.y" -{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy450);} -#line 2209 "parse.c" +#line 322 "parse.y" +{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy172);} +#line 2267 "parse.c" break; case 89: -#line 325 "parse.y" +#line 324 "parse.y" { - sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy242, &yymsp[-3].minor.yy178, yymsp[-2].minor.yy242, yymsp[-1].minor.yy316); - sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy316); + sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy174, &yymsp[-3].minor.yy410, yymsp[-2].minor.yy174, yymsp[-1].minor.yy46); + sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy46); } -#line 2217 "parse.c" +#line 2275 "parse.c" break; case 92: case 94: -#line 339 "parse.y" -{yygotominor.yy316 = OE_Default;} -#line 2223 "parse.c" +#line 338 "parse.y" +{yygotominor.yy46 = OE_Default;} +#line 2281 "parse.c" break; case 97: -#line 344 "parse.y" -{yygotominor.yy316 = OE_Ignore;} -#line 2228 "parse.c" +#line 343 "parse.y" +{yygotominor.yy46 = OE_Ignore;} +#line 2286 "parse.c" break; case 98: case 167: -#line 345 "parse.y" -{yygotominor.yy316 = OE_Replace;} -#line 2234 "parse.c" +#line 344 "parse.y" +{yygotominor.yy46 = OE_Replace;} +#line 2292 "parse.c" break; case 99: -#line 349 "parse.y" +#line 348 "parse.y" { - sqlite3DropTable(pParse, yymsp[0].minor.yy419, 0, yymsp[-1].minor.yy316); + sqlite3DropTable(pParse, yymsp[0].minor.yy373, 0, yymsp[-1].minor.yy46); } -#line 2241 "parse.c" +#line 2299 "parse.c" break; case 102: -#line 359 "parse.y" +#line 358 "parse.y" { - sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy178, &yymsp[-2].minor.yy178, yymsp[0].minor.yy43, yymsp[-6].minor.yy316, yymsp[-4].minor.yy316); + sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy410, &yymsp[-2].minor.yy410, yymsp[0].minor.yy219, yymsp[-6].minor.yy46, yymsp[-4].minor.yy46); } -#line 2248 "parse.c" +#line 2306 "parse.c" break; case 103: -#line 362 "parse.y" +#line 361 "parse.y" { - sqlite3DropTable(pParse, yymsp[0].minor.yy419, 1, yymsp[-1].minor.yy316); + sqlite3DropTable(pParse, yymsp[0].minor.yy373, 1, yymsp[-1].minor.yy46); } -#line 2255 "parse.c" +#line 2313 "parse.c" break; case 104: -#line 369 "parse.y" +#line 368 "parse.y" { - sqlite3Select(pParse, yymsp[0].minor.yy43, SRT_Callback, 0, 0, 0, 0, 0); - sqlite3SelectDelete(yymsp[0].minor.yy43); + sqlite3Select(pParse, yymsp[0].minor.yy219, SRT_Callback, 0, 0, 0, 0, 0); + sqlite3SelectDelete(yymsp[0].minor.yy219); } -#line 2263 "parse.c" +#line 2321 "parse.c" break; case 105: case 128: -#line 379 "parse.y" -{yygotominor.yy43 = yymsp[0].minor.yy43;} -#line 2269 "parse.c" +#line 378 "parse.y" +{yygotominor.yy219 = yymsp[0].minor.yy219;} +#line 2327 "parse.c" break; case 106: -#line 381 "parse.y" +#line 380 "parse.y" { - if( yymsp[0].minor.yy43 ){ - yymsp[0].minor.yy43->op = yymsp[-1].minor.yy316; - yymsp[0].minor.yy43->pPrior = yymsp[-2].minor.yy43; + if( yymsp[0].minor.yy219 ){ + yymsp[0].minor.yy219->op = yymsp[-1].minor.yy46; + yymsp[0].minor.yy219->pPrior = yymsp[-2].minor.yy219; } - yygotominor.yy43 = yymsp[0].minor.yy43; + yygotominor.yy219 = yymsp[0].minor.yy219; } -#line 2280 "parse.c" +#line 2338 "parse.c" break; case 108: -#line 390 "parse.y" -{yygotominor.yy316 = TK_ALL;} -#line 2285 "parse.c" +#line 389 "parse.y" +{yygotominor.yy46 = TK_ALL;} +#line 2343 "parse.c" break; case 110: -#line 394 "parse.y" +#line 393 "parse.y" { - yygotominor.yy43 = sqlite3SelectNew(yymsp[-6].minor.yy242,yymsp[-5].minor.yy419,yymsp[-4].minor.yy450,yymsp[-3].minor.yy242,yymsp[-2].minor.yy450,yymsp[-1].minor.yy242,yymsp[-7].minor.yy316,yymsp[0].minor.yy84.pLimit,yymsp[0].minor.yy84.pOffset); + yygotominor.yy219 = sqlite3SelectNew(yymsp[-6].minor.yy174,yymsp[-5].minor.yy373,yymsp[-4].minor.yy172,yymsp[-3].minor.yy174,yymsp[-2].minor.yy172,yymsp[-1].minor.yy174,yymsp[-7].minor.yy46,yymsp[0].minor.yy234.pLimit,yymsp[0].minor.yy234.pOffset); } -#line 2292 "parse.c" +#line 2350 "parse.c" break; case 114: case 237: -#line 415 "parse.y" -{yygotominor.yy242 = yymsp[-1].minor.yy242;} -#line 2298 "parse.c" +#line 414 "parse.y" +{yygotominor.yy174 = yymsp[-1].minor.yy174;} +#line 2356 "parse.c" break; case 115: case 141: case 149: case 236: -#line 416 "parse.y" -{yygotominor.yy242 = 0;} -#line 2306 "parse.c" +#line 415 "parse.y" +{yygotominor.yy174 = 0;} +#line 2364 "parse.c" break; case 116: -#line 417 "parse.y" +#line 416 "parse.y" { - yygotominor.yy242 = sqlite3ExprListAppend(yymsp[-2].minor.yy242,yymsp[-1].minor.yy450,yymsp[0].minor.yy178.n?&yymsp[0].minor.yy178:0); + yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-2].minor.yy174,yymsp[-1].minor.yy172,yymsp[0].minor.yy410.n?&yymsp[0].minor.yy410:0); } -#line 2313 "parse.c" +#line 2371 "parse.c" break; case 117: -#line 420 "parse.y" +#line 419 "parse.y" { - yygotominor.yy242 = sqlite3ExprListAppend(yymsp[-1].minor.yy242, sqlite3Expr(TK_ALL, 0, 0, 0), 0); + yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-1].minor.yy174, sqlite3Expr(TK_ALL, 0, 0, 0), 0); } -#line 2320 "parse.c" +#line 2378 "parse.c" break; case 118: -#line 423 "parse.y" +#line 422 "parse.y" { Expr *pRight = sqlite3Expr(TK_ALL, 0, 0, 0); - Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy178); - yygotominor.yy242 = sqlite3ExprListAppend(yymsp[-3].minor.yy242, sqlite3Expr(TK_DOT, pLeft, pRight, 0), 0); + Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy410); + yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-3].minor.yy174, sqlite3Expr(TK_DOT, pLeft, pRight, 0), 0); } -#line 2329 "parse.c" +#line 2387 "parse.c" break; case 121: -#line 435 "parse.y" -{yygotominor.yy178.n = 0;} -#line 2334 "parse.c" +#line 434 "parse.y" +{yygotominor.yy410.n = 0;} +#line 2392 "parse.c" break; case 122: -#line 447 "parse.y" -{yygotominor.yy419 = sqliteMalloc(sizeof(*yygotominor.yy419));} -#line 2339 "parse.c" +#line 446 "parse.y" +{yygotominor.yy373 = sqliteMalloc(sizeof(*yygotominor.yy373));} +#line 2397 "parse.c" break; case 123: -#line 448 "parse.y" +#line 447 "parse.y" { - yygotominor.yy419 = yymsp[0].minor.yy419; - sqlite3SrcListShiftJoinType(yygotominor.yy419); + yygotominor.yy373 = yymsp[0].minor.yy373; + sqlite3SrcListShiftJoinType(yygotominor.yy373); } -#line 2347 "parse.c" +#line 2405 "parse.c" break; case 124: -#line 456 "parse.y" +#line 455 "parse.y" { - yygotominor.yy419 = yymsp[-1].minor.yy419; - if( yygotominor.yy419 && yygotominor.yy419->nSrc>0 ) yygotominor.yy419->a[yygotominor.yy419->nSrc-1].jointype = yymsp[0].minor.yy316; + yygotominor.yy373 = yymsp[-1].minor.yy373; + if( yygotominor.yy373 && yygotominor.yy373->nSrc>0 ) yygotominor.yy373->a[yygotominor.yy373->nSrc-1].jointype = yymsp[0].minor.yy46; } -#line 2355 "parse.c" +#line 2413 "parse.c" break; case 125: -#line 460 "parse.y" -{yygotominor.yy419 = 0;} -#line 2360 "parse.c" +#line 459 "parse.y" +{yygotominor.yy373 = 0;} +#line 2418 "parse.c" break; case 126: -#line 461 "parse.y" +#line 460 "parse.y" { - yygotominor.yy419 = sqlite3SrcListAppendFromTerm(yymsp[-5].minor.yy419,&yymsp[-4].minor.yy178,&yymsp[-3].minor.yy178,&yymsp[-2].minor.yy178,0,yymsp[-1].minor.yy450,yymsp[0].minor.yy352); + yygotominor.yy373 = sqlite3SrcListAppendFromTerm(yymsp[-5].minor.yy373,&yymsp[-4].minor.yy410,&yymsp[-3].minor.yy410,&yymsp[-2].minor.yy410,0,yymsp[-1].minor.yy172,yymsp[0].minor.yy432); } -#line 2367 "parse.c" +#line 2425 "parse.c" break; case 127: -#line 466 "parse.y" +#line 465 "parse.y" { - yygotominor.yy419 = sqlite3SrcListAppendFromTerm(yymsp[-6].minor.yy419,0,0,&yymsp[-2].minor.yy178,yymsp[-4].minor.yy43,yymsp[-1].minor.yy450,yymsp[0].minor.yy352); + yygotominor.yy373 = sqlite3SrcListAppendFromTerm(yymsp[-6].minor.yy373,0,0,&yymsp[-2].minor.yy410,yymsp[-4].minor.yy219,yymsp[-1].minor.yy172,yymsp[0].minor.yy432); } -#line 2374 "parse.c" +#line 2432 "parse.c" break; case 129: -#line 477 "parse.y" +#line 476 "parse.y" { - sqlite3SrcListShiftJoinType(yymsp[0].minor.yy419); - yygotominor.yy43 = sqlite3SelectNew(0,yymsp[0].minor.yy419,0,0,0,0,0,0,0); + sqlite3SrcListShiftJoinType(yymsp[0].minor.yy373); + yygotominor.yy219 = sqlite3SelectNew(0,yymsp[0].minor.yy373,0,0,0,0,0,0,0); } -#line 2382 "parse.c" +#line 2440 "parse.c" break; case 130: -#line 484 "parse.y" -{yygotominor.yy178.z=0; yygotominor.yy178.n=0;} -#line 2387 "parse.c" +#line 483 "parse.y" +{yygotominor.yy410.z=0; yygotominor.yy410.n=0;} +#line 2445 "parse.c" break; case 132: -#line 489 "parse.y" -{yygotominor.yy419 = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy178,&yymsp[0].minor.yy178);} -#line 2392 "parse.c" +#line 488 "parse.y" +{yygotominor.yy373 = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy410,&yymsp[0].minor.yy410);} +#line 2450 "parse.c" break; case 133: -#line 493 "parse.y" -{ yygotominor.yy316 = JT_INNER; } -#line 2397 "parse.c" +#line 492 "parse.y" +{ yygotominor.yy46 = JT_INNER; } +#line 2455 "parse.c" break; case 134: -#line 494 "parse.y" -{ yygotominor.yy316 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); } -#line 2402 "parse.c" +#line 493 "parse.y" +{ yygotominor.yy46 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); } +#line 2460 "parse.c" break; case 135: -#line 495 "parse.y" -{ yygotominor.yy316 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy178,0); } -#line 2407 "parse.c" +#line 494 "parse.y" +{ yygotominor.yy46 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy410,0); } +#line 2465 "parse.c" break; case 136: -#line 497 "parse.y" -{ yygotominor.yy316 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy178,&yymsp[-1].minor.yy178); } -#line 2412 "parse.c" +#line 496 "parse.y" +{ yygotominor.yy46 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy410,&yymsp[-1].minor.yy410); } +#line 2470 "parse.c" break; case 137: case 145: @@ -2417,9 +2475,9 @@ static void yy_reduce( case 225: case 227: case 231: -#line 501 "parse.y" -{yygotominor.yy450 = yymsp[0].minor.yy450;} -#line 2425 "parse.c" +#line 500 "parse.y" +{yygotominor.yy172 = yymsp[0].minor.yy172;} +#line 2483 "parse.c" break; case 138: case 151: @@ -2428,230 +2486,230 @@ static void yy_reduce( case 226: case 228: case 232: -#line 502 "parse.y" -{yygotominor.yy450 = 0;} -#line 2436 "parse.c" +#line 501 "parse.y" +{yygotominor.yy172 = 0;} +#line 2494 "parse.c" break; case 139: case 171: -#line 506 "parse.y" -{yygotominor.yy352 = yymsp[-1].minor.yy352;} -#line 2442 "parse.c" +#line 505 "parse.y" +{yygotominor.yy432 = yymsp[-1].minor.yy432;} +#line 2500 "parse.c" break; case 140: case 170: -#line 507 "parse.y" -{yygotominor.yy352 = 0;} -#line 2448 "parse.c" +#line 506 "parse.y" +{yygotominor.yy432 = 0;} +#line 2506 "parse.c" break; case 142: case 150: -#line 518 "parse.y" -{yygotominor.yy242 = yymsp[0].minor.yy242;} -#line 2454 "parse.c" +#line 517 "parse.y" +{yygotominor.yy174 = yymsp[0].minor.yy174;} +#line 2512 "parse.c" break; case 143: -#line 519 "parse.y" +#line 518 "parse.y" { - yygotominor.yy242 = sqlite3ExprListAppend(yymsp[-3].minor.yy242,yymsp[-1].minor.yy450,0); - if( yygotominor.yy242 ) yygotominor.yy242->a[yygotominor.yy242->nExpr-1].sortOrder = yymsp[0].minor.yy316; + yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-3].minor.yy174,yymsp[-1].minor.yy172,0); + if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46; } -#line 2462 "parse.c" +#line 2520 "parse.c" break; case 144: -#line 523 "parse.y" +#line 522 "parse.y" { - yygotominor.yy242 = sqlite3ExprListAppend(0,yymsp[-1].minor.yy450,0); - if( yygotominor.yy242 && yygotominor.yy242->a ) yygotominor.yy242->a[0].sortOrder = yymsp[0].minor.yy316; + yygotominor.yy174 = sqlite3ExprListAppend(0,yymsp[-1].minor.yy172,0); + if( yygotominor.yy174 && yygotominor.yy174->a ) yygotominor.yy174->a[0].sortOrder = yymsp[0].minor.yy46; } -#line 2470 "parse.c" +#line 2528 "parse.c" break; case 146: case 148: -#line 531 "parse.y" -{yygotominor.yy316 = SQLITE_SO_ASC;} -#line 2476 "parse.c" +#line 530 "parse.y" +{yygotominor.yy46 = SQLITE_SO_ASC;} +#line 2534 "parse.c" break; case 147: -#line 532 "parse.y" -{yygotominor.yy316 = SQLITE_SO_DESC;} -#line 2481 "parse.c" +#line 531 "parse.y" +{yygotominor.yy46 = SQLITE_SO_DESC;} +#line 2539 "parse.c" break; case 153: -#line 550 "parse.y" -{yygotominor.yy84.pLimit = 0; yygotominor.yy84.pOffset = 0;} -#line 2486 "parse.c" +#line 557 "parse.y" +{yygotominor.yy234.pLimit = 0; yygotominor.yy234.pOffset = 0;} +#line 2544 "parse.c" break; case 154: -#line 551 "parse.y" -{yygotominor.yy84.pLimit = yymsp[0].minor.yy450; yygotominor.yy84.pOffset = 0;} -#line 2491 "parse.c" +#line 558 "parse.y" +{yygotominor.yy234.pLimit = yymsp[0].minor.yy172; yygotominor.yy234.pOffset = 0;} +#line 2549 "parse.c" break; case 155: -#line 553 "parse.y" -{yygotominor.yy84.pLimit = yymsp[-2].minor.yy450; yygotominor.yy84.pOffset = yymsp[0].minor.yy450;} -#line 2496 "parse.c" +#line 560 "parse.y" +{yygotominor.yy234.pLimit = yymsp[-2].minor.yy172; yygotominor.yy234.pOffset = yymsp[0].minor.yy172;} +#line 2554 "parse.c" break; case 156: -#line 555 "parse.y" -{yygotominor.yy84.pOffset = yymsp[-2].minor.yy450; yygotominor.yy84.pLimit = yymsp[0].minor.yy450;} -#line 2501 "parse.c" +#line 562 "parse.y" +{yygotominor.yy234.pOffset = yymsp[-2].minor.yy172; yygotominor.yy234.pLimit = yymsp[0].minor.yy172;} +#line 2559 "parse.c" break; case 157: -#line 559 "parse.y" -{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy419,yymsp[0].minor.yy450);} -#line 2506 "parse.c" +#line 566 "parse.y" +{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy373,yymsp[0].minor.yy172);} +#line 2564 "parse.c" break; case 160: -#line 570 "parse.y" -{sqlite3Update(pParse,yymsp[-3].minor.yy419,yymsp[-1].minor.yy242,yymsp[0].minor.yy450,yymsp[-4].minor.yy316);} -#line 2511 "parse.c" +#line 577 "parse.y" +{sqlite3Update(pParse,yymsp[-3].minor.yy373,yymsp[-1].minor.yy174,yymsp[0].minor.yy172,yymsp[-4].minor.yy46);} +#line 2569 "parse.c" break; case 161: -#line 576 "parse.y" -{yygotominor.yy242 = sqlite3ExprListAppend(yymsp[-4].minor.yy242,yymsp[0].minor.yy450,&yymsp[-2].minor.yy178);} -#line 2516 "parse.c" +#line 583 "parse.y" +{yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-4].minor.yy174,yymsp[0].minor.yy172,&yymsp[-2].minor.yy410);} +#line 2574 "parse.c" break; case 162: -#line 577 "parse.y" -{yygotominor.yy242 = sqlite3ExprListAppend(0,yymsp[0].minor.yy450,&yymsp[-2].minor.yy178);} -#line 2521 "parse.c" +#line 584 "parse.y" +{yygotominor.yy174 = sqlite3ExprListAppend(0,yymsp[0].minor.yy172,&yymsp[-2].minor.yy410);} +#line 2579 "parse.c" break; case 163: -#line 583 "parse.y" -{sqlite3Insert(pParse, yymsp[-5].minor.yy419, yymsp[-1].minor.yy242, 0, yymsp[-4].minor.yy352, yymsp[-7].minor.yy316);} -#line 2526 "parse.c" +#line 590 "parse.y" +{sqlite3Insert(pParse, yymsp[-5].minor.yy373, yymsp[-1].minor.yy174, 0, yymsp[-4].minor.yy432, yymsp[-7].minor.yy46);} +#line 2584 "parse.c" break; case 164: -#line 585 "parse.y" -{sqlite3Insert(pParse, yymsp[-2].minor.yy419, 0, yymsp[0].minor.yy43, yymsp[-1].minor.yy352, yymsp[-4].minor.yy316);} -#line 2531 "parse.c" +#line 592 "parse.y" +{sqlite3Insert(pParse, yymsp[-2].minor.yy373, 0, yymsp[0].minor.yy219, yymsp[-1].minor.yy432, yymsp[-4].minor.yy46);} +#line 2589 "parse.c" break; case 165: -#line 587 "parse.y" -{sqlite3Insert(pParse, yymsp[-3].minor.yy419, 0, 0, yymsp[-2].minor.yy352, yymsp[-5].minor.yy316);} -#line 2536 "parse.c" +#line 594 "parse.y" +{sqlite3Insert(pParse, yymsp[-3].minor.yy373, 0, 0, yymsp[-2].minor.yy432, yymsp[-5].minor.yy46);} +#line 2594 "parse.c" break; case 168: case 229: -#line 597 "parse.y" -{yygotominor.yy242 = sqlite3ExprListAppend(yymsp[-2].minor.yy242,yymsp[0].minor.yy450,0);} -#line 2542 "parse.c" +#line 604 "parse.y" +{yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-2].minor.yy174,yymsp[0].minor.yy172,0);} +#line 2600 "parse.c" break; case 169: case 230: -#line 598 "parse.y" -{yygotominor.yy242 = sqlite3ExprListAppend(0,yymsp[0].minor.yy450,0);} -#line 2548 "parse.c" +#line 605 "parse.y" +{yygotominor.yy174 = sqlite3ExprListAppend(0,yymsp[0].minor.yy172,0);} +#line 2606 "parse.c" break; case 172: -#line 607 "parse.y" -{yygotominor.yy352 = sqlite3IdListAppend(yymsp[-2].minor.yy352,&yymsp[0].minor.yy178);} -#line 2553 "parse.c" +#line 614 "parse.y" +{yygotominor.yy432 = sqlite3IdListAppend(yymsp[-2].minor.yy432,&yymsp[0].minor.yy410);} +#line 2611 "parse.c" break; case 173: -#line 608 "parse.y" -{yygotominor.yy352 = sqlite3IdListAppend(0,&yymsp[0].minor.yy178);} -#line 2558 "parse.c" +#line 615 "parse.y" +{yygotominor.yy432 = sqlite3IdListAppend(0,&yymsp[0].minor.yy410);} +#line 2616 "parse.c" break; case 175: -#line 619 "parse.y" -{yygotominor.yy450 = yymsp[-1].minor.yy450; sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } -#line 2563 "parse.c" +#line 626 "parse.y" +{yygotominor.yy172 = yymsp[-1].minor.yy172; sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } +#line 2621 "parse.c" break; case 176: case 181: case 182: -#line 620 "parse.y" -{yygotominor.yy450 = sqlite3Expr(yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);} -#line 2570 "parse.c" +#line 627 "parse.y" +{yygotominor.yy172 = sqlite3Expr(yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);} +#line 2628 "parse.c" break; case 177: case 178: -#line 621 "parse.y" -{yygotominor.yy450 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy0);} -#line 2576 "parse.c" +#line 628 "parse.y" +{yygotominor.yy172 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy0);} +#line 2634 "parse.c" break; case 179: -#line 623 "parse.y" +#line 630 "parse.y" { - Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy178); - Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy178); - yygotominor.yy450 = sqlite3Expr(TK_DOT, temp1, temp2, 0); + Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy410); + Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy410); + yygotominor.yy172 = sqlite3Expr(TK_DOT, temp1, temp2, 0); } -#line 2585 "parse.c" +#line 2643 "parse.c" break; case 180: -#line 628 "parse.y" +#line 635 "parse.y" { - Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-4].minor.yy178); - Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy178); - Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy178); + Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-4].minor.yy410); + Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy410); + Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy410); Expr *temp4 = sqlite3Expr(TK_DOT, temp2, temp3, 0); - yygotominor.yy450 = sqlite3Expr(TK_DOT, temp1, temp4, 0); + yygotominor.yy172 = sqlite3Expr(TK_DOT, temp1, temp4, 0); } -#line 2596 "parse.c" +#line 2654 "parse.c" break; case 183: -#line 637 "parse.y" -{yygotominor.yy450 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);} -#line 2601 "parse.c" +#line 644 "parse.y" +{yygotominor.yy172 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);} +#line 2659 "parse.c" break; case 184: -#line 638 "parse.y" +#line 645 "parse.y" { Token *pToken = &yymsp[0].minor.yy0; - Expr *pExpr = yygotominor.yy450 = sqlite3Expr(TK_VARIABLE, 0, 0, pToken); + Expr *pExpr = yygotominor.yy172 = sqlite3Expr(TK_VARIABLE, 0, 0, pToken); sqlite3ExprAssignVarNumber(pParse, pExpr); } -#line 2610 "parse.c" +#line 2668 "parse.c" break; case 185: -#line 643 "parse.y" +#line 650 "parse.y" { - yygotominor.yy450 = sqlite3ExprSetColl(pParse, yymsp[-2].minor.yy450, &yymsp[0].minor.yy178); + yygotominor.yy172 = sqlite3ExprSetColl(pParse, yymsp[-2].minor.yy172, &yymsp[0].minor.yy410); } -#line 2617 "parse.c" +#line 2675 "parse.c" break; case 186: -#line 647 "parse.y" +#line 654 "parse.y" { - yygotominor.yy450 = sqlite3Expr(TK_CAST, yymsp[-3].minor.yy450, 0, &yymsp[-1].minor.yy178); - sqlite3ExprSpan(yygotominor.yy450,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); + yygotominor.yy172 = sqlite3Expr(TK_CAST, yymsp[-3].minor.yy172, 0, &yymsp[-1].minor.yy410); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); } -#line 2625 "parse.c" +#line 2683 "parse.c" break; case 187: -#line 652 "parse.y" +#line 659 "parse.y" { - yygotominor.yy450 = sqlite3ExprFunction(yymsp[-1].minor.yy242, &yymsp[-4].minor.yy0); - sqlite3ExprSpan(yygotominor.yy450,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); - if( yymsp[-2].minor.yy316 && yygotominor.yy450 ){ - yygotominor.yy450->flags |= EP_Distinct; + yygotominor.yy172 = sqlite3ExprFunction(yymsp[-1].minor.yy174, &yymsp[-4].minor.yy0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); + if( yymsp[-2].minor.yy46 && yygotominor.yy172 ){ + yygotominor.yy172->flags |= EP_Distinct; } } -#line 2636 "parse.c" +#line 2694 "parse.c" break; case 188: -#line 659 "parse.y" +#line 666 "parse.y" { - yygotominor.yy450 = sqlite3ExprFunction(0, &yymsp[-3].minor.yy0); - sqlite3ExprSpan(yygotominor.yy450,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); + yygotominor.yy172 = sqlite3ExprFunction(0, &yymsp[-3].minor.yy0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); } -#line 2644 "parse.c" +#line 2702 "parse.c" break; case 189: -#line 663 "parse.y" +#line 670 "parse.y" { /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are ** treated as functions that return constants */ - yygotominor.yy450 = sqlite3ExprFunction(0,&yymsp[0].minor.yy0); - if( yygotominor.yy450 ){ - yygotominor.yy450->op = TK_CONST_FUNC; - yygotominor.yy450->span = yymsp[0].minor.yy0; + yygotominor.yy172 = sqlite3ExprFunction(0,&yymsp[0].minor.yy0); + if( yygotominor.yy172 ){ + yygotominor.yy172->op = TK_CONST_FUNC; + yygotominor.yy172->span = yymsp[0].minor.yy0; } } -#line 2657 "parse.c" +#line 2715 "parse.c" break; case 190: case 191: @@ -2661,538 +2719,527 @@ static void yy_reduce( case 195: case 196: case 197: -#line 672 "parse.y" -{yygotominor.yy450 = sqlite3Expr(yymsp[-1].major, yymsp[-2].minor.yy450, yymsp[0].minor.yy450, 0);} -#line 2669 "parse.c" +#line 679 "parse.y" +{yygotominor.yy172 = sqlite3Expr(yymsp[-1].major, yymsp[-2].minor.yy172, yymsp[0].minor.yy172, 0);} +#line 2727 "parse.c" break; case 198: case 200: -#line 682 "parse.y" -{yygotominor.yy86.eOperator = yymsp[0].minor.yy0; yygotominor.yy86.not = 0;} -#line 2675 "parse.c" +#line 689 "parse.y" +{yygotominor.yy72.eOperator = yymsp[0].minor.yy0; yygotominor.yy72.not = 0;} +#line 2733 "parse.c" break; case 199: case 201: -#line 683 "parse.y" -{yygotominor.yy86.eOperator = yymsp[0].minor.yy0; yygotominor.yy86.not = 1;} -#line 2681 "parse.c" +#line 690 "parse.y" +{yygotominor.yy72.eOperator = yymsp[0].minor.yy0; yygotominor.yy72.not = 1;} +#line 2739 "parse.c" break; case 204: -#line 690 "parse.y" +#line 697 "parse.y" { ExprList *pList; - pList = sqlite3ExprListAppend(0, yymsp[-1].minor.yy450, 0); - pList = sqlite3ExprListAppend(pList, yymsp[-3].minor.yy450, 0); - if( yymsp[0].minor.yy450 ){ - pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy450, 0); + pList = sqlite3ExprListAppend(0, yymsp[-1].minor.yy172, 0); + pList = sqlite3ExprListAppend(pList, yymsp[-3].minor.yy172, 0); + if( yymsp[0].minor.yy172 ){ + pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy172, 0); } - yygotominor.yy450 = sqlite3ExprFunction(pList, &yymsp[-2].minor.yy86.eOperator); - if( yymsp[-2].minor.yy86.not ) yygotominor.yy450 = sqlite3Expr(TK_NOT, yygotominor.yy450, 0, 0); - sqlite3ExprSpan(yygotominor.yy450, &yymsp[-3].minor.yy450->span, &yymsp[-1].minor.yy450->span); - if( yygotominor.yy450 ) yygotominor.yy450->flags |= EP_InfixFunc; + yygotominor.yy172 = sqlite3ExprFunction(pList, &yymsp[-2].minor.yy72.eOperator); + if( yymsp[-2].minor.yy72.not ) yygotominor.yy172 = sqlite3Expr(TK_NOT, yygotominor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172, &yymsp[-3].minor.yy172->span, &yymsp[-1].minor.yy172->span); + if( yygotominor.yy172 ) yygotominor.yy172->flags |= EP_InfixFunc; } -#line 2697 "parse.c" +#line 2755 "parse.c" break; case 205: -#line 703 "parse.y" +#line 710 "parse.y" { - yygotominor.yy450 = sqlite3Expr(yymsp[0].major, yymsp[-1].minor.yy450, 0, 0); - sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy450->span,&yymsp[0].minor.yy0); + yygotominor.yy172 = sqlite3Expr(yymsp[0].major, yymsp[-1].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy172->span,&yymsp[0].minor.yy0); } -#line 2705 "parse.c" +#line 2763 "parse.c" break; case 206: -#line 707 "parse.y" +#line 714 "parse.y" { - yygotominor.yy450 = sqlite3Expr(TK_ISNULL, yymsp[-2].minor.yy450, 0, 0); - sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy450->span,&yymsp[0].minor.yy0); + yygotominor.yy172 = sqlite3Expr(TK_ISNULL, yymsp[-2].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy172->span,&yymsp[0].minor.yy0); } -#line 2713 "parse.c" +#line 2771 "parse.c" break; case 207: -#line 711 "parse.y" +#line 718 "parse.y" { - yygotominor.yy450 = sqlite3Expr(TK_NOTNULL, yymsp[-2].minor.yy450, 0, 0); - sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy450->span,&yymsp[0].minor.yy0); + yygotominor.yy172 = sqlite3Expr(TK_NOTNULL, yymsp[-2].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy172->span,&yymsp[0].minor.yy0); } -#line 2721 "parse.c" +#line 2779 "parse.c" break; case 208: -#line 715 "parse.y" +#line 722 "parse.y" { - yygotominor.yy450 = sqlite3Expr(TK_NOTNULL, yymsp[-3].minor.yy450, 0, 0); - sqlite3ExprSpan(yygotominor.yy450,&yymsp[-3].minor.yy450->span,&yymsp[0].minor.yy0); + yygotominor.yy172 = sqlite3Expr(TK_NOTNULL, yymsp[-3].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy172->span,&yymsp[0].minor.yy0); } -#line 2729 "parse.c" +#line 2787 "parse.c" break; case 209: -#line 719 "parse.y" +#line 726 "parse.y" { - yygotominor.yy450 = sqlite3Expr(yymsp[-1].major, yymsp[0].minor.yy450, 0, 0); - sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy450->span); + yygotominor.yy172 = sqlite3Expr(yymsp[-1].major, yymsp[0].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span); } -#line 2737 "parse.c" +#line 2795 "parse.c" break; case 210: -#line 723 "parse.y" +#line 730 "parse.y" { - yygotominor.yy450 = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy450, 0, 0); - sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy450->span); + yygotominor.yy172 = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span); } -#line 2745 "parse.c" +#line 2803 "parse.c" break; case 211: -#line 727 "parse.y" +#line 734 "parse.y" { - yygotominor.yy450 = sqlite3Expr(TK_UPLUS, yymsp[0].minor.yy450, 0, 0); - sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy450->span); + yygotominor.yy172 = sqlite3Expr(TK_UPLUS, yymsp[0].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span); } -#line 2753 "parse.c" +#line 2811 "parse.c" break; case 214: -#line 734 "parse.y" +#line 741 "parse.y" { - ExprList *pList = sqlite3ExprListAppend(0, yymsp[-2].minor.yy450, 0); - pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy450, 0); - yygotominor.yy450 = sqlite3Expr(TK_BETWEEN, yymsp[-4].minor.yy450, 0, 0); - if( yygotominor.yy450 ){ - yygotominor.yy450->pList = pList; + ExprList *pList = sqlite3ExprListAppend(0, yymsp[-2].minor.yy172, 0); + pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy172, 0); + yygotominor.yy172 = sqlite3Expr(TK_BETWEEN, yymsp[-4].minor.yy172, 0, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->pList = pList; }else{ sqlite3ExprListDelete(pList); } - if( yymsp[-3].minor.yy316 ) yygotominor.yy450 = sqlite3Expr(TK_NOT, yygotominor.yy450, 0, 0); - sqlite3ExprSpan(yygotominor.yy450,&yymsp[-4].minor.yy450->span,&yymsp[0].minor.yy450->span); + if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3Expr(TK_NOT, yygotominor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy172->span); } -#line 2769 "parse.c" +#line 2827 "parse.c" break; case 217: -#line 750 "parse.y" +#line 757 "parse.y" { - yygotominor.yy450 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy450, 0, 0); - if( yygotominor.yy450 ){ - yygotominor.yy450->pList = yymsp[-1].minor.yy242; + yygotominor.yy172 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy172, 0, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->pList = yymsp[-1].minor.yy174; }else{ - sqlite3ExprListDelete(yymsp[-1].minor.yy242); + sqlite3ExprListDelete(yymsp[-1].minor.yy174); } - if( yymsp[-3].minor.yy316 ) yygotominor.yy450 = sqlite3Expr(TK_NOT, yygotominor.yy450, 0, 0); - sqlite3ExprSpan(yygotominor.yy450,&yymsp[-4].minor.yy450->span,&yymsp[0].minor.yy0); + if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3Expr(TK_NOT, yygotominor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy0); } -#line 2783 "parse.c" +#line 2841 "parse.c" break; case 218: -#line 760 "parse.y" +#line 767 "parse.y" { - yygotominor.yy450 = sqlite3Expr(TK_SELECT, 0, 0, 0); - if( yygotominor.yy450 ){ - yygotominor.yy450->pSelect = yymsp[-1].minor.yy43; + yygotominor.yy172 = sqlite3Expr(TK_SELECT, 0, 0, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->pSelect = yymsp[-1].minor.yy219; }else{ - sqlite3SelectDelete(yymsp[-1].minor.yy43); + sqlite3SelectDelete(yymsp[-1].minor.yy219); } - sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } -#line 2796 "parse.c" +#line 2854 "parse.c" break; case 219: -#line 769 "parse.y" +#line 776 "parse.y" { - yygotominor.yy450 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy450, 0, 0); - if( yygotominor.yy450 ){ - yygotominor.yy450->pSelect = yymsp[-1].minor.yy43; + yygotominor.yy172 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy172, 0, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->pSelect = yymsp[-1].minor.yy219; }else{ - sqlite3SelectDelete(yymsp[-1].minor.yy43); + sqlite3SelectDelete(yymsp[-1].minor.yy219); } - if( yymsp[-3].minor.yy316 ) yygotominor.yy450 = sqlite3Expr(TK_NOT, yygotominor.yy450, 0, 0); - sqlite3ExprSpan(yygotominor.yy450,&yymsp[-4].minor.yy450->span,&yymsp[0].minor.yy0); + if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3Expr(TK_NOT, yygotominor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy0); } -#line 2810 "parse.c" +#line 2868 "parse.c" break; case 220: -#line 779 "parse.y" +#line 786 "parse.y" { - SrcList *pSrc = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy178,&yymsp[0].minor.yy178); - yygotominor.yy450 = sqlite3Expr(TK_IN, yymsp[-3].minor.yy450, 0, 0); - if( yygotominor.yy450 ){ - yygotominor.yy450->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,0,0); + SrcList *pSrc = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy410,&yymsp[0].minor.yy410); + yygotominor.yy172 = sqlite3Expr(TK_IN, yymsp[-3].minor.yy172, 0, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,0,0); }else{ sqlite3SrcListDelete(pSrc); } - if( yymsp[-2].minor.yy316 ) yygotominor.yy450 = sqlite3Expr(TK_NOT, yygotominor.yy450, 0, 0); - sqlite3ExprSpan(yygotominor.yy450,&yymsp[-3].minor.yy450->span,yymsp[0].minor.yy178.z?&yymsp[0].minor.yy178:&yymsp[-1].minor.yy178); + if( yymsp[-2].minor.yy46 ) yygotominor.yy172 = sqlite3Expr(TK_NOT, yygotominor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy172->span,yymsp[0].minor.yy410.z?&yymsp[0].minor.yy410:&yymsp[-1].minor.yy410); } -#line 2825 "parse.c" +#line 2883 "parse.c" break; case 221: -#line 790 "parse.y" +#line 797 "parse.y" { - Expr *p = yygotominor.yy450 = sqlite3Expr(TK_EXISTS, 0, 0, 0); + Expr *p = yygotominor.yy172 = sqlite3Expr(TK_EXISTS, 0, 0, 0); if( p ){ - p->pSelect = yymsp[-1].minor.yy43; + p->pSelect = yymsp[-1].minor.yy219; sqlite3ExprSpan(p,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); }else{ - sqlite3SelectDelete(yymsp[-1].minor.yy43); + sqlite3SelectDelete(yymsp[-1].minor.yy219); } } -#line 2838 "parse.c" +#line 2896 "parse.c" break; case 222: -#line 802 "parse.y" +#line 809 "parse.y" { - yygotominor.yy450 = sqlite3Expr(TK_CASE, yymsp[-3].minor.yy450, yymsp[-1].minor.yy450, 0); - if( yygotominor.yy450 ){ - yygotominor.yy450->pList = yymsp[-2].minor.yy242; + yygotominor.yy172 = sqlite3Expr(TK_CASE, yymsp[-3].minor.yy172, yymsp[-1].minor.yy172, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->pList = yymsp[-2].minor.yy174; }else{ - sqlite3ExprListDelete(yymsp[-2].minor.yy242); + sqlite3ExprListDelete(yymsp[-2].minor.yy174); } - sqlite3ExprSpan(yygotominor.yy450, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0); + sqlite3ExprSpan(yygotominor.yy172, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0); } -#line 2851 "parse.c" +#line 2909 "parse.c" break; case 223: -#line 813 "parse.y" +#line 820 "parse.y" { - yygotominor.yy242 = sqlite3ExprListAppend(yymsp[-4].minor.yy242, yymsp[-2].minor.yy450, 0); - yygotominor.yy242 = sqlite3ExprListAppend(yygotominor.yy242, yymsp[0].minor.yy450, 0); + yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-4].minor.yy174, yymsp[-2].minor.yy172, 0); + yygotominor.yy174 = sqlite3ExprListAppend(yygotominor.yy174, yymsp[0].minor.yy172, 0); } -#line 2859 "parse.c" +#line 2917 "parse.c" break; case 224: -#line 817 "parse.y" +#line 824 "parse.y" { - yygotominor.yy242 = sqlite3ExprListAppend(0, yymsp[-2].minor.yy450, 0); - yygotominor.yy242 = sqlite3ExprListAppend(yygotominor.yy242, yymsp[0].minor.yy450, 0); + yygotominor.yy174 = sqlite3ExprListAppend(0, yymsp[-2].minor.yy172, 0); + yygotominor.yy174 = sqlite3ExprListAppend(yygotominor.yy174, yymsp[0].minor.yy172, 0); } -#line 2867 "parse.c" +#line 2925 "parse.c" break; case 233: -#line 844 "parse.y" +#line 851 "parse.y" { - sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy178, &yymsp[-5].minor.yy178, sqlite3SrcListAppend(0,&yymsp[-3].minor.yy178,0), yymsp[-1].minor.yy242, yymsp[-9].minor.yy316, - &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy316); + sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy410, &yymsp[-5].minor.yy410, sqlite3SrcListAppend(0,&yymsp[-3].minor.yy410,0), yymsp[-1].minor.yy174, yymsp[-9].minor.yy46, + &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy46); } -#line 2875 "parse.c" +#line 2933 "parse.c" break; case 234: - case 282: -#line 850 "parse.y" -{yygotominor.yy316 = OE_Abort;} -#line 2881 "parse.c" + case 281: +#line 857 "parse.y" +{yygotominor.yy46 = OE_Abort;} +#line 2939 "parse.c" break; case 235: -#line 851 "parse.y" -{yygotominor.yy316 = OE_None;} -#line 2886 "parse.c" +#line 858 "parse.y" +{yygotominor.yy46 = OE_None;} +#line 2944 "parse.c" break; case 238: -#line 861 "parse.y" +#line 868 "parse.y" { Expr *p = 0; - if( yymsp[-1].minor.yy178.n>0 ){ + if( yymsp[-1].minor.yy410.n>0 ){ p = sqlite3Expr(TK_COLUMN, 0, 0, 0); - if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)yymsp[-1].minor.yy178.z, yymsp[-1].minor.yy178.n); + if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)yymsp[-1].minor.yy410.z, yymsp[-1].minor.yy410.n); } - yygotominor.yy242 = sqlite3ExprListAppend(yymsp[-4].minor.yy242, p, &yymsp[-2].minor.yy178); - if( yygotominor.yy242 ) yygotominor.yy242->a[yygotominor.yy242->nExpr-1].sortOrder = yymsp[0].minor.yy316; + yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-4].minor.yy174, p, &yymsp[-2].minor.yy410); + if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46; } -#line 2899 "parse.c" +#line 2957 "parse.c" break; case 239: -#line 870 "parse.y" +#line 877 "parse.y" { Expr *p = 0; - if( yymsp[-1].minor.yy178.n>0 ){ + if( yymsp[-1].minor.yy410.n>0 ){ p = sqlite3Expr(TK_COLUMN, 0, 0, 0); - if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)yymsp[-1].minor.yy178.z, yymsp[-1].minor.yy178.n); + if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)yymsp[-1].minor.yy410.z, yymsp[-1].minor.yy410.n); } - yygotominor.yy242 = sqlite3ExprListAppend(0, p, &yymsp[-2].minor.yy178); - if( yygotominor.yy242 ) yygotominor.yy242->a[yygotominor.yy242->nExpr-1].sortOrder = yymsp[0].minor.yy316; + yygotominor.yy174 = sqlite3ExprListAppend(0, p, &yymsp[-2].minor.yy410); + if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46; } -#line 2912 "parse.c" +#line 2970 "parse.c" break; case 241: -#line 882 "parse.y" -{yygotominor.yy178.z = 0; yygotominor.yy178.n = 0;} -#line 2917 "parse.c" +#line 889 "parse.y" +{yygotominor.yy410.z = 0; yygotominor.yy410.n = 0;} +#line 2975 "parse.c" break; case 243: -#line 888 "parse.y" -{sqlite3DropIndex(pParse, yymsp[0].minor.yy419, yymsp[-1].minor.yy316);} -#line 2922 "parse.c" +#line 895 "parse.y" +{sqlite3DropIndex(pParse, yymsp[0].minor.yy373, yymsp[-1].minor.yy46);} +#line 2980 "parse.c" break; case 244: case 245: -#line 893 "parse.y" +#line 901 "parse.y" {sqlite3Vacuum(pParse);} -#line 2928 "parse.c" +#line 2986 "parse.c" break; case 246: -#line 900 "parse.y" -{sqlite3Pragma(pParse,&yymsp[-3].minor.yy178,&yymsp[-2].minor.yy178,&yymsp[0].minor.yy178,0);} -#line 2933 "parse.c" +#line 909 "parse.y" +{sqlite3Pragma(pParse,&yymsp[-3].minor.yy410,&yymsp[-2].minor.yy410,&yymsp[0].minor.yy410,0);} +#line 2991 "parse.c" break; case 247: -#line 901 "parse.y" -{sqlite3Pragma(pParse,&yymsp[-3].minor.yy178,&yymsp[-2].minor.yy178,&yymsp[0].minor.yy0,0);} -#line 2938 "parse.c" +#line 910 "parse.y" +{sqlite3Pragma(pParse,&yymsp[-3].minor.yy410,&yymsp[-2].minor.yy410,&yymsp[0].minor.yy0,0);} +#line 2996 "parse.c" break; case 248: -#line 902 "parse.y" +#line 911 "parse.y" { - sqlite3Pragma(pParse,&yymsp[-3].minor.yy178,&yymsp[-2].minor.yy178,&yymsp[0].minor.yy178,1); + sqlite3Pragma(pParse,&yymsp[-3].minor.yy410,&yymsp[-2].minor.yy410,&yymsp[0].minor.yy410,1); } -#line 2945 "parse.c" +#line 3003 "parse.c" break; case 249: -#line 905 "parse.y" -{sqlite3Pragma(pParse,&yymsp[-4].minor.yy178,&yymsp[-3].minor.yy178,&yymsp[-1].minor.yy178,0);} -#line 2950 "parse.c" +#line 914 "parse.y" +{sqlite3Pragma(pParse,&yymsp[-4].minor.yy410,&yymsp[-3].minor.yy410,&yymsp[-1].minor.yy410,0);} +#line 3008 "parse.c" break; case 250: -#line 906 "parse.y" -{sqlite3Pragma(pParse,&yymsp[-1].minor.yy178,&yymsp[0].minor.yy178,0,0);} -#line 2955 "parse.c" +#line 915 "parse.y" +{sqlite3Pragma(pParse,&yymsp[-1].minor.yy410,&yymsp[0].minor.yy410,0,0);} +#line 3013 "parse.c" break; case 258: -#line 920 "parse.y" +#line 929 "parse.y" { Token all; - all.z = yymsp[-3].minor.yy178.z; - all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy178.z) + yymsp[0].minor.yy0.n; - sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy75, &all); + all.z = yymsp[-3].minor.yy410.z; + all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy410.z) + yymsp[0].minor.yy0.n; + sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy243, &all); } -#line 2965 "parse.c" +#line 3023 "parse.c" break; case 259: -#line 929 "parse.y" +#line 938 "parse.y" { - sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy178, &yymsp[-6].minor.yy178, yymsp[-5].minor.yy316, yymsp[-4].minor.yy354.a, yymsp[-4].minor.yy354.b, yymsp[-2].minor.yy419, yymsp[-1].minor.yy316, yymsp[0].minor.yy450, yymsp[-10].minor.yy316, yymsp[-8].minor.yy316); - yygotominor.yy178 = (yymsp[-6].minor.yy178.n==0?yymsp[-7].minor.yy178:yymsp[-6].minor.yy178); + sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy410, &yymsp[-6].minor.yy410, yymsp[-5].minor.yy46, yymsp[-4].minor.yy370.a, yymsp[-4].minor.yy370.b, yymsp[-2].minor.yy373, yymsp[0].minor.yy172, yymsp[-10].minor.yy46, yymsp[-8].minor.yy46); + yygotominor.yy410 = (yymsp[-6].minor.yy410.n==0?yymsp[-7].minor.yy410:yymsp[-6].minor.yy410); } -#line 2973 "parse.c" +#line 3031 "parse.c" break; case 260: case 263: -#line 935 "parse.y" -{ yygotominor.yy316 = TK_BEFORE; } -#line 2979 "parse.c" +#line 944 "parse.y" +{ yygotominor.yy46 = TK_BEFORE; } +#line 3037 "parse.c" break; case 261: -#line 936 "parse.y" -{ yygotominor.yy316 = TK_AFTER; } -#line 2984 "parse.c" +#line 945 "parse.y" +{ yygotominor.yy46 = TK_AFTER; } +#line 3042 "parse.c" break; case 262: -#line 937 "parse.y" -{ yygotominor.yy316 = TK_INSTEAD;} -#line 2989 "parse.c" +#line 946 "parse.y" +{ yygotominor.yy46 = TK_INSTEAD;} +#line 3047 "parse.c" break; case 264: case 265: -#line 942 "parse.y" -{yygotominor.yy354.a = yymsp[0].major; yygotominor.yy354.b = 0;} -#line 2995 "parse.c" +#line 951 "parse.y" +{yygotominor.yy370.a = yymsp[0].major; yygotominor.yy370.b = 0;} +#line 3053 "parse.c" break; case 266: -#line 944 "parse.y" -{yygotominor.yy354.a = TK_UPDATE; yygotominor.yy354.b = yymsp[0].minor.yy352;} -#line 3000 "parse.c" +#line 953 "parse.y" +{yygotominor.yy370.a = TK_UPDATE; yygotominor.yy370.b = yymsp[0].minor.yy432;} +#line 3058 "parse.c" break; - case 267: - case 268: -#line 947 "parse.y" -{ yygotominor.yy316 = TK_ROW; } -#line 3006 "parse.c" - break; case 269: -#line 949 "parse.y" -{ yygotominor.yy316 = TK_STATEMENT; } -#line 3011 "parse.c" +#line 960 "parse.y" +{ yygotominor.yy172 = 0; } +#line 3063 "parse.c" break; case 270: -#line 953 "parse.y" -{ yygotominor.yy450 = 0; } -#line 3016 "parse.c" +#line 961 "parse.y" +{ yygotominor.yy172 = yymsp[0].minor.yy172; } +#line 3068 "parse.c" break; case 271: -#line 954 "parse.y" -{ yygotominor.yy450 = yymsp[0].minor.yy450; } -#line 3021 "parse.c" - break; - case 272: -#line 958 "parse.y" +#line 965 "parse.y" { - if( yymsp[-2].minor.yy75 ){ - yymsp[-2].minor.yy75->pLast->pNext = yymsp[-1].minor.yy75; + if( yymsp[-2].minor.yy243 ){ + yymsp[-2].minor.yy243->pLast->pNext = yymsp[-1].minor.yy243; }else{ - yymsp[-2].minor.yy75 = yymsp[-1].minor.yy75; + yymsp[-2].minor.yy243 = yymsp[-1].minor.yy243; } - yymsp[-2].minor.yy75->pLast = yymsp[-1].minor.yy75; - yygotominor.yy75 = yymsp[-2].minor.yy75; + yymsp[-2].minor.yy243->pLast = yymsp[-1].minor.yy243; + yygotominor.yy243 = yymsp[-2].minor.yy243; } -#line 3034 "parse.c" +#line 3081 "parse.c" break; + case 272: +#line 974 "parse.y" +{ yygotominor.yy243 = 0; } +#line 3086 "parse.c" + break; case 273: -#line 967 "parse.y" -{ yygotominor.yy75 = 0; } -#line 3039 "parse.c" +#line 980 "parse.y" +{ yygotominor.yy243 = sqlite3TriggerUpdateStep(&yymsp[-3].minor.yy410, yymsp[-1].minor.yy174, yymsp[0].minor.yy172, yymsp[-4].minor.yy46); } +#line 3091 "parse.c" break; case 274: -#line 973 "parse.y" -{ yygotominor.yy75 = sqlite3TriggerUpdateStep(&yymsp[-3].minor.yy178, yymsp[-1].minor.yy242, yymsp[0].minor.yy450, yymsp[-4].minor.yy316); } -#line 3044 "parse.c" +#line 985 "parse.y" +{yygotominor.yy243 = sqlite3TriggerInsertStep(&yymsp[-5].minor.yy410, yymsp[-4].minor.yy432, yymsp[-1].minor.yy174, 0, yymsp[-7].minor.yy46);} +#line 3096 "parse.c" break; case 275: -#line 978 "parse.y" -{yygotominor.yy75 = sqlite3TriggerInsertStep(&yymsp[-5].minor.yy178, yymsp[-4].minor.yy352, yymsp[-1].minor.yy242, 0, yymsp[-7].minor.yy316);} -#line 3049 "parse.c" +#line 988 "parse.y" +{yygotominor.yy243 = sqlite3TriggerInsertStep(&yymsp[-2].minor.yy410, yymsp[-1].minor.yy432, 0, yymsp[0].minor.yy219, yymsp[-4].minor.yy46);} +#line 3101 "parse.c" break; case 276: -#line 981 "parse.y" -{yygotominor.yy75 = sqlite3TriggerInsertStep(&yymsp[-2].minor.yy178, yymsp[-1].minor.yy352, 0, yymsp[0].minor.yy43, yymsp[-4].minor.yy316);} -#line 3054 "parse.c" +#line 992 "parse.y" +{yygotominor.yy243 = sqlite3TriggerDeleteStep(&yymsp[-1].minor.yy410, yymsp[0].minor.yy172);} +#line 3106 "parse.c" break; case 277: -#line 985 "parse.y" -{yygotominor.yy75 = sqlite3TriggerDeleteStep(&yymsp[-1].minor.yy178, yymsp[0].minor.yy450);} -#line 3059 "parse.c" +#line 995 "parse.y" +{yygotominor.yy243 = sqlite3TriggerSelectStep(yymsp[0].minor.yy219); } +#line 3111 "parse.c" break; case 278: -#line 988 "parse.y" -{yygotominor.yy75 = sqlite3TriggerSelectStep(yymsp[0].minor.yy43); } -#line 3064 "parse.c" - break; - case 279: -#line 991 "parse.y" +#line 998 "parse.y" { - yygotominor.yy450 = sqlite3Expr(TK_RAISE, 0, 0, 0); - if( yygotominor.yy450 ){ - yygotominor.yy450->iColumn = OE_Ignore; - sqlite3ExprSpan(yygotominor.yy450, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0); + yygotominor.yy172 = sqlite3Expr(TK_RAISE, 0, 0, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->iColumn = OE_Ignore; + sqlite3ExprSpan(yygotominor.yy172, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0); } } -#line 3075 "parse.c" +#line 3122 "parse.c" break; - case 280: -#line 998 "parse.y" + case 279: +#line 1005 "parse.y" { - yygotominor.yy450 = sqlite3Expr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy178); - if( yygotominor.yy450 ) { - yygotominor.yy450->iColumn = yymsp[-3].minor.yy316; - sqlite3ExprSpan(yygotominor.yy450, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0); + yygotominor.yy172 = sqlite3Expr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy410); + if( yygotominor.yy172 ) { + yygotominor.yy172->iColumn = yymsp[-3].minor.yy46; + sqlite3ExprSpan(yygotominor.yy172, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0); } } -#line 3086 "parse.c" +#line 3133 "parse.c" break; - case 281: -#line 1008 "parse.y" -{yygotominor.yy316 = OE_Rollback;} -#line 3091 "parse.c" + case 280: +#line 1015 "parse.y" +{yygotominor.yy46 = OE_Rollback;} +#line 3138 "parse.c" break; + case 282: +#line 1017 "parse.y" +{yygotominor.yy46 = OE_Fail;} +#line 3143 "parse.c" + break; case 283: -#line 1010 "parse.y" -{yygotominor.yy316 = OE_Fail;} -#line 3096 "parse.c" +#line 1022 "parse.y" +{ + sqlite3DropTrigger(pParse,yymsp[0].minor.yy373,yymsp[-1].minor.yy46); +} +#line 3150 "parse.c" break; case 284: -#line 1015 "parse.y" +#line 1029 "parse.y" { - sqlite3DropTrigger(pParse,yymsp[0].minor.yy419,yymsp[-1].minor.yy316); + sqlite3Attach(pParse, yymsp[-3].minor.yy172, yymsp[-1].minor.yy172, yymsp[0].minor.yy386); } -#line 3103 "parse.c" +#line 3157 "parse.c" break; case 285: -#line 1021 "parse.y" +#line 1032 "parse.y" { - sqlite3Attach(pParse, yymsp[-3].minor.yy450, yymsp[-1].minor.yy450, yymsp[0].minor.yy158); + sqlite3Detach(pParse, yymsp[0].minor.yy172); } -#line 3110 "parse.c" +#line 3164 "parse.c" break; case 286: -#line 1026 "parse.y" -{ yygotominor.yy158 = 0; } -#line 3115 "parse.c" +#line 1038 "parse.y" +{ yygotominor.yy386 = 0; } +#line 3169 "parse.c" break; case 287: -#line 1027 "parse.y" -{ yygotominor.yy158 = yymsp[0].minor.yy450; } -#line 3120 "parse.c" +#line 1039 "parse.y" +{ yygotominor.yy386 = yymsp[0].minor.yy172; } +#line 3174 "parse.c" break; case 290: -#line 1033 "parse.y" -{ - sqlite3Detach(pParse, yymsp[0].minor.yy450); -} -#line 3127 "parse.c" +#line 1047 "parse.y" +{sqlite3Reindex(pParse, 0, 0);} +#line 3179 "parse.c" break; case 291: -#line 1039 "parse.y" -{sqlite3Reindex(pParse, 0, 0);} -#line 3132 "parse.c" +#line 1048 "parse.y" +{sqlite3Reindex(pParse, &yymsp[-1].minor.yy410, &yymsp[0].minor.yy410);} +#line 3184 "parse.c" break; case 292: -#line 1040 "parse.y" -{sqlite3Reindex(pParse, &yymsp[-1].minor.yy178, &yymsp[0].minor.yy178);} -#line 3137 "parse.c" +#line 1053 "parse.y" +{sqlite3Analyze(pParse, 0, 0);} +#line 3189 "parse.c" break; case 293: -#line 1045 "parse.y" -{sqlite3Analyze(pParse, 0, 0);} -#line 3142 "parse.c" +#line 1054 "parse.y" +{sqlite3Analyze(pParse, &yymsp[-1].minor.yy410, &yymsp[0].minor.yy410);} +#line 3194 "parse.c" break; case 294: -#line 1046 "parse.y" -{sqlite3Analyze(pParse, &yymsp[-1].minor.yy178, &yymsp[0].minor.yy178);} -#line 3147 "parse.c" +#line 1059 "parse.y" +{ + sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy373,&yymsp[0].minor.yy410); +} +#line 3201 "parse.c" break; case 295: -#line 1051 "parse.y" +#line 1062 "parse.y" { - sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy419,&yymsp[0].minor.yy178); + sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy410); } -#line 3154 "parse.c" +#line 3208 "parse.c" break; case 296: -#line 1054 "parse.y" +#line 1065 "parse.y" { - sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy178); + sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy373); } -#line 3161 "parse.c" +#line 3215 "parse.c" break; - case 297: -#line 1057 "parse.y" -{ - sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy419); -} -#line 3168 "parse.c" + case 299: +#line 1074 "parse.y" +{sqlite3VtabFinishParse(pParse,0);} +#line 3220 "parse.c" break; case 300: -#line 1066 "parse.y" -{sqlite3VtabFinishParse(pParse,0);} -#line 3173 "parse.c" +#line 1075 "parse.y" +{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} +#line 3225 "parse.c" break; case 301: -#line 1067 "parse.y" -{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} -#line 3178 "parse.c" - break; - case 302: -#line 1068 "parse.y" +#line 1076 "parse.y" { - sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy178, &yymsp[-2].minor.yy178, &yymsp[0].minor.yy178); + sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy410, &yymsp[-2].minor.yy410, &yymsp[0].minor.yy410); } -#line 3185 "parse.c" +#line 3232 "parse.c" break; - case 305: -#line 1073 "parse.y" + case 304: +#line 1081 "parse.y" {sqlite3VtabArgInit(pParse);} -#line 3190 "parse.c" +#line 3237 "parse.c" break; + case 306: case 307: case 308: - case 309: - case 311: -#line 1075 "parse.y" + case 310: +#line 1083 "parse.y" {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} -#line 3198 "parse.c" +#line 3245 "parse.c" break; }; yygoto = yyRuleInfo[yyruleno].lhs; @@ -3259,7 +3306,7 @@ static void yy_syntax_error( } pParse->parseError = 1; } -#line 3266 "parse.c" +#line 3313 "parse.c" sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ } @@ -3315,7 +3362,13 @@ void sqlite3Parser( /* (re)initialize the parser, if necessary */ yypParser = (yyParser*)yyp; if( yypParser->yyidx<0 ){ - /* if( yymajor==0 ) return; // not sure why this was here... */ +#if YYSTACKDEPTH<=0 + if( yypParser->yystksz <=0 ){ + memset(&yyminorunion, 0, sizeof(yyminorunion)); + yyStackOverflow(yypParser, &yyminorunion); + return; + } +#endif yypParser->yyidx = 0; yypParser->yyerrcnt = -1; yypParser->yystack[0].stateno = 0; ============================================================ --- sqlite/parse.h 6f6a83f5cf2575172e44744ed9ffeacbbe812531 +++ sqlite/parse.h 10959ac7d8e432bad0301c318fe8ff29d464d533 @@ -49,105 +49,104 @@ #define TK_REPLACE 49 #define TK_RESTRICT 50 #define TK_ROW 51 +#define TK_TRIGGER 52 +#define TK_VACUUM 53 +#define TK_VIEW 54 +#define TK_VIRTUAL 55 +#define TK_REINDEX 56 +#define TK_RENAME 57 +#define TK_CTIME_KW 58 +#define TK_ANY 59 +#define TK_OR 60 +#define TK_AND 61 +#define TK_IS 62 +#define TK_BETWEEN 63 +#define TK_IN 64 +#define TK_ISNULL 65 +#define TK_NOTNULL 66 +#define TK_NE 67 +#define TK_EQ 68 +#define TK_GT 69 +#define TK_LE 70 +#define TK_LT 71 +#define TK_GE 72 +#define TK_ESCAPE 73 +#define TK_BITAND 74 +#define TK_BITOR 75 +#define TK_LSHIFT 76 +#define TK_RSHIFT 77 +#define TK_PLUS 78 +#define TK_MINUS 79 +#define TK_STAR 80 +#define TK_SLASH 81 +#define TK_REM 82 +#define TK_CONCAT 83 +#define TK_COLLATE 84 +#define TK_UMINUS 85 +#define TK_UPLUS 86 +#define TK_BITNOT 87 +#define TK_STRING 88 +#define TK_JOIN_KW 89 +#define TK_CONSTRAINT 90 +#define TK_DEFAULT 91 +#define TK_NULL 92 +#define TK_PRIMARY 93 +#define TK_UNIQUE 94 +#define TK_CHECK 95 +#define TK_REFERENCES 96 +#define TK_AUTOINCR 97 +#define TK_ON 98 +#define TK_DELETE 99 +#define TK_UPDATE 100 +#define TK_INSERT 101 +#define TK_SET 102 +#define TK_DEFERRABLE 103 +#define TK_FOREIGN 104 +#define TK_DROP 105 +#define TK_UNION 106 +#define TK_ALL 107 +#define TK_EXCEPT 108 +#define TK_INTERSECT 109 +#define TK_SELECT 110 +#define TK_DISTINCT 111 +#define TK_DOT 112 +#define TK_FROM 113 +#define TK_JOIN 114 +#define TK_USING 115 +#define TK_ORDER 116 +#define TK_BY 117 +#define TK_GROUP 118 +#define TK_HAVING 119 +#define TK_LIMIT 120 +#define TK_WHERE 121 +#define TK_INTO 122 +#define TK_VALUES 123 +#define TK_INTEGER 124 +#define TK_FLOAT 125 +#define TK_BLOB 126 +#define TK_REGISTER 127 +#define TK_VARIABLE 128 +#define TK_CASE 129 +#define TK_WHEN 130 +#define TK_THEN 131 +#define TK_ELSE 132 +#define TK_INDEX 133 +#define TK_ALTER 134 +#define TK_TO 135 +#define TK_ADD 136 +#define TK_COLUMNKW 137 +#define TK_TO_TEXT 138 +#define TK_TO_BLOB 139 +#define TK_TO_NUMERIC 140 +#define TK_TO_INT 141 +#define TK_TO_REAL 142 +#define TK_END_OF_FILE 143 +#define TK_ILLEGAL 144 +#define TK_SPACE 145 +#define TK_UNCLOSED_STRING 146 +#define TK_COMMENT 147 +#define TK_FUNCTION 148 +#define TK_COLUMN 149 +#define TK_AGG_FUNCTION 150 +#define TK_AGG_COLUMN 151 +#define TK_CONST_FUNC 152 -#define TK_STATEMENT 52 -#define TK_TRIGGER 53 -#define TK_VACUUM 54 -#define TK_VIEW 55 -#define TK_VIRTUAL 56 -#define TK_REINDEX 57 -#define TK_RENAME 58 -#define TK_CTIME_KW 59 -#define TK_ANY 60 -#define TK_OR 61 -#define TK_AND 62 -#define TK_IS 63 -#define TK_BETWEEN 64 -#define TK_IN 65 -#define TK_ISNULL 66 -#define TK_NOTNULL 67 -#define TK_NE 68 -#define TK_EQ 69 -#define TK_GT 70 -#define TK_LE 71 -#define TK_LT 72 -#define TK_GE 73 -#define TK_ESCAPE 74 -#define TK_BITAND 75 -#define TK_BITOR 76 -#define TK_LSHIFT 77 -#define TK_RSHIFT 78 -#define TK_PLUS 79 -#define TK_MINUS 80 -#define TK_STAR 81 -#define TK_SLASH 82 -#define TK_REM 83 -#define TK_CONCAT 84 -#define TK_COLLATE 85 -#define TK_UMINUS 86 -#define TK_UPLUS 87 -#define TK_BITNOT 88 -#define TK_STRING 89 -#define TK_JOIN_KW 90 -#define TK_CONSTRAINT 91 -#define TK_DEFAULT 92 -#define TK_NULL 93 -#define TK_PRIMARY 94 -#define TK_UNIQUE 95 -#define TK_CHECK 96 -#define TK_REFERENCES 97 -#define TK_AUTOINCR 98 -#define TK_ON 99 -#define TK_DELETE 100 -#define TK_UPDATE 101 -#define TK_INSERT 102 -#define TK_SET 103 -#define TK_DEFERRABLE 104 -#define TK_FOREIGN 105 -#define TK_DROP 106 -#define TK_UNION 107 -#define TK_ALL 108 -#define TK_EXCEPT 109 -#define TK_INTERSECT 110 -#define TK_SELECT 111 -#define TK_DISTINCT 112 -#define TK_DOT 113 -#define TK_FROM 114 -#define TK_JOIN 115 -#define TK_USING 116 -#define TK_ORDER 117 -#define TK_BY 118 -#define TK_GROUP 119 -#define TK_HAVING 120 -#define TK_LIMIT 121 -#define TK_WHERE 122 -#define TK_INTO 123 -#define TK_VALUES 124 -#define TK_INTEGER 125 -#define TK_FLOAT 126 -#define TK_BLOB 127 -#define TK_REGISTER 128 -#define TK_VARIABLE 129 -#define TK_CASE 130 -#define TK_WHEN 131 -#define TK_THEN 132 -#define TK_ELSE 133 -#define TK_INDEX 134 -#define TK_ALTER 135 -#define TK_TO 136 -#define TK_ADD 137 -#define TK_COLUMNKW 138 -#define TK_TO_TEXT 139 -#define TK_TO_BLOB 140 -#define TK_TO_NUMERIC 141 -#define TK_TO_INT 142 -#define TK_TO_REAL 143 -#define TK_END_OF_FILE 144 -#define TK_ILLEGAL 145 -#define TK_SPACE 146 -#define TK_UNCLOSED_STRING 147 -#define TK_COMMENT 148 -#define TK_FUNCTION 149 -#define TK_COLUMN 150 -#define TK_AGG_FUNCTION 151 -#define TK_AGG_COLUMN 152 -#define TK_CONST_FUNC 153 ============================================================ --- sqlite/pragma.c 5091300911670ddaa552bfa12c45cbca1bb7e7d6 +++ sqlite/pragma.c 3b992b5b2640d6ae25cef05aa6a42cd1d6c43234 @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.127 2007/01/27 02:24:56 drh Exp $ +** $Id: pragma.c,v 1.132 2007/03/30 17:11:13 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -62,6 +62,17 @@ static int getBoolean(const char *z){ return getSafetyLevel(z)&1; } +/* +** Interpret the given string as a locking mode value. +*/ +static int getLockingMode(const char *z){ + if( z ){ + if( 0==sqlite3StrICmp(z, "exclusive") ) return PAGER_LOCKINGMODE_EXCLUSIVE; + if( 0==sqlite3StrICmp(z, "normal") ) return PAGER_LOCKINGMODE_NORMAL; + } + return PAGER_LOCKINGMODE_QUERY; +} + #ifndef SQLITE_OMIT_PAGER_PRAGMAS /* ** Interpret the given string as a temp db location. Return 1 for file @@ -89,7 +100,7 @@ static int invalidateTempStorage(Parse * static int invalidateTempStorage(Parse *pParse){ sqlite3 *db = pParse->db; if( db->aDb[1].pBt!=0 ){ - if( db->flags & SQLITE_InTrans ){ + if( !db->autoCommit ){ sqlite3ErrorMsg(pParse, "temporary storage cannot be changed " "from within a transaction"); return SQLITE_ERROR; @@ -157,7 +168,7 @@ static int flagPragma(Parse *pParse, con { "ignore_check_constraints", SQLITE_IgnoreChecks }, #endif /* The following is VERY experimental */ - { "writable_schema", SQLITE_WriteSchema }, + { "writable_schema", SQLITE_WriteSchema|SQLITE_RecoveryMode }, { "omit_readlock", SQLITE_NoReadlock }, /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted @@ -315,6 +326,53 @@ void sqlite3Pragma( sqlite3BtreeSetPageSize(pBt, atoi(zRight), -1); } }else + + /* + ** PRAGMA [database.]locking_mode + ** PRAGMA [database.]locking_mode = (normal|exclusive) + */ + if( sqlite3StrICmp(zLeft,"locking_mode")==0 ){ + const char *zRet = "normal"; + int eMode = getLockingMode(zRight); + + if( pId2->n==0 && eMode==PAGER_LOCKINGMODE_QUERY ){ + /* Simple "PRAGMA locking_mode;" statement. This is a query for + ** the current default locking mode (which may be different to + ** the locking-mode of the main database). + */ + eMode = db->dfltLockMode; + }else{ + Pager *pPager; + if( pId2->n==0 ){ + /* This indicates that no database name was specified as part + ** of the PRAGMA command. In this case the locking-mode must be + ** set on all attached databases, as well as the main db file. + ** + ** Also, the sqlite3.dfltLockMode variable is set so that + ** any subsequently attached databases also use the specified + ** locking mode. + */ + int ii; + assert(pDb==&db->aDb[0]); + for(ii=2; iinDb; ii++){ + pPager = sqlite3BtreePager(db->aDb[ii].pBt); + sqlite3PagerLockingMode(pPager, eMode); + } + db->dfltLockMode = eMode; + } + pPager = sqlite3BtreePager(pDb->pBt); + eMode = sqlite3PagerLockingMode(pPager, eMode); + } + + assert(eMode==PAGER_LOCKINGMODE_NORMAL||eMode==PAGER_LOCKINGMODE_EXCLUSIVE); + if( eMode==PAGER_LOCKINGMODE_EXCLUSIVE ){ + zRet = "exclusive"; + } + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "locking_mode", P3_STATIC); + sqlite3VdbeOp3(v, OP_String8, 0, 0, zRet, 0); + sqlite3VdbeAddOp(v, OP_Callback, 1, 0); + }else #endif /* SQLITE_OMIT_PAGER_PRAGMAS */ /* @@ -916,7 +974,7 @@ void sqlite3Pragma( sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, P3_TRANSIENT); } - } + }else #endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */ #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) @@ -941,7 +999,7 @@ void sqlite3Pragma( if( pBt==0 || (pPager = sqlite3BtreePager(pBt))==0 ){ sqlite3VdbeOp3(v, OP_String8, 0, 0, "closed", P3_STATIC); }else{ - int j = sqlite3pager_lockstate(pPager); + int j = sqlite3PagerLockstate(pPager); sqlite3VdbeOp3(v, OP_String8, 0, 0, (j>=0 && j<=4) ? azLockName[j] : "unknown", P3_STATIC); } ============================================================ --- sqlite/prepare.c 484389c6811415b8f23d259ac9c029613e1c72c3 +++ sqlite/prepare.c 37207b2b2ccb41d379b01dd62231686bcc48ef1f @@ -13,7 +13,7 @@ ** interface, and routines that contribute to loading the database schema ** from disk. ** -** $Id: prepare.c,v 1.43 2007/01/09 14:01:13 drh Exp $ +** $Id: prepare.c,v 1.45 2007/03/26 22:05:02 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -310,10 +310,17 @@ static int sqlite3InitOne(sqlite3 *db, i rc = SQLITE_NOMEM; sqlite3ResetInternalSchema(db, 0); } - if( rc==SQLITE_OK ){ + if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){ + /* Black magic: If the SQLITE_RecoveryMode flag is set, then consider + ** the schema loaded, even if errors occured. In this situation the + ** current sqlite3_prepare() operation will fail, but the following one + ** will attempt to compile the supplied statement against whatever subset + ** of the schema was loaded before the error occured. The primary + ** purpose of this is to allow access to the sqlite_master table + ** even when it's contents have been corrupted. + */ DbSetProperty(db, iDb, DB_SchemaLoaded); - }else{ - sqlite3ResetInternalSchema(db, iDb); + rc = SQLITE_OK; } return rc; } @@ -559,7 +566,7 @@ int sqlite3Reprepare(Vdbe *p){ */ int sqlite3Reprepare(Vdbe *p){ int rc; - Vdbe *pNew; + sqlite3_stmt *pNew; const char *zSql; sqlite3 *db; @@ -568,17 +575,17 @@ int sqlite3Reprepare(Vdbe *p){ return 0; } db = sqlite3VdbeDb(p); - rc = sqlite3Prepare(db, zSql, -1, 0, (sqlite3_stmt**)&pNew, 0); + rc = sqlite3Prepare(db, zSql, -1, 0, &pNew, 0); if( rc ){ assert( pNew==0 ); return 0; }else{ assert( pNew!=0 ); } - sqlite3VdbeSwap(pNew, p); - sqlite3_transfer_bindings((sqlite3_stmt*)pNew, (sqlite3_stmt*)p); - sqlite3VdbeResetStepResult(pNew); - sqlite3VdbeFinalize(pNew); + sqlite3VdbeSwap((Vdbe*)pNew, p); + sqlite3_transfer_bindings(pNew, (sqlite3_stmt*)p); + sqlite3VdbeResetStepResult((Vdbe*)pNew); + sqlite3VdbeFinalize((Vdbe*)pNew); return 1; } ============================================================ --- sqlite/printf.c aade23a789d7cc88b397ec0d33a0a01a33a7a9c1 +++ sqlite/printf.c 0c6f40648770831341ac45ab32423a80b4c87f05 @@ -821,9 +821,8 @@ char *sqlite3_mprintf(const char *zForma char *sqlite3_mprintf(const char *zFormat, ...){ va_list ap; char *z; - char zBase[SQLITE_PRINT_BUF_SIZE]; va_start(ap, zFormat); - z = base_vprintf(sqlite3_realloc, 0, zBase, sizeof(zBase), zFormat, ap); + z = sqlite3_vmprintf(zFormat, ap); va_end(ap); return z; } ============================================================ --- sqlite/select.c 63b2163f35fd2570a02dab5759979644c4405f1c +++ sqlite/select.c 6d6e7c992fb0f170e60e6c1f53fe87f52e73aeba @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.326 2007/02/01 23:02:45 drh Exp $ +** $Id: select.c,v 1.333 2007/04/06 01:04:40 drh Exp $ */ #include "sqliteInt.h" @@ -68,6 +68,7 @@ Select *sqlite3SelectNew( pNew->pOrderBy = pOrderBy; pNew->isDistinct = isDistinct; pNew->op = TK_SELECT; + assert( pOffset==0 || pLimit!=0 ); pNew->pLimit = pLimit; pNew->pOffset = pOffset; pNew->iLimit = -1; @@ -534,7 +535,7 @@ static int selectInnerLoop( }else{ sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); - sqlite3VdbeAddOp(v, OP_Insert, iParm, 0); + sqlite3VdbeAddOp(v, OP_Insert, iParm, OPFLAG_APPEND); } break; } @@ -693,7 +694,7 @@ static void generateSortTail( int cont = sqlite3VdbeMakeLabel(v); int addr; int iTab; - int pseudoTab; + int pseudoTab = 0; ExprList *pOrderBy = p->pOrderBy; iTab = pOrderBy->iECursor; @@ -713,7 +714,7 @@ static void generateSortTail( case SRT_EphemTab: { sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); - sqlite3VdbeAddOp(v, OP_Insert, iParm, 0); + sqlite3VdbeAddOp(v, OP_Insert, iParm, OPFLAG_APPEND); break; } #ifndef SQLITE_OMIT_SUBQUERY @@ -2366,6 +2367,8 @@ static int simpleMinMaxQuery(Parse *pPar iCol = pExpr->iColumn; pTab = pSrc->a[0].pTab; + /* This optimization cannot be used with virtual tables. */ + if( IsVirtual(pTab) ) return 0; /* If we get to here, it means the query is of the correct form. ** Check to make sure we have an index and make pIdx point to the @@ -3144,11 +3147,7 @@ int sqlite3Select( for(i=0; iiSorterColumniColumn<0 ){ - sqlite3VdbeAddOp(v, OP_Rowid, pCol->iTable, 0); - }else{ - sqlite3VdbeAddOp(v, OP_Column, pCol->iTable, pCol->iColumn); - } + sqlite3ExprCodeGetColumn(v, pCol->pTab, pCol->iColumn, pCol->iTable); j++; } sqlite3VdbeAddOp(v, OP_MakeRecord, j, 0); @@ -3298,7 +3297,7 @@ select_end: return rc; } -#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) +#if defined(SQLITE_DEBUG) /* ******************************************************************************* ** The following code is used for testing and debugging only. The code ============================================================ --- sqlite/sqlite3.h c17a4ef52a78c0ca61df95965c1ce3c2192b98de +++ sqlite/sqlite3.h 9cbbd1bfa4521bee3ec1584f5b4356888c9bb688 @@ -12,7 +12,7 @@ ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.198 2007/01/26 00:51:44 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.201 2007/03/30 20:43:42 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -31,7 +31,7 @@ extern "C" { #ifdef SQLITE_VERSION # undef SQLITE_VERSION #endif -#define SQLITE_VERSION "3.3.13" +#define SQLITE_VERSION "3.3.15" /* ** The format of the version string is "X.Y.Z", where @@ -48,7 +48,7 @@ extern "C" { #ifdef SQLITE_VERSION_NUMBER # undef SQLITE_VERSION_NUMBER #endif -#define SQLITE_VERSION_NUMBER 3003013 +#define SQLITE_VERSION_NUMBER 3003015 /* ** The version string is also compiled into the library so that a program @@ -182,7 +182,7 @@ int sqlite3_exec( #define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */ #define SQLITE_FULL 13 /* Insertion failed because database is full */ #define SQLITE_CANTOPEN 14 /* Unable to open the database file */ -#define SQLITE_PROTOCOL 15 /* Database lock protocol error */ +#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */ #define SQLITE_EMPTY 16 /* Database is empty */ #define SQLITE_SCHEMA 17 /* The database schema changed */ #define SQLITE_TOOBIG 18 /* NOT USED. Too much data for one row */ @@ -230,6 +230,7 @@ int sqlite3_exec( #define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) #define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) #define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) +#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8)) /* ** Enable or disable the extended result codes. @@ -239,25 +240,29 @@ int sqlite3_extended_result_codes(sqlite /* ** Each entry in an SQLite table has a unique integer key. (The key is ** the value of the INTEGER PRIMARY KEY column if there is such a column, -** otherwise the key is generated at random. The unique key is always +** otherwise the key is generated automatically. The unique key is always ** available as the ROWID, OID, or _ROWID_ column.) The following routine ** returns the integer key of the most recent insert in the database. -** -** This function is similar to the mysql_insert_id() function from MySQL. */ sqlite_int64 sqlite3_last_insert_rowid(sqlite3*); /* ** This function returns the number of database rows that were changed -** (or inserted or deleted) by the most recent called sqlite3_exec(). +** (or inserted or deleted) by the most recent SQL statement. Only +** changes that are directly specified by the INSERT, UPDATE, or +** DELETE statement are counted. Auxiliary changes caused by +** triggers are not counted. Within the body of a trigger, however, +** the sqlite3_changes() API can be called to find the number of +** changes in the most recently completed INSERT, UPDATE, or DELETE +** statement within the body of the trigger. ** ** All changes are counted, even if they were later undone by a ** ROLLBACK or ABORT. Except, changes associated with creating and ** dropping tables are not counted. ** -** If a callback invokes sqlite3_exec() recursively, then the changes -** in the inner, recursive call are counted together with the changes -** in the outer call. +** If a callback invokes sqlite3_exec() or sqlite3_step() recursively, +** then the changes in the inner, recursive call are counted together +** with the changes in the outer call. ** ** SQLite implements the command "DELETE FROM table" without a WHERE clause ** by dropping and recreating the table. (This is much faster than going @@ -292,6 +297,9 @@ int sqlite3_total_changes(sqlite3*); ** called in response to a user action such as pressing "Cancel" ** or Ctrl-C where the user wants a long query operation to halt ** immediately. +** +** It is safe to call this routine from a different thread that the +** thread that is currently running the database operation. */ void sqlite3_interrupt(sqlite3*); @@ -302,9 +310,13 @@ void sqlite3_interrupt(sqlite3*); ** sqlite3_complete16(), a nul-terminated machine byte order UTF-16 string ** is required. ** -** The algorithm is simple. If the last token other than spaces -** and comments is a semicolon, then return true. otherwise return -** false. +** This routine is useful for command-line input to see of the user has +** entered a complete statement of SQL or if the current statement needs +** to be continued on the next line. The algorithm is simple. If the +** last token other than spaces and comments is a semicolon, then return +** true. Actually, the algorithm is a little more complicated than that +** in order to deal with triggers, but the basic idea is the same: the +** statement is not complete unless it ends in a semicolon. */ int sqlite3_complete(const char *sql); int sqlite3_complete16(const void *sql); @@ -743,31 +755,32 @@ typedef struct Mem sqlite3_value; /* ** In the SQL strings input to sqlite3_prepare() and sqlite3_prepare16(), -** one or more literals can be replace by parameters "?" or ":AAA" or -** "$VVV" where AAA is an identifer and VVV is a variable name according -** to the syntax rules of the TCL programming language. -** The value of these parameters (also called "host parameter names") can -** be set using the routines listed below. +** one or more literals can be replace by parameters "?" or "?NNN" or +** ":AAA" or "@AAA" or "$VVV" where NNN is a integer, AAA is an identifer, +** and VVV is a variable name according to the syntax rules of the +** TCL programming language. The value of these parameters (also called +** "host parameter names") can be set using the routines listed below. ** -** In every case, the first parameter is a pointer to the sqlite3_stmt -** structure returned from sqlite3_prepare(). The second parameter is the -** index of the parameter. The first parameter as an index of 1. For -** named parameters (":AAA" or "$VVV") you can use +** In every case, the first argument is a pointer to the sqlite3_stmt +** structure returned from sqlite3_prepare(). The second argument is the +** index of the host parameter name. The first host parameter as an index +** of 1. For named host parameters (":AAA" or "$VVV") you can use ** sqlite3_bind_parameter_index() to get the correct index value given -** the parameters name. If the same named parameter occurs more than +** the parameter name. If the same named parameter occurs more than ** once, it is assigned the same index each time. ** -** The fifth parameter to sqlite3_bind_blob(), sqlite3_bind_text(), and +** The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and ** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or ** text after SQLite has finished with it. If the fifth argument is the ** special value SQLITE_STATIC, then the library assumes that the information ** is in static, unmanaged space and does not need to be freed. If the ** fifth argument has the value SQLITE_TRANSIENT, then SQLite makes its -** own private copy of the data. +** own private copy of the data before the sqlite3_bind_* routine returns. ** -** The sqlite3_bind_* routine must be called before sqlite3_step() after -** an sqlite3_prepare() or sqlite3_reset(). Unbound parameterss are -** interpreted as NULL. +** The sqlite3_bind_* routine must be called before sqlite3_step() and after +** an sqlite3_prepare() or sqlite3_reset(). Bindings persist across +** multiple calls to sqlite3_reset() and sqlite3_step(). Unbound parameters +** are interpreted as NULL. */ int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); int sqlite3_bind_double(sqlite3_stmt*, int, double); @@ -779,13 +792,13 @@ int sqlite3_bind_value(sqlite3_stmt*, in int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); /* -** Return the number of parameters in a compiled SQL statement. This +** Return the number of host parameters in a compiled SQL statement. This ** routine was added to support DBD::SQLite. */ int sqlite3_bind_parameter_count(sqlite3_stmt*); /* -** Return the name of the i-th parameter. Ordinary parameters "?" are +** Return the name of the i-th name parameter. Ordinary parameters "?" are ** nameless and a NULL is returned. For parameters of the form :AAA or ** $VVV the complete text of the parameter name is returned, including ** the initial ":" or "$". NULL is returned if the index is out of range. @@ -821,7 +834,7 @@ const void *sqlite3_column_name16(sqlite const void *sqlite3_column_name16(sqlite3_stmt*,int); /* -** The first parameter to the following calls is a compiled SQL statement. +** The first argument to the following calls is a compiled SQL statement. ** These functions return information about the Nth column returned by ** the statement, where N is the second function argument. ** ============================================================ --- sqlite/sqlite3ext.h 011c75fd6459a61454514af07c7a4f1f5c767f27 +++ sqlite/sqlite3ext.h 7d0d363ea7327e817ef0dfe1b7eee1f171b72890 @@ -15,7 +15,7 @@ ** as extensions by SQLite should #include this file instead of ** sqlite3.h. ** -** @(#) $Id: sqlite3ext.h,v 1.8 2007/01/09 14:37:18 drh Exp $ +** @(#) $Id: sqlite3ext.h,v 1.10 2007/03/29 18:46:01 drh Exp $ */ #ifndef _SQLITE3EXT_H_ #define _SQLITE3EXT_H_ @@ -142,8 +142,11 @@ struct sqlite3_api_routines { const void * (*value_text16be)(sqlite3_value*); const void * (*value_text16le)(sqlite3_value*); int (*value_type)(sqlite3_value*); - char * (*vmprintf)(const char*,va_list); + char *(*vmprintf)(const char*,va_list); int (*overload_function)(sqlite3*, const char *zFuncName, int nArg); + int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); + int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); + int (*clear_bindings)(sqlite3_stmt*); }; /* @@ -232,6 +235,8 @@ struct sqlite3_api_routines { #define sqlite3_open16 sqlite3_api->open16 #define sqlite3_prepare sqlite3_api->prepare #define sqlite3_prepare16 sqlite3_api->prepare16 +#define sqlite3_prepare_v2 sqlite3_api->prepare_v2 +#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 #define sqlite3_profile sqlite3_api->profile #define sqlite3_progress_handler sqlite3_api->progress_handler #define sqlite3_realloc sqlite3_api->realloc @@ -274,6 +279,9 @@ struct sqlite3_api_routines { #define sqlite3_value_type sqlite3_api->value_type #define sqlite3_vmprintf sqlite3_api->vmprintf #define sqlite3_overload_function sqlite3_api->overload_function +#define sqlite3_prepare_v2 sqlite3_api->prepare_v2 +#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 +#define sqlite3_clear_bindings sqlite3_api->clear_bindings #endif /* SQLITE_CORE */ #define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api; ============================================================ --- sqlite/sqliteInt.h 409dfff7f08135017aa2dfb65245dfc7b1db7099 +++ sqlite/sqliteInt.h 347160d30eb61210417f1086aeb57d7d3e2a8191 @@ -11,16 +11,13 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.536 2007/02/13 12:49:24 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.550 2007/04/06 11:26:00 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ -/* -** Extra interface definitions for those who need them -*/ -#ifdef SQLITE_EXTRA -# include "sqliteExtra.h" +#if defined(SQLITE_TCL) || defined(TCLSH) +# include #endif /* @@ -215,8 +212,15 @@ extern const int sqlite3one; ** evaluated at runtime. */ extern const int sqlite3one; -#define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0) -#define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1) +#if defined(i386) || defined(__i386__) || defined(_M_IX86) +# define SQLITE_BIGENDIAN 0 +# define SQLITE_LITTLEENDIAN 1 +# define SQLITE_UTF16NATIVE SQLITE_UTF16LE +#else +# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0) +# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1) +# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE) +#endif /* ** An instance of the following structure is used to store the busy-handler @@ -414,7 +418,6 @@ struct Schema { #define DB_UnresetViews 0x0002 /* Some views have defined column names */ #define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */ -#define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE) /* ** Each database is an instance of the following structure. @@ -510,6 +513,7 @@ struct sqlite3 { #ifdef SQLITE_SSE sqlite3_stmt *pFetch; /* Used by SSE to fetch stored statements */ #endif + u8 dfltLockMode; /* Default locking-mode for attached dbs */ }; /* @@ -545,6 +549,8 @@ struct sqlite3 { #define SQLITE_FullFSync 0x00010000 /* Use full fsync on the backend */ #define SQLITE_LoadExtension 0x00020000 /* Enable load_extension */ +#define SQLITE_RecoveryMode 0x00040000 /* Ignore schema errors */ + /* ** Possible values for the sqlite.magic field. ** The numbers are obtained at random and have no special meaning, other @@ -922,6 +928,7 @@ struct AggInfo { ExprList *pGroupBy; /* The group by clause */ int nSortingColumn; /* Number of columns in the sorting index */ struct AggInfo_col { /* For each column used in source tables */ + Table *pTab; /* Source table */ int iTable; /* Cursor number of the source table */ int iColumn; /* Column number within the source table */ int iSorterColumn; /* Column number in the sorting index */ @@ -1159,12 +1166,16 @@ struct WhereLevel { int iTabCur; /* The VDBE cursor used to access the table */ int iIdxCur; /* The VDBE cursor used to acesss pIdx */ int brk; /* Jump here to break out of the loop */ + int nxt; /* Jump here to start the next IN combination */ int cont; /* Jump here to continue with the next loop cycle */ int top; /* First instruction of interior of the loop */ int op, p1, p2; /* Opcode used to terminate the loop */ int nEq; /* Number of == or IN constraints on this loop */ int nIn; /* Number of IN operators constraining this loop */ - int *aInLoop; /* Loop terminators for IN operators */ + struct InLoop { + int iCur; /* The VDBE cursor used by this IN operator */ + int topAddr; /* Top of the IN loop */ + } *aInLoop; /* Information about each nested IN operator */ sqlite3_index_info *pBestIdx; /* Index information for this level */ /* The following field is really not part of the current level. But @@ -1371,6 +1382,7 @@ struct AuthContext { #define OPFLAG_NCHANGE 1 /* Set to update db->nChange */ #define OPFLAG_LASTROWID 2 /* Set to update db->lastRowid */ #define OPFLAG_ISUPDATE 4 /* This OP_Insert is an sql UPDATE */ +#define OPFLAG_APPEND 8 /* This is likely to be an append */ /* * Each trigger present in the database schema is stored as an instance of @@ -1395,7 +1407,6 @@ struct Trigger { Expr *pWhen; /* The WHEN clause of the expresion (may be NULL) */ IdList *pColumns; /* If this is an UPDATE OF trigger, the is stored here */ - int foreach; /* One of TK_ROW or TK_STATEMENT */ Token nameToken; /* Token containing zName. Use during parsing only */ Schema *pSchema; /* Schema containing the trigger */ Schema *pTabSchema; /* Schema containing the table */ @@ -1566,7 +1577,7 @@ char *sqlite3StrNDup(const char*, int); char *sqlite3StrDup(const char*); char *sqlite3StrNDup(const char*, int); # define sqlite3CheckMemory(a,b) -void sqlite3ReallocOrFree(void**,int); +void *sqlite3ReallocOrFree(void*,int); void sqlite3FreeX(void*); void *sqlite3MallocX(int); int sqlite3AllocSize(void *); @@ -1598,7 +1609,6 @@ void sqlite3BeginParse(Parse*,int); void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); void sqlite3ResetInternalSchema(sqlite3*, int); void sqlite3BeginParse(Parse*,int); -void sqlite3RollbackInternalChanges(sqlite3*); void sqlite3CommitInternalChanges(sqlite3*); Table *sqlite3ResultSetOfSelect(Parse*,char*,Select*); void sqlite3OpenMasterTable(Parse *, int); @@ -1623,7 +1633,7 @@ void sqlite3Insert(Parse*, SrcList*, Exp void sqlite3DropTable(Parse*, SrcList*, int, int); void sqlite3DeleteTable(sqlite3*, Table*); void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int); -int sqlite3ArrayAllocate(void**,int,int); +void *sqlite3ArrayAllocate(void*,int,int,int*,int*,int*); IdList *sqlite3IdListAppend(IdList*, Token*); int sqlite3IdListIndex(IdList*,const char*); SrcList *sqlite3SrcListAppend(SrcList*, Token*, Token*); @@ -1650,6 +1660,7 @@ void sqlite3WhereEnd(WhereInfo*); void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**); void sqlite3WhereEnd(WhereInfo*); +void sqlite3ExprCodeGetColumn(Vdbe*, Table*, int, int); void sqlite3ExprCode(Parse*, Expr*); void sqlite3ExprCodeAndCache(Parse*, Expr*); int sqlite3ExprCodeExprList(Parse*, ExprList*); @@ -1686,7 +1697,7 @@ void sqlite3GenerateConstraintChecks(Par void sqlite3GenerateRowIndexDelete(Vdbe*, Table*, int, char*); void sqlite3GenerateIndexKey(Vdbe*, Index*, int); void sqlite3GenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int); -void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int); +void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int, int); void sqlite3OpenTableAndIndices(Parse*, Table*, int, int); void sqlite3BeginWriteOperation(Parse*, int, int); Expr *sqlite3ExprDup(Expr*); @@ -1705,7 +1716,7 @@ void sqlite3ChangeCookie(sqlite3*, Vdbe* #ifndef SQLITE_OMIT_TRIGGER void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*, - int,Expr*,int, int); + Expr*,int, int); void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*); void sqlite3DropTrigger(Parse*, SrcList*, int); void sqlite3DropTriggerPtr(Parse*, Trigger*); @@ -1895,4 +1906,18 @@ int sqlite3Reprepare(Vdbe*); #include "sseInt.h" #endif +/* +** If the SQLITE_ENABLE IOTRACE exists then the global variable +** sqlite3_io_trace is a pointer to a printf-like routine used to +** print I/O tracing messages. +*/ +#ifdef SQLITE_ENABLE_IOTRACE +# define IOTRACE(A) if( sqlite3_io_trace ){ sqlite3_io_trace A; } + void sqlite3VdbeIOTraceSql(Vdbe*); +#else +# define IOTRACE(A) +# define sqlite3VdbeIOTraceSql(X) #endif +extern void (*sqlite3_io_trace)(const char*,...); + +#endif ============================================================ --- sqlite/trigger.c 8c55d31876013ed4e97ee7ce24478fbe00db49bb +++ sqlite/trigger.c 420192efe3e6f03addf7897c60c3c8bf913d3493 @@ -47,7 +47,6 @@ void sqlite3BeginTrigger( int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */ IdList *pColumns, /* column list if this is an UPDATE OF trigger */ SrcList *pTableName,/* The name of the table/view the trigger applies to */ - int foreach, /* One of TK_ROW or TK_STATEMENT */ Expr *pWhen, /* WHEN clause */ int isTemp, /* True if the TEMPORARY keyword is present */ int noErr /* Suppress errors if the trigger already exists */ @@ -180,7 +179,6 @@ void sqlite3BeginTrigger( pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; pTrigger->pWhen = sqlite3ExprDup(pWhen); pTrigger->pColumns = sqlite3IdListDup(pColumns); - pTrigger->foreach = foreach; sqlite3TokenCopy(&pTrigger->nameToken,pName); assert( pParse->pNewTrigger==0 ); pParse->pNewTrigger = pTrigger; @@ -390,7 +388,11 @@ TriggerStep *sqlite3TriggerUpdateStep( int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ ){ TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); - if( pTriggerStep==0 ) return 0; + if( pTriggerStep==0 ){ + sqlite3ExprListDelete(pEList); + sqlite3ExprDelete(pWhere); + return 0; + } pTriggerStep->op = TK_UPDATE; pTriggerStep->target = *pTableName; @@ -409,7 +411,10 @@ TriggerStep *sqlite3TriggerDeleteStep(To */ TriggerStep *sqlite3TriggerDeleteStep(Token *pTableName, Expr *pWhere){ TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); - if( pTriggerStep==0 ) return 0; + if( pTriggerStep==0 ){ + sqlite3ExprDelete(pWhere); + return 0; + } pTriggerStep->op = TK_DELETE; pTriggerStep->target = *pTableName; ============================================================ --- sqlite/update.c bdfcf3600f129bd5f06094781ab41cd7b7f5ab25 +++ sqlite/update.c 3359041db390a8f856d67272f299600e2104f350 @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** -** $Id: update.c,v 1.134 2007/02/07 01:06:53 drh Exp $ +** $Id: update.c,v 1.137 2007/03/29 05:51:49 drh Exp $ */ #include "sqliteInt.h" @@ -465,7 +465,7 @@ void sqlite3Update( /* Create the new index entries and the new record. */ - sqlite3CompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRowid, 1, -1); + sqlite3CompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRowid, 1, -1, 0); } /* Increment the row counter @@ -617,6 +617,7 @@ static void updateVirtualTable( sqlite3VdbeOp3(v, OP_VUpdate, 0, pTab->nCol+2, (const char*)pTab->pVtab, P3_VTAB); sqlite3VdbeAddOp(v, OP_Next, ephemTab, addr); + sqlite3VdbeJumpHere(v, addr-1); sqlite3VdbeAddOp(v, OP_Close, ephemTab, 0); /* Cleanup */ ============================================================ --- sqlite/utf.c 67ecb1032bc0b42c105e88d65ef9d9f626eb0e1f +++ sqlite/utf.c e64a48bc21aa973eb622dd47da87d56a4cdcf528 @@ -12,7 +12,7 @@ ** This file contains routines used to translate between UTF-8, ** UTF-16, UTF-16BE, and UTF-16LE. ** -** $Id: utf.c,v 1.43 2006/10/19 01:58:44 drh Exp $ +** $Id: utf.c,v 1.44 2007/03/31 15:28:00 drh Exp $ ** ** Notes on UTF-8: ** @@ -63,6 +63,12 @@ #include "vdbeInt.h" /* +** The following constant value is used by the SQLITE_BIGENDIAN and +** SQLITE_LITTLEENDIAN macros. +*/ +const int sqlite3one = 1; + +/* ** This table maps from the first byte of a UTF-8 character to the number ** of trailing bytes expected. A value '4' indicates that the table key ** is not a legal first byte for a UTF-8 character. ============================================================ --- sqlite/util.c 91d4cb189476906639ae611927d939691d1365f6 +++ sqlite/util.c b6344325378e75b9e18175d8b6aed1723d73dad9 @@ -14,7 +14,7 @@ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.193 2006/09/15 07:28:51 drh Exp $ +** $Id: util.c,v 1.199 2007/04/06 02:32:34 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -83,7 +83,7 @@ int sqlite3_release_memory(int n){ ** Release memory held by SQLite instances created by the current thread. */ int sqlite3_release_memory(int n){ - return sqlite3pager_release_memory(n); + return sqlite3PagerReleaseMemory(n); } #else /* If SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined, then define a version @@ -661,12 +661,13 @@ void *sqlite3Malloc(int n, int doMemMana } return p; } -void sqlite3ReallocOrFree(void **pp, int n){ - void *p = sqlite3Realloc(*pp, n); - if( !p ){ - sqlite3FreeX(*pp); +void *sqlite3ReallocOrFree(void *p, int n){ + void *pNew; + pNew = sqlite3Realloc(p, n); + if( !pNew ){ + sqlite3FreeX(p); } - *pp = p; + return pNew; } /* @@ -750,7 +751,7 @@ void sqlite3SetString(char **pz, ...){ const char *z; char *zResult; - if( pz==0 ) return; + assert( pz!=0 ); nByte = 1; va_start(ap, pz); while( (z = va_arg(ap, const char*))!=0 ){ @@ -1132,6 +1133,13 @@ int sqlite3FitsIn64Bits(const char *zNum ** Return an error (non-zero) if the magic was not SQLITE_MAGIC_OPEN ** when this routine is called. ** +** This routine is called when entering an SQLite API. The SQLITE_MAGIC_OPEN +** value indicates that the database connection passed into the API is +** open and is not being used by another thread. By changing the value +** to SQLITE_MAGIC_BUSY we indicate that the connection is in use. +** sqlite3SafetyOff() below will change the value back to SQLITE_MAGIC_OPEN +** when the API exits. +** ** This routine is a attempt to detect if two threads use the ** same sqlite* pointer at the same time. There is a race ** condition so it is possible that the error is not detected. @@ -1165,11 +1173,11 @@ int sqlite3SafetyOff(sqlite3 *db){ if( db->magic==SQLITE_MAGIC_BUSY ){ db->magic = SQLITE_MAGIC_OPEN; return 0; - }else if( db->magic==SQLITE_MAGIC_OPEN ){ + }else { db->magic = SQLITE_MAGIC_ERROR; db->u1.isInterrupted = 1; + return 1; } - return 1; } /* @@ -1384,11 +1392,11 @@ void *sqlite3TextToPtr(const char *z){ z++; } if( sizeof(p)==sizeof(v) ){ - p = *(void**)&v; + memcpy(&p, &v, sizeof(p)); }else{ assert( sizeof(p)==sizeof(v2) ); v2 = (u32)v; - p = *(void**)&v2; + memcpy(&p, &v2, sizeof(p)); } return p; } @@ -1461,9 +1469,11 @@ void sqlite3FailedMalloc(){ ** Set the "malloc has failed" condition to true for this thread. */ void sqlite3FailedMalloc(){ - sqlite3OsEnterMutex(); - assert( mallocHasFailed==0 ); - mallocHasFailed = 1; + if( !sqlite3MallocFailed() ){ + sqlite3OsEnterMutex(); + assert( mallocHasFailed==0 ); + mallocHasFailed = 1; + } } #ifdef SQLITE_MEMDEBUG ============================================================ --- sqlite/vacuum.c b4569b08aaa5afb141af3f76d0315745db4e9e4b +++ sqlite/vacuum.c 8bd895d29e7074e78d4e80f948e35ddc9cf2beef @@ -14,13 +14,13 @@ ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. ** -** $Id: vacuum.c,v 1.66 2007/01/03 23:37:29 drh Exp $ +** $Id: vacuum.c,v 1.69 2007/03/27 16:19:52 danielk1977 Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" #include "os.h" -#ifndef SQLITE_OMIT_VACUUM +#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) /* ** Execute zSql on database db. Return an error code. */ @@ -83,13 +83,11 @@ int sqlite3RunVacuum(char **pzErrMsg, sq char *zSql = 0; /* SQL statements */ int saved_flags; /* Saved value of the db->flags */ Db *pDb = 0; /* Database to detach at end of vacuum */ - char zTemp[SQLITE_TEMPNAME_SIZE+20]; /* Name of the TEMP file */ /* Save the current value of the write-schema flag before setting it. */ saved_flags = db->flags; db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks; - sqlite3OsTempFileName(zTemp); if( !db->autoCommit ){ sqlite3SetString(pzErrMsg, "cannot VACUUM from within a transaction", (char*)0); @@ -106,20 +104,18 @@ int sqlite3RunVacuum(char **pzErrMsg, sq ** ** An optimisation would be to use a non-journaled pager. */ - zSql = sqlite3MPrintf("ATTACH '%q' AS vacuum_db;", zTemp); - if( !zSql ){ - rc = SQLITE_NOMEM; - goto end_of_vacuum; - } + zSql = "ATTACH '' AS vacuum_db;"; rc = execSql(db, zSql); - sqliteFree(zSql); - zSql = 0; if( rc!=SQLITE_OK ) goto end_of_vacuum; pDb = &db->aDb[db->nDb-1]; assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 ); pTemp = db->aDb[db->nDb-1].pBt; sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), sqlite3BtreeGetReserve(pMain)); + if( sqlite3MallocFailed() ){ + rc = SQLITE_NOMEM; + goto end_of_vacuum; + } assert( sqlite3BtreeGetPageSize(pTemp)==sqlite3BtreeGetPageSize(pMain) ); rc = execSql(db, "PRAGMA vacuum_db.synchronous=OFF"); if( rc!=SQLITE_OK ){ @@ -259,12 +255,8 @@ end_of_vacuum: pDb->pSchema = 0; } - sqlite3OsDelete(zTemp); - strcat(zTemp, "-journal"); - sqlite3OsDelete(zTemp); - sqliteFree( zSql ); sqlite3ResetInternalSchema(db, 0); return rc; } +#endif /* SQLITE_OMIT_VACUUM && SQLITE_OMIT_ATTACH */ -#endif /* SQLITE_OMIT_VACUUM */ ============================================================ --- sqlite/vdbe.c b5a2ad31c177b6c2d5fedb2ed180b9b57058398b +++ sqlite/vdbe.c 87e31f0790ac8a5aad7b7fcd5b97948943fccba3 @@ -43,7 +43,7 @@ ** 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.588 2007/01/27 13:37:22 drh Exp $ +** $Id: vdbe.c,v 1.598 2007/03/30 18:42:56 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -211,7 +211,7 @@ static void applyNumericAffinity(Mem *pR sqlite3VdbeChangeEncoding(pRec, SQLITE_UTF8); if( !realnum && sqlite3atoi64(pRec->z, &value) ){ sqlite3VdbeMemRelease(pRec); - pRec->i = value; + pRec->u.i = value; pRec->flags = MEM_Int; }else{ sqlite3VdbeMemRealify(pRec); @@ -454,6 +454,7 @@ int sqlite3VdbeExec( p->resOnStack = 0; db->busyHandler.nBusy = 0; CHECK_FOR_INTERRUPT; + sqlite3VdbeIOTraceSql(p); #ifdef SQLITE_DEBUG if( (p->db->flags & SQLITE_VdbeListing)!=0 || sqlite3OsFileExists("vdbe_explain") @@ -669,7 +670,7 @@ case OP_Integer: { case OP_Integer: { pTos++; pTos->flags = MEM_Int; - pTos->i = pOp->p1; + pTos->u.i = pOp->p1; break; } @@ -685,7 +686,7 @@ case OP_Int64: { pTos->z = pOp->p3; pTos->n = strlen(pTos->z); pTos->enc = SQLITE_UTF8; - pTos->i = sqlite3VdbeIntValue(pTos); + pTos->u.i = sqlite3VdbeIntValue(pTos); pTos->flags |= MEM_Int; break; } @@ -1098,8 +1099,8 @@ case OP_Remainder: { /* same a pTos->flags = MEM_Null; }else if( (pTos->flags & pNos->flags & MEM_Int)==MEM_Int ){ i64 a, b; - a = pTos->i; - b = pNos->i; + a = pTos->u.i; + b = pNos->u.i; switch( pOp->opcode ){ case OP_Add: b += a; break; case OP_Subtract: b -= a; break; @@ -1118,7 +1119,7 @@ case OP_Remainder: { /* same a Release(pTos); pTos--; Release(pTos); - pTos->i = b; + pTos->u.i = b; pTos->flags = MEM_Int; }else{ double a, b; @@ -1309,7 +1310,7 @@ case OP_ShiftRight: { /* same Release(pTos); pTos--; Release(pTos); - pTos->i = a; + pTos->u.i = a; pTos->flags = MEM_Int; break; } @@ -1324,7 +1325,7 @@ case OP_AddImm: { /* no-push case OP_AddImm: { /* no-push */ assert( pTos>=p->aStack ); sqlite3VdbeMemIntegerify(pTos); - pTos->i += pOp->p1; + pTos->u.i += pOp->p1; break; } @@ -1349,7 +1350,7 @@ case OP_ForceInt: { /* no-pus break; } if( pTos->flags & MEM_Int ){ - v = pTos->i + (pOp->p1!=0); + v = pTos->u.i + (pOp->p1!=0); }else{ /* FIX ME: should this not be assert( pTos->flags & MEM_Real ) ??? */ sqlite3VdbeMemRealify(pTos); @@ -1358,7 +1359,7 @@ case OP_ForceInt: { /* no-pus if( pOp->p1 && pTos->r==(double)v ) v++; } Release(pTos); - pTos->i = v; + pTos->u.i = v; pTos->flags = MEM_Int; break; } @@ -1647,7 +1648,7 @@ case OP_Ge: { /* same as TK_ }else{ pTos++; pTos->flags = MEM_Int; - pTos->i = res; + pTos->u.i = res; } break; } @@ -1674,13 +1675,13 @@ case OP_Or: { /* same as TK_ v1 = 2; }else{ sqlite3VdbeMemIntegerify(pTos); - v1 = pTos->i==0; + v1 = pTos->u.i==0; } if( pNos->flags & MEM_Null ){ v2 = 2; }else{ sqlite3VdbeMemIntegerify(pNos); - v2 = pNos->i==0; + v2 = pNos->u.i==0; } if( pOp->opcode==OP_And ){ static const unsigned char and_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 }; @@ -1694,7 +1695,7 @@ case OP_Or: { /* same as TK_ if( v1==2 ){ pTos->flags = MEM_Null; }else{ - pTos->i = v1==0; + pTos->u.i = v1==0; pTos->flags = MEM_Int; } break; @@ -1724,8 +1725,8 @@ case OP_AbsValue: { pTos->flags = MEM_Real; }else if( pTos->flags & MEM_Int ){ Release(pTos); - if( pOp->opcode==OP_Negative || pTos->i<0 ){ - pTos->i = -pTos->i; + if( pOp->opcode==OP_Negative || pTos->u.i<0 ){ + pTos->u.i = -pTos->u.i; } pTos->flags = MEM_Int; }else if( pTos->flags & MEM_Null ){ @@ -1748,7 +1749,7 @@ case OP_Not: { /* same as if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */ sqlite3VdbeMemIntegerify(pTos); assert( (pTos->flags & MEM_Dyn)==0 ); - pTos->i = !pTos->i; + pTos->u.i = !pTos->u.i; pTos->flags = MEM_Int; break; } @@ -1764,7 +1765,7 @@ case OP_BitNot: { /* same as if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */ sqlite3VdbeMemIntegerify(pTos); assert( (pTos->flags & MEM_Dyn)==0 ); - pTos->i = ~pTos->i; + pTos->u.i = ~pTos->u.i; pTos->flags = MEM_Int; break; } @@ -1936,6 +1937,9 @@ case OP_Column: { ** which is the number of records. */ pC = p->apCsr[p1]; +#ifndef SQLITE_OMIT_VIRTUALTABLE + assert( pC->pVtabCursor==0 ); +#endif assert( pC!=0 ); if( pC->pCursor!=0 ){ /* The record is stored in a B-Tree */ @@ -2445,7 +2449,7 @@ case OP_ReadCookie: { */ rc = sqlite3BtreeGetMeta(db->aDb[pOp->p1].pBt, 1 + pOp->p2, (u32 *)&iMeta); pTos++; - pTos->i = iMeta; + pTos->u.i = iMeta; pTos->flags = MEM_Int; break; } @@ -2469,14 +2473,14 @@ case OP_SetCookie: { /* no-push */ assert( pTos>=p->aStack ); sqlite3VdbeMemIntegerify(pTos); /* See note about index shifting on OP_ReadCookie */ - rc = sqlite3BtreeUpdateMeta(pDb->pBt, 1+pOp->p2, (int)pTos->i); + rc = sqlite3BtreeUpdateMeta(pDb->pBt, 1+pOp->p2, (int)pTos->u.i); if( pOp->p2==0 ){ /* When the schema cookie changes, record the new cookie internally */ - pDb->pSchema->schema_cookie = pTos->i; + pDb->pSchema->schema_cookie = pTos->u.i; db->flags |= SQLITE_InternChanges; }else if( pOp->p2==1 ){ /* Record changes in the file format */ - pDb->pSchema->file_format = pTos->i; + pDb->pSchema->file_format = pTos->u.i; } assert( (pTos->flags & MEM_Dyn)==0 ); pTos--; @@ -2578,7 +2582,7 @@ case OP_OpenWrite: { /* no-push */ assert( pTos>=p->aStack ); sqlite3VdbeMemIntegerify(pTos); - iDb = pTos->i; + iDb = pTos->u.i; assert( (pTos->flags & MEM_Dyn)==0 ); pTos--; assert( iDb>=0 && iDbnDb ); @@ -2596,7 +2600,7 @@ case OP_OpenWrite: { /* no-push */ if( p2<=0 ){ assert( pTos>=p->aStack ); sqlite3VdbeMemIntegerify(pTos); - p2 = pTos->i; + p2 = pTos->u.i; assert( (pTos->flags & MEM_Dyn)==0 ); pTos--; assert( p2>=2 ); @@ -2822,7 +2826,7 @@ case OP_MoveGt: { /* no-push */ if( pC->isTable ){ i64 iKey; sqlite3VdbeMemIntegerify(pTos); - iKey = intToKey(pTos->i); + iKey = intToKey(pTos->u.i); if( pOp->p2==0 && pOp->opcode==OP_MoveGe ){ pC->movetoTarget = iKey; pC->deferredMoveto = 1; @@ -2830,16 +2834,16 @@ case OP_MoveGt: { /* no-push */ pTos--; break; } - rc = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, &res); + rc = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } - pC->lastRowid = pTos->i; + pC->lastRowid = pTos->u.i; pC->rowidIsValid = res==0; }else{ assert( pTos->flags & MEM_Blob ); /* Stringify(pTos, encoding); */ - rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res); + rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } @@ -2946,7 +2950,7 @@ case OP_Found: { /* no-push */ int res, rx; assert( pC->isTable==0 ); Stringify(pTos, encoding); - rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res); + rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, 0, &res); alreadyExists = rx==SQLITE_OK && res==0; pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; @@ -2995,7 +2999,7 @@ case OP_IsUnique: { /* no-push */ */ assert( pNos>=p->aStack ); sqlite3VdbeMemIntegerify(pTos); - R = pTos->i; + R = pTos->u.i; assert( (pTos->flags & MEM_Dyn)==0 ); pTos--; assert( i>=0 && inCursor ); @@ -3024,7 +3028,7 @@ case OP_IsUnique: { /* no-push */ */ assert( pCx->deferredMoveto==0 ); pCx->cacheStatus = CACHE_STALE; - rc = sqlite3BtreeMoveto(pCrsr, zKey, len, &res); + rc = sqlite3BtreeMoveto(pCrsr, zKey, len, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } @@ -3061,7 +3065,7 @@ case OP_IsUnique: { /* no-push */ ** constraint.) */ pTos++; - pTos->i = v; + pTos->u.i = v; pTos->flags = MEM_Int; } break; @@ -3093,15 +3097,17 @@ case OP_NotExists: { /* no-push * u64 iKey; assert( pTos->flags & MEM_Int ); assert( p->apCsr[i]->isTable ); - iKey = intToKey(pTos->i); - rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res); - pC->lastRowid = pTos->i; + iKey = intToKey(pTos->u.i); + rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, 0,&res); + pC->lastRowid = pTos->u.i; pC->rowidIsValid = res==0; pC->nullRow = 0; pC->cacheStatus = CACHE_STALE; /* res might be uninitialized if rc!=SQLITE_OK. But if rc!=SQLITE_OK ** processing is about to abort so we really do not care whether or not - ** the following jump is taken. */ + ** the following jump is taken. (In other words, do not stress over + ** the error that valgrind sometimes shows on the next statement when + ** running ioerr.test and similar failure-recovery test scripts.) */ if( res!=0 ){ pc = pOp->p2 - 1; pC->rowidIsValid = 0; @@ -3124,7 +3130,7 @@ case OP_Sequence: { assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); pTos++; - pTos->i = p->apCsr[i]->seqCount++; + pTos->u.i = p->apCsr[i]->seqCount++; pTos->flags = MEM_Int; break; } @@ -3233,14 +3239,14 @@ case OP_NewRowid: { pMem = &p->aMem[pOp->p2]; sqlite3VdbeMemIntegerify(pMem); assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P2) holds an integer */ - if( pMem->i==MAX_ROWID || pC->useRandomRowid ){ + if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ rc = SQLITE_FULL; goto abort_due_to_error; } - if( vi+1 ){ - v = pMem->i + 1; + if( vu.i+1 ){ + v = pMem->u.i + 1; } - pMem->i = v; + pMem->u.i = v; } #endif @@ -3266,7 +3272,7 @@ case OP_NewRowid: { } if( v==0 ) continue; x = intToKey(v); - rx = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)x, &res); + rx = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)x, 0, &res); cnt++; }while( cnt<1000 && rx==SQLITE_OK && res==0 ); db->priorNewRowid = v; @@ -3280,7 +3286,7 @@ case OP_NewRowid: { pC->cacheStatus = CACHE_STALE; } pTos++; - pTos->i = v; + pTos->u.i = v; pTos->flags = MEM_Int; break; } @@ -3317,11 +3323,11 @@ case OP_Insert: { /* no-push */ assert( pNos->flags & MEM_Int ); assert( pC->isTable ); - iKey = intToKey(pNos->i); + iKey = intToKey(pNos->u.i); if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++; - if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->i; - if( pC->nextRowidValid && pNos->i>=pC->nextRowid ){ + if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->u.i; + if( pC->nextRowidValid && pNos->u.i>=pC->nextRowid ){ pC->nextRowidValid = 0; } if( pTos->flags & MEM_Null ){ @@ -3346,7 +3352,9 @@ case OP_Insert: { /* no-push */ } pC->nullRow = 0; }else{ - rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey, pTos->z, pTos->n); + rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey, + pTos->z, pTos->n, + pOp->p2 & OPFLAG_APPEND); } pC->rowidIsValid = 0; @@ -3500,9 +3508,9 @@ case OP_RowData: { pTos->z = z; } if( pC->isIndex ){ - sqlite3BtreeKey(pCrsr, 0, n, pTos->z); + rc = sqlite3BtreeKey(pCrsr, 0, n, pTos->z); }else{ - sqlite3BtreeData(pCrsr, 0, n, pTos->z); + rc = sqlite3BtreeData(pCrsr, 0, n, pTos->z); } }else if( pC->pseudoTable ){ pTos->n = pC->nData; @@ -3543,7 +3551,7 @@ case OP_Rowid: { sqlite3BtreeKeySize(pC->pCursor, &v); v = keyToInt(v); } - pTos->i = v; + pTos->u.i = v; pTos->flags = MEM_Int; break; } @@ -3673,7 +3681,9 @@ case OP_Next: { /* no-push */ CHECK_FOR_INTERRUPT; assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); + if( pC==0 ){ + break; /* See ticket #2273 */ + } if( (pCrsr = pC->pCursor)!=0 ){ int res; if( pC->nullRow ){ @@ -3698,12 +3708,15 @@ case OP_Next: { /* no-push */ break; } -/* Opcode: IdxInsert P1 * * +/* Opcode: IdxInsert P1 P2 * ** ** The top of the stack holds a SQL index key made using either the ** MakeIdxRec or MakeRecord instructions. This opcode writes that key ** into the index P1. Data for the entry is nil. ** +** P2 is a flag that provides a hint to the b-tree layer that this +** insert is likely to be an append. +** ** This instruction only works for indices. The equivalent instruction ** for tables is OP_Insert. */ @@ -3715,12 +3728,11 @@ case OP_IdxInsert: { /* no-push * assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); assert( pTos->flags & MEM_Blob ); - assert( pOp->p2==0 ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int nKey = pTos->n; const char *zKey = pTos->z; assert( pC->isTable==0 ); - rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0); + rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, pOp->p2); assert( pC->deferredMoveto==0 ); pC->cacheStatus = CACHE_STALE; } @@ -3745,7 +3757,7 @@ case OP_IdxDelete: { /* no-push * assert( p->apCsr[i]!=0 ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int res; - rc = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, &res); + rc = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, 0, &res); if( rc==SQLITE_OK && res==0 ){ rc = sqlite3BtreeDelete(pCrsr); } @@ -3787,7 +3799,7 @@ case OP_IdxRowid: { goto abort_due_to_error; } pTos->flags = MEM_Int; - pTos->i = rowid; + pTos->u.i = rowid; } } break; @@ -3914,7 +3926,7 @@ case OP_Destroy: { rc = sqlite3BtreeDropTable(db->aDb[pOp->p2].pBt, pOp->p1, &iMoved); pTos++; pTos->flags = MEM_Int; - pTos->i = iMoved; + pTos->u.i = iMoved; #ifndef SQLITE_OMIT_AUTOVACUUM if( rc==SQLITE_OK && iMoved!=0 ){ sqlite3RootPageMoved(&db->aDb[pOp->p2], iMoved, pOp->p1); @@ -4013,7 +4025,7 @@ case OP_CreateTable: { rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags); pTos++; if( rc==SQLITE_OK ){ - pTos->i = pgno; + pTos->u.i = pgno; pTos->flags = MEM_Int; }else{ pTos->flags = MEM_Null; @@ -4160,14 +4172,14 @@ case OP_IntegrityCk: { assert( (pnErr->flags & MEM_Int)!=0 ); for(j=0; ji; + aRoot[j] = pMem->u.i; } aRoot[j] = 0; popStack(&pTos, nRoot); pTos++; z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p2].pBt, aRoot, nRoot, - pnErr->i, &nErr); - pnErr->i -= nErr; + pnErr->u.i, &nErr); + pnErr->u.i -= nErr; if( nErr==0 ){ assert( z==0 ); pTos->flags = MEM_Null; @@ -4192,7 +4204,7 @@ case OP_FifoWrite: { /* no-push * case OP_FifoWrite: { /* no-push */ assert( pTos>=p->aStack ); sqlite3VdbeMemIntegerify(pTos); - sqlite3VdbeFifoPush(&p->sFifo, pTos->i); + sqlite3VdbeFifoPush(&p->sFifo, pTos->u.i); assert( (pTos->flags & MEM_Dyn)==0 ); pTos--; break; @@ -4211,7 +4223,7 @@ case OP_FifoRead: { pc = pOp->p2 - 1; }else{ pTos++; - pTos->i = v; + pTos->u.i = v; pTos->flags = MEM_Int; } break; @@ -4232,7 +4244,8 @@ case OP_ContextPush: { /* no-push /* FIX ME: This should be allocated as part of the vdbe at compile-time */ if( i>=p->contextStackDepth ){ p->contextStackDepth = i+1; - sqliteReallocOrFree((void**)&p->contextStack, sizeof(Context)*(i+1)); + p->contextStack = sqliteReallocOrFree(p->contextStack, + sizeof(Context)*(i+1)); if( p->contextStack==0 ) goto no_mem; } pContext = &p->contextStack[i]; @@ -4317,8 +4330,8 @@ case OP_MemMax: { /* no-push */ pMem = &p->aMem[i]; sqlite3VdbeMemIntegerify(pMem); sqlite3VdbeMemIntegerify(pTos); - if( pMem->ii){ - pMem->i = pTos->i; + if( pMem->u.iu.i){ + pMem->u.i = pTos->u.i; } break; } @@ -4337,7 +4350,7 @@ case OP_MemIncr: { /* no-push */ assert( i>=0 && inMem ); pMem = &p->aMem[i]; assert( pMem->flags==MEM_Int ); - pMem->i += pOp->p1; + pMem->u.i += pOp->p1; break; } @@ -4354,7 +4367,7 @@ case OP_IfMemPos: { /* no-push */ assert( i>=0 && inMem ); pMem = &p->aMem[i]; assert( pMem->flags==MEM_Int ); - if( pMem->i>0 ){ + if( pMem->u.i>0 ){ pc = pOp->p2 - 1; } break; @@ -4373,7 +4386,7 @@ case OP_IfMemNeg: { /* no-push */ assert( i>=0 && inMem ); pMem = &p->aMem[i]; assert( pMem->flags==MEM_Int ); - if( pMem->i<0 ){ + if( pMem->u.i<0 ){ pc = pOp->p2 - 1; } break; @@ -4392,7 +4405,7 @@ case OP_IfMemZero: { /* no-push * assert( i>=0 && inMem ); pMem = &p->aMem[i]; assert( pMem->flags==MEM_Int ); - if( pMem->i==0 ){ + if( pMem->u.i==0 ){ pc = pOp->p2 - 1; } break; @@ -4506,7 +4519,7 @@ case OP_AggFinal: { /* no-push */ } -#ifndef SQLITE_OMIT_VACUUM +#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) /* Opcode: Vacuum * * * ** ** Vacuum the entire database. This opcode will cause other virtual @@ -4679,7 +4692,7 @@ case OP_VFilter: { /* no-push */ /* Grab the index number and argc parameters off the top of the stack. */ assert( (&pTos[-1])>=p->aStack ); assert( (pTos[0].flags&MEM_Int)!=0 && pTos[-1].flags==MEM_Int ); - nArg = pTos[-1].i; + nArg = pTos[-1].u.i; /* Invoke the xFilter method */ { @@ -4693,7 +4706,7 @@ case OP_VFilter: { /* no-push */ if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; p->inVtabMethod = 1; - rc = pModule->xFilter(pCur->pVtabCursor, pTos->i, pOp->p3, nArg, apArg); + rc = pModule->xFilter(pCur->pVtabCursor, pTos->u.i, pOp->p3, nArg, apArg); p->inVtabMethod = 0; if( rc==SQLITE_OK ){ res = pModule->xEof(pCur->pVtabCursor); @@ -4735,7 +4748,7 @@ case OP_VRowid: { pTos++; pTos->flags = MEM_Int; - pTos->i = iRow; + pTos->u.i = iRow; } break; @@ -4934,9 +4947,9 @@ default: { if( pTos[i].flags & MEM_Null ){ fprintf(p->trace, " NULL"); }else if( (pTos[i].flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ - fprintf(p->trace, " si:%lld", pTos[i].i); + fprintf(p->trace, " si:%lld", pTos[i].u.i); }else if( pTos[i].flags & MEM_Int ){ - fprintf(p->trace, " i:%lld", pTos[i].i); + fprintf(p->trace, " i:%lld", pTos[i].u.i); }else if( pTos[i].flags & MEM_Real ){ fprintf(p->trace, " r:%g", pTos[i].r); }else{ ============================================================ --- sqlite/vdbeInt.h 13ba07121cf534d5b80130d2f5eb0a4937a36bba +++ sqlite/vdbeInt.h 4b19fd8febad3fd14c4c97adaefc06754d323132 @@ -31,7 +31,7 @@ ** array is defined in a separate source code file named opcode.c which is ** automatically generated by the makefile. */ -extern char *sqlite3OpcodeNames[]; +extern const char *const sqlite3OpcodeNames[]; /* ** SQL is translated into a sequence of instructions to be @@ -125,7 +125,10 @@ struct Mem { ** SQLITE_BLOB. */ struct Mem { - i64 i; /* Integer value. Or FuncDef* when flags==MEM_Agg */ + union { + i64 i; /* Integer value. Or FuncDef* when flags==MEM_Agg */ + FuncDef *pDef; /* Used only when flags==MEM_Agg */ + } u; double r; /* Real value */ char *z; /* String or BLOB value */ int n; /* Number of characters in string value, including '\0' */ ============================================================ --- sqlite/vdbeapi.c 2d1e6843af8705a1172e54a418d2a3d5febd1dd7 +++ sqlite/vdbeapi.c 1fca7ff056d03f131caa6b1296bb221da65ed7f4 @@ -341,7 +341,7 @@ void *sqlite3_aggregate_context(sqlite3_ }else{ pMem->flags = MEM_Agg; pMem->xDel = sqlite3FreeX; - *(FuncDef**)&pMem->i = p->pFunc; + pMem->u.pDef = p->pFunc; if( nByte<=NBFS ){ pMem->z = pMem->zShort; memset(pMem->z, 0, nByte); @@ -443,7 +443,7 @@ static Mem *columnMem(sqlite3_stmt *pStm Vdbe *pVm = (Vdbe *)pStmt; int vals = sqlite3_data_count(pStmt); if( i>=vals || i<0 ){ - static const Mem nullMem = {0, 0.0, "", 0, MEM_Null, MEM_Null }; + static const Mem nullMem = {{0}, 0.0, "", 0, MEM_Null, MEM_Null }; sqlite3Error(pVm->db, SQLITE_RANGE, 0); return (Mem*)&nullMem; } ============================================================ --- sqlite/vdbeaux.c c5324d62f51529bccc5be3b04bac2e4eeae1569a +++ sqlite/vdbeaux.c 0bae26de1ba1683de80c89ba1d4081b4c809d05b @@ -195,8 +195,8 @@ int sqlite3VdbeMakeLabel(Vdbe *p){ assert( p->magic==VDBE_MAGIC_INIT ); if( i>=p->nLabelAlloc ){ p->nLabelAlloc = p->nLabelAlloc*2 + 10; - sqliteReallocOrFree((void**)&p->aLabel, - p->nLabelAlloc*sizeof(p->aLabel[0])); + p->aLabel = sqliteReallocOrFree(p->aLabel, + p->nLabelAlloc*sizeof(p->aLabel[0])); } if( p->aLabel ){ p->aLabel[i] = -1; @@ -719,11 +719,11 @@ int sqlite3VdbeList( Mem *pMem = p->aStack; pMem->flags = MEM_Int; pMem->type = SQLITE_INTEGER; - pMem->i = i; /* Program counter */ + pMem->u.i = i; /* Program counter */ pMem++; pMem->flags = MEM_Static|MEM_Str|MEM_Term; - pMem->z = sqlite3OpcodeNames[pOp->opcode]; /* Opcode */ + pMem->z = (char*)sqlite3OpcodeNames[pOp->opcode]; /* Opcode */ assert( pMem->z!=0 ); pMem->n = strlen(pMem->z); pMem->type = SQLITE_TEXT; @@ -731,12 +731,12 @@ int sqlite3VdbeList( pMem++; pMem->flags = MEM_Int; - pMem->i = pOp->p1; /* P1 */ + pMem->u.i = pOp->p1; /* P1 */ pMem->type = SQLITE_INTEGER; pMem++; pMem->flags = MEM_Int; - pMem->i = pOp->p2; /* P2 */ + pMem->u.i = pOp->p2; /* P2 */ pMem->type = SQLITE_INTEGER; pMem++; @@ -757,11 +757,11 @@ int sqlite3VdbeList( } #endif /* SQLITE_OMIT_EXPLAIN */ +#ifdef SQLITE_DEBUG /* ** Print the SQL that was used to generate a VDBE program. */ void sqlite3VdbePrintSql(Vdbe *p){ -#ifdef SQLITE_DEBUG int nOp = p->nOp; VdbeOp *pOp; if( nOp<1 ) return; @@ -771,9 +771,40 @@ void sqlite3VdbePrintSql(Vdbe *p){ while( isspace(*(u8*)z) ) z++; printf("SQL: [%s]\n", z); } +} #endif + +#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) +/* +** Print an IOTRACE message showing SQL content. +*/ +void sqlite3VdbeIOTraceSql(Vdbe *p){ + int nOp = p->nOp; + VdbeOp *pOp; + if( sqlite3_io_trace==0 ) return; + if( nOp<1 ) return; + pOp = &p->aOp[nOp-1]; + if( pOp->opcode==OP_Noop && pOp->p3!=0 ){ + char *z = sqlite3StrDup(pOp->p3); + int i, j; + for(i=0; isspace(z[i]); i++){} + for(j=0; z[i]; i++){ + if( isspace(z[i]) ){ + if( z[i-1]!=' ' ){ + z[j++] = ' '; + } + }else{ + z[j++] = z[i]; + } + } + z[j] = 0; + sqlite3_io_trace("SQL %s\n", z); + sqliteFree(z); + } } +#endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */ + /* ** Prepare a virtual machine for execution. This involves things such ** as allocating stack space and initializing the program counter. @@ -1059,18 +1090,22 @@ static int vdbeCommit(sqlite3 *db){ for(i=0; rc==SQLITE_OK && inDb; i++){ Btree *pBt = db->aDb[i].pBt; if( pBt ){ - rc = sqlite3BtreeSync(pBt, 0); + rc = sqlite3BtreeCommitPhaseOne(pBt, 0); } } - /* Do the commit only if all databases successfully synced */ - if( rc==SQLITE_OK ){ - for(i=0; inDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - sqlite3BtreeCommit(pBt); - } + /* Do the commit only if all databases successfully complete phase 1. + ** If one of the BtreeCommitPhaseOne() calls fails, this indicates an + ** IO error while deleting or truncating a journal file. It is unlikely, + ** but could happen. In this case abandon processing and return the error. + */ + for(i=0; rc==SQLITE_OK && inDb; i++){ + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + rc = sqlite3BtreeCommitPhaseTwo(pBt); } + } + if( rc==SQLITE_OK ){ sqlite3VtabCommit(db); } } @@ -1147,16 +1182,16 @@ static int vdbeCommit(sqlite3 *db){ ** sets the master journal pointer in each individual journal. If ** an error occurs here, do not delete the master journal file. ** - ** If the error occurs during the first call to sqlite3BtreeSync(), - ** then there is a chance that the master journal file will be - ** orphaned. But we cannot delete it, in case the master journal - ** file name was written into the journal file before the failure - ** occured. + ** If the error occurs during the first call to + ** sqlite3BtreeCommitPhaseOne(), then there is a chance that the + ** master journal file will be orphaned. But we cannot delete it, + ** in case the master journal file name was written into the journal + ** file before the failure occured. */ for(i=0; rc==SQLITE_OK && inDb; i++){ Btree *pBt = db->aDb[i].pBt; if( pBt && sqlite3BtreeIsInTrans(pBt) ){ - rc = sqlite3BtreeSync(pBt, zMaster); + rc = sqlite3BtreeCommitPhaseOne(pBt, zMaster); } } sqlite3OsClose(&master); @@ -1170,11 +1205,11 @@ static int vdbeCommit(sqlite3 *db){ ** transaction files are deleted. */ rc = sqlite3OsDelete(zMaster); + sqliteFree(zMaster); + zMaster = 0; if( rc ){ return rc; } - sqliteFree(zMaster); - zMaster = 0; rc = sqlite3OsSyncDirectory(zMainFile); if( rc!=SQLITE_OK ){ /* This is not good. The master journal file has been deleted, but @@ -1188,18 +1223,21 @@ static int vdbeCommit(sqlite3 *db){ } /* All files and directories have already been synced, so the following - ** calls to sqlite3BtreeCommit() are only closing files and deleting - ** journals. If something goes wrong while this is happening we don't - ** really care. The integrity of the transaction is already guaranteed, - ** but some stray 'cold' journals may be lying around. Returning an - ** error code won't help matters. + ** calls to sqlite3BtreeCommitPhaseTwo() are only closing files and + ** deleting or truncating journals. If something goes wrong while + ** this is happening we don't really care. The integrity of the + ** transaction is already guaranteed, but some stray 'cold' journals + ** may be lying around. Returning an error code won't help matters. */ + disable_simulated_io_errors(); for(i=0; inDb; i++){ Btree *pBt = db->aDb[i].pBt; if( pBt ){ - sqlite3BtreeCommit(pBt); + sqlite3BtreeCommitPhaseTwo(pBt); } } + enable_simulated_io_errors(); + sqlite3VtabCommit(db); } #endif @@ -1470,10 +1508,6 @@ int sqlite3VdbeReset(Vdbe *p){ */ int sqlite3VdbeReset(Vdbe *p){ sqlite3 *db; - if( p->magic!=VDBE_MAGIC_RUN && p->magic!=VDBE_MAGIC_HALT ){ - sqlite3Error(p->db, SQLITE_MISUSE, 0); - return SQLITE_MISUSE; - } db = p->db; /* If the VM did not run to completion or if it encountered an @@ -1624,12 +1658,7 @@ int sqlite3VdbeCursorMoveto(Cursor *p){ extern int sqlite3_search_count; #endif assert( p->isTable ); - if( p->isTable ){ - rc = sqlite3BtreeMoveto(p->pCursor, 0, p->movetoTarget, &res); - }else{ - rc = sqlite3BtreeMoveto(p->pCursor,(char*)&p->movetoTarget, - sizeof(i64),&res); - } + rc = sqlite3BtreeMoveto(p->pCursor, 0, p->movetoTarget, 0, &res); if( rc ) return rc; *p->pIncrKey = 0; p->lastRowid = keyToInt(p->movetoTarget); @@ -1701,7 +1730,7 @@ u32 sqlite3VdbeSerialType(Mem *pMem, int if( flags&MEM_Int ){ /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */ # define MAX_6BYTE ((((i64)0x00001000)<<32)-1) - i64 i = pMem->i; + i64 i = pMem->u.i; u64 u; if( file_format>=4 && (i&1)==i ){ return 8+i; @@ -1722,10 +1751,8 @@ u32 sqlite3VdbeSerialType(Mem *pMem, int assert( n>=0 ); return ((n*2) + 13); } - if( flags&MEM_Blob ){ - return (pMem->n*2 + 12); - } - return 0; + assert( (flags & MEM_Blob)!=0 ); + return (pMem->n*2 + 12); } /* @@ -1754,9 +1781,10 @@ int sqlite3VdbeSerialPut(unsigned char * u64 v; int i; if( serial_type==7 ){ - v = *(u64*)&pMem->r; + assert( sizeof(v)==sizeof(pMem->r) ); + memcpy(&v, &pMem->r, sizeof(v)); }else{ - v = *(u64*)&pMem->i; + v = pMem->u.i; } len = i = sqlite3VdbeSerialTypeLen(serial_type); while( i-- ){ @@ -1794,22 +1822,22 @@ int sqlite3VdbeSerialGet( break; } case 1: { /* 1-byte signed integer */ - pMem->i = (signed char)buf[0]; + pMem->u.i = (signed char)buf[0]; pMem->flags = MEM_Int; return 1; } case 2: { /* 2-byte signed integer */ - pMem->i = (((signed char)buf[0])<<8) | buf[1]; + pMem->u.i = (((signed char)buf[0])<<8) | buf[1]; pMem->flags = MEM_Int; return 2; } case 3: { /* 3-byte signed integer */ - pMem->i = (((signed char)buf[0])<<16) | (buf[1]<<8) | buf[2]; + pMem->u.i = (((signed char)buf[0])<<16) | (buf[1]<<8) | buf[2]; pMem->flags = MEM_Int; return 3; } case 4: { /* 4-byte signed integer */ - pMem->i = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; + pMem->u.i = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; pMem->flags = MEM_Int; return 4; } @@ -1817,7 +1845,7 @@ int sqlite3VdbeSerialGet( u64 x = (((signed char)buf[0])<<8) | buf[1]; u32 y = (buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5]; x = (x<<32) | y; - pMem->i = *(i64*)&x; + pMem->u.i = *(i64*)&x; pMem->flags = MEM_Int; return 6; } @@ -1830,24 +1858,27 @@ int sqlite3VdbeSerialGet( ** byte order. The byte order differs on some (broken) architectures. */ static const u64 t1 = ((u64)0x3ff00000)<<32; - assert( 1.0==*(double*)&t1 ); + static const double r1 = 1.0; + assert( sizeof(r1)==sizeof(t1) && memcmp(&r1, &t1, sizeof(r1))==0 ); #endif x = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; y = (buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7]; x = (x<<32) | y; if( serial_type==6 ){ - pMem->i = *(i64*)&x; + pMem->u.i = *(i64*)&x; pMem->flags = MEM_Int; }else{ - pMem->r = *(double*)&x; + assert( sizeof(x)==8 && sizeof(pMem->r)==8 ); + memcpy(&pMem->r, &x, sizeof(x)); + /* pMem->r = *(double*)&x; */ pMem->flags = MEM_Real; } return 8; } case 8: /* Integer 0 */ case 9: { /* Integer 1 */ - pMem->i = serial_type-8; + pMem->u.i = serial_type-8; pMem->flags = MEM_Int; return 0; } @@ -1984,7 +2015,7 @@ int sqlite3VdbeIdxRowid(BtCursor *pCur, ** Return SQLITE_OK if everything works, or an error code otherwise. */ int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){ - i64 nCellKey; + i64 nCellKey = 0; int rc; u32 szHdr; /* Size of the header */ u32 typeRowid; /* Serial type of the rowid */ @@ -2003,7 +2034,7 @@ int sqlite3VdbeIdxRowid(BtCursor *pCur, sqlite3GetVarint32((u8*)&m.z[szHdr-1], &typeRowid); lenRowid = sqlite3VdbeSerialTypeLen(typeRowid); sqlite3VdbeSerialGet((u8*)&m.z[m.n-lenRowid], typeRowid, &v); - *rowid = v.i; + *rowid = v.u.i; sqlite3VdbeMemRelease(&m); return SQLITE_OK; } @@ -2023,7 +2054,7 @@ int sqlite3VdbeIdxKeyCompare( int nKey, const u8 *pKey, /* The key to compare */ int *res /* Write the comparison result here */ ){ - i64 nCellKey; + i64 nCellKey = 0; int rc; BtCursor *pCur = pC->pCursor; int lenRowid; ============================================================ --- sqlite/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5 +++ sqlite/vdbefifo.c 3ca8049c561d5d67cbcb94dc909ae9bb68c0bf8f @@ -19,7 +19,7 @@ ** Allocate a new FifoPage and return a pointer to it. Return NULL if ** we run out of memory. Leave space on the page for nEntry entries. */ -static FifoPage *allocatePage(int nEntry){ +static FifoPage *allocateFifoPage(int nEntry){ FifoPage *pPage; if( nEntry>32767 ){ nEntry = 32767; @@ -50,12 +50,12 @@ int sqlite3VdbeFifoPush(Fifo *pFifo, i64 FifoPage *pPage; pPage = pFifo->pLast; if( pPage==0 ){ - pPage = pFifo->pLast = pFifo->pFirst = allocatePage(20); + pPage = pFifo->pLast = pFifo->pFirst = allocateFifoPage(20); if( pPage==0 ){ return SQLITE_NOMEM; } }else if( pPage->iWrite>=pPage->nSlot ){ - pPage->pNext = allocatePage(pFifo->nEntry); + pPage->pNext = allocateFifoPage(pFifo->nEntry); if( pPage->pNext==0 ){ return SQLITE_NOMEM; } ============================================================ --- sqlite/vdbemem.c ff2424bee9eaf7c61d1f28bc0e711bebddebd653 +++ sqlite/vdbemem.c 981a113405bd9b80aeb71fe246a2f01708e8a8f7 @@ -170,7 +170,7 @@ int sqlite3VdbeMemStringify(Mem *pMem, i ** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16. */ if( fg & MEM_Int ){ - sqlite3_snprintf(NBFS, z, "%lld", pMem->i); + sqlite3_snprintf(NBFS, z, "%lld", pMem->u.i); }else{ assert( fg & MEM_Real ); sqlite3_snprintf(NBFS, z, "%!.15g", pMem->r); @@ -195,7 +195,7 @@ int sqlite3VdbeMemFinalize(Mem *pMem, Fu int rc = SQLITE_OK; if( pFunc && pFunc->xFinalize ){ sqlite3_context ctx; - assert( (pMem->flags & MEM_Null)!=0 || pFunc==*(FuncDef**)&pMem->i ); + assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef ); ctx.s.flags = MEM_Null; ctx.s.z = pMem->zShort; ctx.pMem = pMem; @@ -225,7 +225,7 @@ void sqlite3VdbeMemRelease(Mem *p){ if( p->flags & (MEM_Dyn|MEM_Agg) ){ if( p->xDel ){ if( p->flags & MEM_Agg ){ - sqlite3VdbeMemFinalize(p, *(FuncDef**)&p->i); + sqlite3VdbeMemFinalize(p, p->u.pDef); assert( (p->flags & MEM_Agg)==0 ); sqlite3VdbeMemRelease(p); }else{ @@ -252,7 +252,7 @@ i64 sqlite3VdbeIntValue(Mem *pMem){ i64 sqlite3VdbeIntValue(Mem *pMem){ int flags = pMem->flags; if( flags & MEM_Int ){ - return pMem->i; + return pMem->u.i; }else if( flags & MEM_Real ){ return (i64)pMem->r; }else if( flags & (MEM_Str|MEM_Blob) ){ @@ -279,7 +279,7 @@ double sqlite3VdbeRealValue(Mem *pMem){ if( pMem->flags & MEM_Real ){ return pMem->r; }else if( pMem->flags & MEM_Int ){ - return (double)pMem->i; + return (double)pMem->u.i; }else if( pMem->flags & (MEM_Str|MEM_Blob) ){ double val = 0.0; if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8) @@ -300,8 +300,8 @@ void sqlite3VdbeIntegerAffinity(Mem *pMe */ void sqlite3VdbeIntegerAffinity(Mem *pMem){ assert( pMem->flags & MEM_Real ); - pMem->i = pMem->r; - if( ((double)pMem->i)==pMem->r ){ + pMem->u.i = pMem->r; + if( ((double)pMem->u.i)==pMem->r ){ pMem->flags |= MEM_Int; } } @@ -310,7 +310,7 @@ int sqlite3VdbeMemIntegerify(Mem *pMem){ ** Convert pMem to type integer. Invalidate any prior representations. */ int sqlite3VdbeMemIntegerify(Mem *pMem){ - pMem->i = sqlite3VdbeIntValue(pMem); + pMem->u.i = sqlite3VdbeIntValue(pMem); sqlite3VdbeMemRelease(pMem); pMem->flags = MEM_Int; return SQLITE_OK; @@ -353,7 +353,7 @@ void sqlite3VdbeMemSetInt64(Mem *pMem, i */ void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){ sqlite3VdbeMemRelease(pMem); - pMem->i = val; + pMem->u.i = val; pMem->flags = MEM_Int; pMem->type = SQLITE_INTEGER; } @@ -538,12 +538,12 @@ int sqlite3MemCompare(const Mem *pMem1, if( (f1 & f2 & MEM_Int)==0 ){ double r1, r2; if( (f1&MEM_Real)==0 ){ - r1 = pMem1->i; + r1 = pMem1->u.i; }else{ r1 = pMem1->r; } if( (f2&MEM_Real)==0 ){ - r2 = pMem2->i; + r2 = pMem2->u.i; }else{ r2 = pMem2->r; } @@ -553,8 +553,8 @@ int sqlite3MemCompare(const Mem *pMem1, }else{ assert( f1&MEM_Int ); assert( f2&MEM_Int ); - if( pMem1->i < pMem2->i ) return -1; - if( pMem1->i > pMem2->i ) return 1; + if( pMem1->u.i < pMem2->u.i ) return -1; + if( pMem1->u.i > pMem2->u.i ) return 1; return 0; } } @@ -637,14 +637,15 @@ int sqlite3VdbeMemFromBtree( int key, /* If true, retrieve from the btree key, not data. */ Mem *pMem /* OUT: Return data in this Mem structure. */ ){ - char *zData; /* Data from the btree layer */ - int available; /* Number of bytes available on the local btree page */ + char *zData; /* Data from the btree layer */ + int available = 0; /* Number of bytes available on the local btree page */ if( key ){ zData = (char *)sqlite3BtreeKeyFetch(pCur, &available); }else{ zData = (char *)sqlite3BtreeDataFetch(pCur, &available); } + assert( zData!=0 ); pMem->n = amt; if( offset+amt<=available ){ @@ -735,7 +736,7 @@ void sqlite3VdbeMemSanity(Mem *pMem){ || (pMem->flags&MEM_Null)==0 ); /* If the MEM is both real and integer, the values are equal */ assert( (pMem->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) - || pMem->r==pMem->i ); + || pMem->r==pMem->u.i ); } #endif @@ -831,7 +832,7 @@ int sqlite3ValueFromExpr( } }else if( op==TK_UMINUS ) { if( SQLITE_OK==sqlite3ValueFromExpr(pExpr->pLeft, enc, affinity, &pVal) ){ - pVal->i = -1 * pVal->i; + pVal->u.i = -1 * pVal->u.i; pVal->r = -1.0 * pVal->r; } } ============================================================ --- sqlite/where.c 2a919a3fbaff2e55604119f7c60133db459b404c +++ sqlite/where.c fce0dad6b230eb7ea844e8b8667c074d07e3fdd5 @@ -16,7 +16,7 @@ ** 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.237 2007/02/06 13:26:33 drh Exp $ +** $Id: where.c,v 1.246 2007/04/06 01:04:40 drh Exp $ */ #include "sqliteInt.h" @@ -35,9 +35,9 @@ int sqlite3_where_trace = 0; */ #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) int sqlite3_where_trace = 0; -# define TRACE(X) if(sqlite3_where_trace) sqlite3DebugPrintf X +# define WHERETRACE(X) if(sqlite3_where_trace) sqlite3DebugPrintf X #else -# define TRACE(X) +# define WHERETRACE(X) #endif /* Forward reference @@ -220,6 +220,9 @@ static void whereClauseClear(WhereClause ** Add a new entries to the WhereClause structure. Increase the allocated ** space as necessary. ** +** If the flags argument includes TERM_DYNAMIC, then responsibility +** for freeing the expression p is assumed by the WhereClause object. +** ** WARNING: This routine might reallocate the space used to store ** WhereTerms. All pointers to WhereTerms should be invalided after ** calling this routine. Such pointers may be reinitialized by referencing @@ -231,7 +234,12 @@ static int whereClauseInsert(WhereClause if( pWC->nTerm>=pWC->nSlot ){ WhereTerm *pOld = pWC->a; pWC->a = sqliteMalloc( sizeof(pWC->a[0])*pWC->nSlot*2 ); - if( pWC->a==0 ) return 0; + if( pWC->a==0 ){ + if( flags & TERM_DYNAMIC ){ + sqlite3ExprDelete(p); + } + return 0; + } memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm); if( pOld!=pWC->aStatic ){ sqliteFree(pOld); @@ -523,6 +531,10 @@ static int isLikeOrGlob( } pColl = pLeft->pColl; if( pColl==0 ){ + /* TODO: Coverage testing doesn't get this case. Is it actually possible + ** for an expression of type TK_COLUMN to not have an assigned collation + ** sequence at this point? + */ pColl = db->pDfltColl; } if( (pColl->type!=SQLITE_COLL_BINARY || noCase) && @@ -582,8 +594,94 @@ static void transferJoinMarkings(Expr *p pDerived->iRightJoinTable = pBase->iRightJoinTable; } +#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY) +/* +** Return TRUE if the given term of an OR clause can be converted +** into an IN clause. The iCursor and iColumn define the left-hand +** side of the IN clause. +** +** The context is that we have multiple OR-connected equality terms +** like this: +** +** a= OR a= OR b= OR ... +** +** The pOrTerm input to this routine corresponds to a single term of +** this OR clause. In order for the term to be a condidate for +** conversion to an IN operator, the following must be true: +** +** * The left-hand side of the term must be the column which +** is identified by iCursor and iColumn. +** +** * If the right-hand side is also a column, then the affinities +** of both right and left sides must be such that no type +** conversions are required on the right. (Ticket #2249) +** +** If both of these conditions are true, then return true. Otherwise +** return false. +*/ +static int orTermIsOptCandidate(WhereTerm *pOrTerm, int iCursor, int iColumn){ + int affLeft, affRight; + assert( pOrTerm->eOperator==WO_EQ ); + if( pOrTerm->leftCursor!=iCursor ){ + return 0; + } + if( pOrTerm->leftColumn!=iColumn ){ + return 0; + } + affRight = sqlite3ExprAffinity(pOrTerm->pExpr->pRight); + if( affRight==0 ){ + return 1; + } + affLeft = sqlite3ExprAffinity(pOrTerm->pExpr->pLeft); + if( affRight!=affLeft ){ + return 0; + } + return 1; +} /* +** Return true if the given term of an OR clause can be ignored during +** a check to make sure all OR terms are candidates for optimization. +** In other words, return true if a call to the orTermIsOptCandidate() +** above returned false but it is not necessary to disqualify the +** optimization. +** +** Suppose the original OR phrase was this: +** +** a=4 OR a=11 OR a=b +** +** During analysis, the third term gets flipped around and duplicate +** so that we are left with this: +** +** a=4 OR a=11 OR a=b OR b=a +** +** Since the last two terms are duplicates, only one of them +** has to qualify in order for the whole phrase to qualify. When +** this routine is called, we know that pOrTerm did not qualify. +** This routine merely checks to see if pOrTerm has a duplicate that +** might qualify. If there is a duplicate that has not yet been +** disqualified, then return true. If there are no duplicates, or +** the duplicate has also been disqualifed, return false. +*/ +static int orTermHasOkDuplicate(WhereClause *pOr, WhereTerm *pOrTerm){ + if( pOrTerm->flags & TERM_COPIED ){ + /* This is the original term. The duplicate is to the left had + ** has not yet been analyzed and thus has not yet been disqualified. */ + return 1; + } + if( (pOrTerm->flags & TERM_VIRTUAL)!=0 + && (pOr->a[pOrTerm->iParent].flags & TERM_OR_OK)!=0 ){ + /* This is a duplicate term. The original qualified so this one + ** does not have to. */ + return 1; + } + /* This is either a singleton term or else it is a duplicate for + ** which the original did not qualify. Either way we are done for. */ + return 0; +} +#endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */ + +/* ** The input to this routine is an WhereTerm structure with only the ** "pExpr" field filled in. The job of this routine is to analyze the ** subexpression and populate all the other fields of the WhereTerm @@ -644,7 +742,7 @@ static void exprAnalyze( int idxNew; pDup = sqlite3ExprDup(pExpr); if( sqlite3MallocFailed() ){ - sqliteFree(pDup); + sqlite3ExprDelete(pDup); return; } idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC); @@ -716,9 +814,10 @@ static void exprAnalyze( whereClauseInit(&sOr, pWC->pParse, pMaskSet); whereSplit(&sOr, pExpr, TK_OR); exprAnalyzeAll(pSrc, &sOr); - assert( sOr.nTerm>0 ); + assert( sOr.nTerm>=2 ); j = 0; do{ + assert( j=0; @@ -726,17 +825,15 @@ static void exprAnalyze( if( pOrTerm->eOperator!=WO_EQ ){ goto or_not_possible; } - if( pOrTerm->leftCursor==iCursor && pOrTerm->leftColumn==iColumn ){ + if( orTermIsOptCandidate(pOrTerm, iCursor, iColumn) ){ pOrTerm->flags |= TERM_OR_OK; - }else if( (pOrTerm->flags & TERM_COPIED)!=0 || - ((pOrTerm->flags & TERM_VIRTUAL)!=0 && - (sOr.a[pOrTerm->iParent].flags & TERM_OR_OK)!=0) ){ + }else if( orTermHasOkDuplicate(&sOr, pOrTerm) ){ pOrTerm->flags &= ~TERM_OR_OK; }else{ ok = 0; } } - }while( !ok && (sOr.a[j++].flags & TERM_COPIED)!=0 && jzName)); + WHERETRACE(("Recomputing index info for %s...\n", pTab->zName)); /* Count the number of possible WHERE clause constraints referring ** to this virtual table */ @@ -1207,13 +1303,19 @@ static double bestVirtualIndex( ** xBestIndex. */ - /* The module name must be defined */ + /* The module name must be defined. Also, by this point there must + ** be a pointer to an sqlite3_vtab structure. Otherwise + ** sqlite3ViewGetColumnNames() would have picked up the error. + */ assert( pTab->azModuleArg && pTab->azModuleArg[0] ); + assert( pTab->pVtab ); +#if 0 if( pTab->pVtab==0 ){ sqlite3ErrorMsg(pParse, "undefined module %s for table %s", pTab->azModuleArg[0], pTab->zName); return 0.0; } +#endif /* Set the aConstraint[].usable fields and initialize all ** output variables to zero. @@ -1257,7 +1359,7 @@ static double bestVirtualIndex( } sqlite3SafetyOff(pParse->db); - TRACE(("xBestIndex for %s\n", pTab->zName)); + WHERETRACE(("xBestIndex for %s\n", pTab->zName)); TRACE_IDX_INPUTS(pIdxInfo); rc = pTab->pVtab->pModule->xBestIndex(pTab->pVtab, pIdxInfo); TRACE_IDX_OUTPUTS(pIdxInfo); @@ -1272,6 +1374,7 @@ static double bestVirtualIndex( rc = sqlite3SafetyOn(pParse->db); } *(int*)&pIdxInfo->nOrderBy = nOrderBy; + return pIdxInfo->estimatedCost; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -1317,7 +1420,7 @@ static double bestIndex( int eqTermMask; /* Mask of valid equality operators */ double cost; /* Cost of using pProbe */ - TRACE(("bestIndex: tbl=%s notReady=%x\n", pSrc->pTab->zName, notReady)); + WHERETRACE(("bestIndex: tbl=%s notReady=%x\n", pSrc->pTab->zName, notReady)); lowestCost = SQLITE_BIG_DBL; pProbe = pSrc->pTab->pIndex; @@ -1348,7 +1451,7 @@ static double bestIndex( ** a single row is generated, output is always in sorted order */ *pFlags = WHERE_ROWID_EQ | WHERE_UNIQUE; *pnEq = 1; - TRACE(("... best is rowid\n")); + WHERETRACE(("... best is rowid\n")); return 0.0; }else if( (pExpr = pTerm->pExpr)->pList!=0 ){ /* Rowid IN (LIST): cost is NlogN where N is the number of list @@ -1361,14 +1464,14 @@ static double bestIndex( ** that value so make a wild guess. */ lowestCost = 200; } - TRACE(("... rowid IN cost: %.9g\n", lowestCost)); + WHERETRACE(("... rowid IN cost: %.9g\n", lowestCost)); } /* Estimate the cost of a table scan. If we do not know how many ** entries are in the table, use 1 million as a guess. */ cost = pProbe ? pProbe->aiRowEst[0] : 1000000; - TRACE(("... table scan base cost: %.9g\n", cost)); + WHERETRACE(("... table scan base cost: %.9g\n", cost)); flags = WHERE_ROWID_RANGE; /* Check for constraints on a range of rowids in a table scan. @@ -1383,7 +1486,7 @@ static double bestIndex( flags |= WHERE_BTM_LIMIT; cost /= 3; /* Guess that rowid>EXPR eliminates two-thirds of rows */ } - TRACE(("... rowid range reduces cost to %.9g\n", cost)); + WHERETRACE(("... rowid range reduces cost to %.9g\n", cost)); }else{ flags = 0; } @@ -1398,7 +1501,7 @@ static double bestIndex( } }else{ cost += cost*estLog(cost); - TRACE(("... sorting increases cost to %.9g\n", cost)); + WHERETRACE(("... sorting increases cost to %.9g\n", cost)); } } if( costzName)); + WHERETRACE(("... index %s:\n", pProbe->zName)); /* Count the number of columns in the index that are satisfied ** by x=EXPR constraints or x IN (...) constraints. @@ -1450,7 +1553,7 @@ static double bestIndex( && nEq==pProbe->nColumn ){ flags |= WHERE_UNIQUE; } - TRACE(("...... nEq=%d inMult=%.9g cost=%.9g\n", nEq, inMultiplier, cost)); + WHERETRACE(("...... nEq=%d inMult=%.9g cost=%.9g\n", nEq, inMultiplier, cost)); /* Look for range constraints */ @@ -1467,7 +1570,7 @@ static double bestIndex( flags |= WHERE_BTM_LIMIT; cost /= 3; } - TRACE(("...... range reduces cost to %.9g\n", cost)); + WHERETRACE(("...... range reduces cost to %.9g\n", cost)); } } @@ -1485,7 +1588,7 @@ static double bestIndex( } }else{ cost += cost*estLog(cost); - TRACE(("...... orderby increases cost to %.9g\n", cost)); + WHERETRACE(("...... orderby increases cost to %.9g\n", cost)); } } @@ -1505,7 +1608,7 @@ static double bestIndex( if( m==0 ){ flags |= WHERE_IDX_ONLY; cost /= 2; - TRACE(("...... idx-only reduces cost to %.9g\n", cost)); + WHERETRACE(("...... idx-only reduces cost to %.9g\n", cost)); } } @@ -1523,7 +1626,7 @@ static double bestIndex( /* Report the best result */ *ppIndex = bestIdx; - TRACE(("best index is %s, cost=%.9g, flags=%x, nEq=%d\n", + WHERETRACE(("best index is %s, cost=%.9g, flags=%x, nEq=%d\n", bestIdx ? bestIdx->zName : "(none)", lowestCost, bestFlags, bestNEq)); *pFlags = bestFlags | eqTermMask; *pnEq = bestNEq; @@ -1601,7 +1704,6 @@ static void codeEqualityTerm( static void codeEqualityTerm( Parse *pParse, /* The parsing context */ WhereTerm *pTerm, /* The term of the WHERE clause to be coded */ - int brk, /* Jump here to abandon the loop */ WhereLevel *pLevel /* When level of the FROM clause we are working on */ ){ Expr *pX = pTerm->pExpr; @@ -1613,21 +1715,25 @@ static void codeEqualityTerm( #ifndef SQLITE_OMIT_SUBQUERY }else{ int iTab; - int *aIn; + struct InLoop *pIn; assert( pX->op==TK_IN ); sqlite3CodeSubselect(pParse, pX); iTab = pX->iTable; sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0); VdbeComment((v, "# %.*s", pX->span.n, pX->span.z)); + if( pLevel->nIn==0 ){ + pLevel->nxt = sqlite3VdbeMakeLabel(v); + } pLevel->nIn++; - sqliteReallocOrFree((void**)&pLevel->aInLoop, - sizeof(pLevel->aInLoop[0])*2*pLevel->nIn); - aIn = pLevel->aInLoop; - if( aIn ){ - aIn += pLevel->nIn*2 - 2; - aIn[0] = iTab; - aIn[1] = sqlite3VdbeAddOp(v, OP_Column, iTab, 0); + pLevel->aInLoop = sqliteReallocOrFree(pLevel->aInLoop, + sizeof(pLevel->aInLoop[0])*pLevel->nIn); + pIn = pLevel->aInLoop; + if( pIn ){ + pIn += pLevel->nIn - 1; + pIn->iCur = iTab; + pIn->topAddr = sqlite3VdbeAddOp(v, OP_Column, iTab, 0); + sqlite3VdbeAddOp(v, OP_IsNull, -1, 0); }else{ pLevel->nIn = 0; } @@ -1663,8 +1769,7 @@ static void codeAllEqualityTerms( Parse *pParse, /* Parsing context */ WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */ WhereClause *pWC, /* The WHERE clause */ - Bitmask notReady, /* Which parts of FROM have not yet been coded */ - int brk /* Jump here to end the loop */ + Bitmask notReady /* Which parts of FROM have not yet been coded */ ){ int nEq = pLevel->nEq; /* The number of == or IN constraints to code */ int termsInMem = 0; /* If true, store value in mem[] cells */ @@ -1693,9 +1798,9 @@ static void codeAllEqualityTerms( pTerm = findTerm(pWC, iCur, k, notReady, pLevel->flags, pIdx); if( pTerm==0 ) break; assert( (pTerm->flags & TERM_CODED)==0 ); - codeEqualityTerm(pParse, pTerm, brk, pLevel); - if( (pTerm->eOperator & WO_ISNULL)==0 ){ - sqlite3VdbeAddOp(v, OP_IsNull, termsInMem ? -1 : -(j+1), brk); + codeEqualityTerm(pParse, pTerm, pLevel); + if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){ + sqlite3VdbeAddOp(v, OP_IsNull, termsInMem ? -1 : -(j+1), pLevel->brk); } if( termsInMem ){ sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem+j+1, 1); @@ -1734,6 +1839,10 @@ static void whereInfoFree(WhereInfo *pWI sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo; if( pInfo ){ if( pInfo->needToFreeIdxStr ){ + /* Coverage: Don't think this can be reached. By the time this + ** function is called, the index-strings have been passed + ** to the vdbe layer for deletion. + */ sqlite3_free(pInfo->idxStr); } sqliteFree(pInfo); @@ -1917,7 +2026,7 @@ WhereInfo *sqlite3WhereBegin( pTabItem = pTabList->a; pLevel = pWInfo->a; andFlags = ~0; - TRACE(("*** Optimizer Start ***\n")); + WHERETRACE(("*** Optimizer Start ***\n")); for(i=iFrom=0, pLevel=pWInfo->a; inSrc; i++, pLevel++){ Index *pIdx; /* Index for FROM table at pTabItem */ int flags; /* Flags asssociated with pIdx */ @@ -1958,6 +2067,14 @@ WhereInfo *sqlite3WhereBegin( } pIdx = 0; nEq = 0; + if( (SQLITE_BIG_DBL/2.0)pBestIdx never set. + */ + cost = (SQLITE_BIG_DBL/2.0); + } }else #endif { @@ -1977,7 +2094,7 @@ WhereInfo *sqlite3WhereBegin( } if( doNotReorder ) break; } - TRACE(("*** Optimizer choose table %d for loop %d\n", bestJ, + WHERETRACE(("*** Optimizer choose table %d for loop %d\n", bestJ, pLevel-pWInfo->a)); if( (bestFlags & WHERE_ORDERBY)!=0 ){ *ppOrderBy = 0; @@ -1996,7 +2113,7 @@ WhereInfo *sqlite3WhereBegin( notReady &= ~getMask(&maskSet, pTabList->a[bestJ].iCursor); pLevel->iFrom = bestJ; } - TRACE(("*** Optimizer Finished ***\n")); + WHERETRACE(("*** Optimizer Finished ***\n")); /* If the total query only selects a single row, then the ORDER BY ** clause is irrelevant. @@ -2090,6 +2207,7 @@ WhereInfo *sqlite3WhereBegin( int j; int iCur = pTabItem->iCursor; /* The VDBE cursor for the table */ Index *pIdx; /* The index we will be using */ + int nxt; /* Where to jump to continue with the next IN case */ int iIdxCur; /* The VDBE cursor for the index */ int omitTable; /* True if we use the index only */ int bRev; /* True if we need to scan in reverse order */ @@ -2105,8 +2223,13 @@ WhereInfo *sqlite3WhereBegin( ** for the current loop. Jump to brk to break out of a loop. ** Jump to cont to go immediately to the next iteration of the ** loop. + ** + ** When there is an IN operator, we also have a "nxt" label that + ** means to continue with the next IN value combination. When + ** there are no IN operators in the constraints, the "nxt" label + ** is the same as "brk". */ - brk = pLevel->brk = sqlite3VdbeMakeLabel(v); + brk = pLevel->brk = pLevel->nxt = sqlite3VdbeMakeLabel(v); cont = pLevel->cont = sqlite3VdbeMakeLabel(v); /* If this is the right table of a LEFT OUTER JOIN, allocate and @@ -2172,9 +2295,10 @@ WhereInfo *sqlite3WhereBegin( assert( pTerm->pExpr!=0 ); assert( pTerm->leftCursor==iCur ); assert( omitTable==0 ); - codeEqualityTerm(pParse, pTerm, brk, pLevel); - sqlite3VdbeAddOp(v, OP_MustBeInt, 1, brk); - sqlite3VdbeAddOp(v, OP_NotExists, iCur, brk); + codeEqualityTerm(pParse, pTerm, pLevel); + nxt = pLevel->nxt; + sqlite3VdbeAddOp(v, OP_MustBeInt, 1, nxt); + sqlite3VdbeAddOp(v, OP_NotExists, iCur, nxt); VdbeComment((v, "pk")); pLevel->op = OP_Noop; }else if( pLevel->flags & WHERE_ROWID_RANGE ){ @@ -2253,7 +2377,7 @@ WhereInfo *sqlite3WhereBegin( /* Generate code to evaluate all constraint terms using == or IN ** and level the values of those terms on the stack. */ - codeAllEqualityTerms(pParse, pLevel, &wc, notReady, brk); + codeAllEqualityTerms(pParse, pLevel, &wc, notReady); /* Duplicate the equality term values because they will all be ** used twice: once to make the termination key and once to make the @@ -2284,6 +2408,7 @@ WhereInfo *sqlite3WhereBegin( ** 2002-Dec-04: On a reverse-order scan, the so-called "termination" ** key computed here really ends up being the start key. */ + nxt = pLevel->nxt; if( topLimit ){ Expr *pX; int k = pIdx->aiColumn[j]; @@ -2292,7 +2417,7 @@ WhereInfo *sqlite3WhereBegin( pX = pTerm->pExpr; assert( (pTerm->flags & TERM_CODED)==0 ); sqlite3ExprCode(pParse, pX->pRight); - sqlite3VdbeAddOp(v, OP_IsNull, -(nEq+1), brk); + sqlite3VdbeAddOp(v, OP_IsNull, -(nEq+1), nxt); topEq = pTerm->eOperator & (WO_LE|WO_GE); disableTerm(pLevel, pTerm); testOp = OP_IdxGE; @@ -2306,7 +2431,7 @@ WhereInfo *sqlite3WhereBegin( buildIndexProbe(v, nCol, pIdx); if( bRev ){ int op = topEq ? OP_MoveLe : OP_MoveLt; - sqlite3VdbeAddOp(v, op, iIdxCur, brk); + sqlite3VdbeAddOp(v, op, iIdxCur, nxt); }else{ sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1); } @@ -2331,7 +2456,7 @@ WhereInfo *sqlite3WhereBegin( pX = pTerm->pExpr; assert( (pTerm->flags & TERM_CODED)==0 ); sqlite3ExprCode(pParse, pX->pRight); - sqlite3VdbeAddOp(v, OP_IsNull, -(nEq+1), brk); + sqlite3VdbeAddOp(v, OP_IsNull, -(nEq+1), nxt); btmEq = pTerm->eOperator & (WO_LE|WO_GE); disableTerm(pLevel, pTerm); }else{ @@ -2346,7 +2471,7 @@ WhereInfo *sqlite3WhereBegin( testOp = OP_IdxLT; }else{ int op = btmEq ? OP_MoveGe : OP_MoveGt; - sqlite3VdbeAddOp(v, op, iIdxCur, brk); + sqlite3VdbeAddOp(v, op, iIdxCur, nxt); } }else if( bRev ){ testOp = OP_Noop; @@ -2361,7 +2486,7 @@ WhereInfo *sqlite3WhereBegin( start = sqlite3VdbeCurrentAddr(v); if( testOp!=OP_Noop ){ sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0); - sqlite3VdbeAddOp(v, testOp, iIdxCur, brk); + sqlite3VdbeAddOp(v, testOp, iIdxCur, nxt); if( (topEq && !bRev) || (!btmEq && bRev) ){ sqlite3VdbeChangeP3(v, -1, "+", P3_STATIC); } @@ -2390,7 +2515,8 @@ WhereInfo *sqlite3WhereBegin( /* Generate code to evaluate all constraint terms using == or IN ** and leave the values of those terms on the stack. */ - codeAllEqualityTerms(pParse, pLevel, &wc, notReady, brk); + codeAllEqualityTerms(pParse, pLevel, &wc, notReady); + nxt = pLevel->nxt; /* Generate a single key that will be used to both start and terminate ** the search @@ -2399,21 +2525,21 @@ WhereInfo *sqlite3WhereBegin( 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 + ** Then generate code (2) that jumps to "nxt" after the cursor is past ** the last matching element of the table. The code (1) is executed ** once to initialize the search, the code (2) is executed before each ** iteration of the scan to see if the scan has finished. */ if( bRev ){ /* Scan in reverse order */ - sqlite3VdbeAddOp(v, OP_MoveLe, iIdxCur, brk); + sqlite3VdbeAddOp(v, OP_MoveLe, iIdxCur, nxt); start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0); - sqlite3VdbeAddOp(v, OP_IdxLT, iIdxCur, brk); + sqlite3VdbeAddOp(v, OP_IdxLT, iIdxCur, nxt); pLevel->op = OP_Prev; }else{ /* Scan in the forward order */ - sqlite3VdbeAddOp(v, OP_MoveGe, iIdxCur, brk); + sqlite3VdbeAddOp(v, OP_MoveGe, iIdxCur, nxt); start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0); - sqlite3VdbeOp3(v, OP_IdxGE, iIdxCur, brk, "+", P3_STATIC); + sqlite3VdbeOp3(v, OP_IdxGE, iIdxCur, nxt, "+", P3_STATIC); pLevel->op = OP_Next; } if( !omitTable ){ @@ -2546,16 +2672,18 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ if( pLevel->op!=OP_Noop ){ sqlite3VdbeAddOp(v, pLevel->op, pLevel->p1, pLevel->p2); } - sqlite3VdbeResolveLabel(v, pLevel->brk); if( pLevel->nIn ){ - int *a; + struct InLoop *pIn; int j; - for(j=pLevel->nIn, a=&pLevel->aInLoop[j*2-2]; j>0; j--, a-=2){ - sqlite3VdbeAddOp(v, OP_Next, a[0], a[1]); - sqlite3VdbeJumpHere(v, a[1]-1); + sqlite3VdbeResolveLabel(v, pLevel->nxt); + for(j=pLevel->nIn, pIn=&pLevel->aInLoop[j-1]; j>0; j--, pIn--){ + sqlite3VdbeJumpHere(v, pIn->topAddr+1); + sqlite3VdbeAddOp(v, OP_Next, pIn->iCur, pIn->topAddr); + sqlite3VdbeJumpHere(v, pIn->topAddr-1); } sqliteFree(pLevel->aInLoop); } + sqlite3VdbeResolveLabel(v, pLevel->brk); if( pLevel->iLeftJoin ){ int addr; addr = sqlite3VdbeAddOp(v, OP_IfMemPos, pLevel->iLeftJoin, 0);