From 5a500afd571a5f1219d6e840e8ab41ba772eb616 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 11 Mar 2014 20:33:04 +0000 Subject: [PATCH 01/17] Enable the b-tree cursor objects overflow page-number cache, which is normally enabled only for incr-blob cursors, for all cursors. FossilOrigin-Name: da59198505990a4fe832be7932117c7e014955b7 --- manifest | 26 +++++++------- manifest.uuid | 2 +- src/btree.c | 98 +++++++++++++++++++++++--------------------------- src/btree.h | 2 +- src/btreeInt.h | 2 ++ src/vdbeblob.c | 4 +-- 6 files changed, 63 insertions(+), 71 deletions(-) diff --git a/manifest b/manifest index 219399a93b..17e141330e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Version\s3.8.4.1 -D 2014-03-11T15:27:36.923 +C Enable\sthe\sb-tree\scursor\sobjects\soverflow\spage-number\scache,\swhich\sis\snormally\senabled\sonly\sfor\sincr-blob\scursors,\sfor\sall\scursors. +D 2014-03-11T20:33:04.219 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -164,9 +164,9 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c 4d28fb15543f0e071b1780b2af8cd2ee489de32d -F src/btree.h 9e0f97c01b972f779eb7655cfb4f8727fd6dc26f -F src/btreeInt.h 0be66063468a520e4d66b80c7a1dc26d04ee6ea4 +F src/btree.c c748d8387789d01769e442b9da65e52ed61f408e +F src/btree.h 6b0c1a3f0937f9852ec727c820e71dbdd4bd0b27 +F src/btreeInt.h 22a8f07968ec821910ab93cc822d7f0c404c74d1 F src/build.c 0d50ef95aad63f4c4fc47f3fa2670d4557c45db0 F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac @@ -283,7 +283,7 @@ F src/vdbe.h fb2c48c198300a7c632f09fc940011d2ad2fc2ae F src/vdbeInt.h e54fc4f289fce48e81b3371128446033d097733b F src/vdbeapi.c 0ed6053f947edd0b30f64ce5aeb811872a3450a4 F src/vdbeaux.c e45e3f9daf38c5be3fd39e9aacc1c9066af57a06 -F src/vdbeblob.c 15377abfb59251bccedd5a9c7d014a895f0c04aa +F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac F src/vdbemem.c 6fc77594c60f6155404f3f8d71bf36d1fdeb4447 F src/vdbesort.c 46801acb342e5e4c07ba1777fe58880c143abb59 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 @@ -1156,10 +1156,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 33f5694fa42d9a521ca081de4ddd1e9dc8952b16 -R 581994aed374f15c1c6bac5b0a9a5df5 -T +bgcolor * #d0c0ff -T +sym-release * -T +sym-version-3.8.4.1 * -U drh -Z c1ec45dc8a92b80bfa16f4c74ccfeec8 +P 018d317b1257ce68a92908b05c9c7cf1494050d0 +R 9660042129e37a760044c3b5edf13974 +T *branch * overflow-pgno-cache +T *sym-overflow-pgno-cache * +T -sym-trunk * +U dan +Z 262878375cf61ff20b91f83b47f52bc2 diff --git a/manifest.uuid b/manifest.uuid index 1f0b42178b..6b4cb8a17f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -018d317b1257ce68a92908b05c9c7cf1494050d0 \ No newline at end of file +da59198505990a4fe832be7932117c7e014955b7 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 29ead1c67a..5716a5199a 100644 --- a/src/btree.c +++ b/src/btree.c @@ -446,16 +446,11 @@ static int cursorHoldsMutex(BtCursor *p){ } #endif - -#ifndef SQLITE_OMIT_INCRBLOB /* -** Invalidate the overflow page-list cache for cursor pCur, if any. +** Invalidate the overflow cache of the cursor passed as the first argument. +** on the shared btree structure pBt. */ -static void invalidateOverflowCache(BtCursor *pCur){ - assert( cursorHoldsMutex(pCur) ); - sqlite3_free(pCur->aOverflow); - pCur->aOverflow = 0; -} +#define invalidateOverflowCache(pCur) (pCur->bOvflValid = 0) /* ** Invalidate the overflow page-list cache for all cursors opened @@ -469,6 +464,7 @@ static void invalidateAllOverflowCache(BtShared *pBt){ } } +#ifndef SQLITE_OMIT_INCRBLOB /* ** This function is called before modifying the contents of a table ** to invalidate any incrblob cursors that are open on the @@ -498,9 +494,7 @@ static void invalidateIncrblobCursors( } #else - /* Stub functions when INCRBLOB is omitted */ - #define invalidateOverflowCache(x) - #define invalidateAllOverflowCache(x) + /* Stub function when INCRBLOB is omitted */ #define invalidateIncrblobCursors(x,y,z) #endif /* SQLITE_OMIT_INCRBLOB */ @@ -3694,7 +3688,7 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){ releasePage(pCur->apPage[i]); } unlockBtreeIfUnused(pBt); - invalidateOverflowCache(pCur); + sqlite3DbFree(pBtree->db, pCur->aOverflow); /* sqlite3_free(pCur); */ sqlite3BtreeLeave(pBtree); } @@ -3915,10 +3909,12 @@ static int copyPayload( /* ** This function is used to read or overwrite payload information -** for the entry that the pCur cursor is pointing to. If the eOp -** parameter is 0, this is a read operation (data copied into -** buffer pBuf). If it is non-zero, a write (data copied from -** buffer pBuf). +** for the entry that the pCur cursor is pointing to. The eOp +** argument is interpreted as follows: +** +** 0: The operation is a read. Populate the overflow cache. +** 1: The operation is a write. Populate the overflow cache. +** 2: The operation is a read. Do not populate the overflow cache. ** ** A total of "amt" bytes are read or written beginning at "offset". ** Data is read to or from the buffer pBuf. @@ -3926,11 +3922,11 @@ static int copyPayload( ** The content being read or written might appear on the main page ** or be scattered out on multiple overflow pages. ** -** If the BtCursor.isIncrblobHandle flag is set, and the current -** cursor entry uses one or more overflow pages, this function -** allocates space for and lazily popluates the overflow page-list -** cache array (BtCursor.aOverflow). Subsequent calls use this -** cache to make seeking to the supplied offset more efficient. +** If the current cursor entry uses one or more overflow pages and the +** eOp argument is not 2, this function may allocate space for and lazily +** popluates the overflow page-list cache array (BtCursor.aOverflow). +** Subsequent calls use this cache to make seeking to the supplied offset +** more efficient. ** ** Once an overflow page-list cache has been allocated, it may be ** invalidated if some other cursor writes to the same table, or if @@ -3977,7 +3973,7 @@ static int accessPayload( if( a+offset>pCur->info.nLocal ){ a = pCur->info.nLocal - offset; } - rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage); + rc = copyPayload(&aPayload[offset], pBuf, a, (eOp & 0x01), pPage->pDbPage); offset = 0; pBuf += a; amt -= a; @@ -3991,7 +3987,6 @@ static int accessPayload( nextPage = get4byte(&aPayload[pCur->info.nLocal]); -#ifndef SQLITE_OMIT_INCRBLOB /* If the isIncrblobHandle flag is set and the BtCursor.aOverflow[] ** has not been allocated, allocate it now. The array is sized at ** one entry for each overflow page in the overflow chain. The @@ -3999,13 +3994,22 @@ static int accessPayload( ** etc. A value of 0 in the aOverflow[] array means "not yet known" ** (the cache is lazily populated). */ - if( pCur->isIncrblobHandle && !pCur->aOverflow ){ + if( eOp!=2 && !pCur->bOvflValid ){ int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; - pCur->aOverflow = (Pgno *)sqlite3MallocZero(sizeof(Pgno)*nOvfl); - /* nOvfl is always positive. If it were zero, fetchPayload would have - ** been used instead of this routine. */ - if( ALWAYS(nOvfl) && !pCur->aOverflow ){ - rc = SQLITE_NOMEM; + if( nOvfl>pCur->nOvflAlloc ){ + Pgno *aNew = (Pgno*)sqlite3DbRealloc( + pCur->pBtree->db, pCur->aOverflow, nOvfl*2*sizeof(Pgno) + ); + if( aNew==0 ){ + rc = SQLITE_NOMEM; + }else{ + pCur->nOvflAlloc = nOvfl*2; + pCur->aOverflow = aNew; + } + } + if( rc==SQLITE_OK ){ + memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno)); + pCur->bOvflValid = 1; } } @@ -4013,22 +4017,19 @@ static int accessPayload( ** entry for the first required overflow page is valid, skip ** directly to it. */ - if( pCur->aOverflow && pCur->aOverflow[offset/ovflSize] ){ + if( pCur->bOvflValid && pCur->aOverflow[offset/ovflSize] ){ iIdx = (offset/ovflSize); nextPage = pCur->aOverflow[iIdx]; offset = (offset%ovflSize); } -#endif for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){ -#ifndef SQLITE_OMIT_INCRBLOB /* If required, populate the overflow page-list cache. */ - if( pCur->aOverflow ){ + if( pCur->bOvflValid ){ assert(!pCur->aOverflow[iIdx] || pCur->aOverflow[iIdx]==nextPage); pCur->aOverflow[iIdx] = nextPage; } -#endif if( offset>=ovflSize ){ /* The only reason to read this page is to obtain the page @@ -4037,11 +4038,9 @@ static int accessPayload( ** page-list cache, if any, then fall back to the getOverflowPage() ** function. */ -#ifndef SQLITE_OMIT_INCRBLOB - if( pCur->aOverflow && pCur->aOverflow[iIdx+1] ){ + if( pCur->bOvflValid && pCur->aOverflow[iIdx+1] ){ nextPage = pCur->aOverflow[iIdx+1]; } else -#endif rc = getOverflowPage(pBt, nextPage, 0, &nextPage); offset -= ovflSize; }else{ @@ -4069,7 +4068,7 @@ static int accessPayload( ** output buffer, bypassing the page-cache altogether. This speeds ** up loading large records that span many overflow pages. */ - if( eOp==0 /* (1) */ + if( (eOp&0x01)==0 /* (1) */ && offset==0 /* (2) */ && pBt->inTransaction==TRANS_READ /* (4) */ && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */ @@ -4087,12 +4086,12 @@ static int accessPayload( { DbPage *pDbPage; rc = sqlite3PagerAcquire(pBt->pPager, nextPage, &pDbPage, - (eOp==0 ? PAGER_GET_READONLY : 0) + ((eOp&0x01)==0 ? PAGER_GET_READONLY : 0) ); if( rc==SQLITE_OK ){ aPayload = sqlite3PagerGetData(pDbPage); nextPage = get4byte(aPayload); - rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage); + rc = copyPayload(&aPayload[offset+4], pBuf, a, (eOp&0x01), pDbPage); sqlite3PagerUnref(pDbPage); offset = 0; } @@ -4337,6 +4336,7 @@ static int moveToRoot(BtCursor *pCur){ assert( CURSOR_INVALID < CURSOR_REQUIRESEEK ); assert( CURSOR_VALID < CURSOR_REQUIRESEEK ); assert( CURSOR_FAULT > CURSOR_REQUIRESEEK ); + invalidateOverflowCache(pCur); if( pCur->eState>=CURSOR_REQUIRESEEK ){ if( pCur->eState==CURSOR_FAULT ){ assert( pCur->skipNext!=SQLITE_OK ); @@ -4686,7 +4686,7 @@ int sqlite3BtreeMovetoUnpacked( goto moveto_finish; } pCur->aiIdx[pCur->iPage] = (u16)idx; - rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0); + rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 2); if( rc ){ sqlite3_free(pCellKey); goto moveto_finish; @@ -4775,6 +4775,7 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ assert( pRes!=0 ); assert( *pRes==0 || *pRes==1 ); assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); + invalidateOverflowCache(pCur); if( pCur->eState!=CURSOR_VALID ){ rc = restoreCursorPosition(pCur); if( rc!=SQLITE_OK ){ @@ -4870,6 +4871,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ assert( pRes!=0 ); assert( *pRes==0 || *pRes==1 ); assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); + invalidateOverflowCache(pCur); pCur->atLast = 0; if( pCur->eState!=CURSOR_VALID ){ if( ALWAYS(pCur->eState>=CURSOR_REQUIRESEEK) ){ @@ -8424,19 +8426,9 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ } /* -** Set a flag on this cursor to cache the locations of pages from the -** overflow list for the current row. This is used by cursors opened -** for incremental blob IO only. -** -** This function sets a flag only. The actual page location cache -** (stored in BtCursor.aOverflow[]) is allocated and used by function -** accessPayload() (the worker function for sqlite3BtreeData() and -** sqlite3BtreePutData()). +** Mark this cursor as an incremental blob cursor. */ -void sqlite3BtreeCacheOverflow(BtCursor *pCur){ - assert( cursorHoldsMutex(pCur) ); - assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - invalidateOverflowCache(pCur); +void sqlite3BtreeIncrblobCursor(BtCursor *pCur){ pCur->isIncrblobHandle = 1; } #endif diff --git a/src/btree.h b/src/btree.h index eda7bef70a..bedbef692f 100644 --- a/src/btree.h +++ b/src/btree.h @@ -187,7 +187,7 @@ char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); struct Pager *sqlite3BtreePager(Btree*); int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); -void sqlite3BtreeCacheOverflow(BtCursor *); +void sqlite3BtreeIncrblobCursor(BtCursor *); void sqlite3BtreeClearCursor(BtCursor *); int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask); diff --git a/src/btreeInt.h b/src/btreeInt.h index 87b4181f82..a41d8ebb55 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -497,6 +497,8 @@ struct BtCursor { BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */ #ifndef SQLITE_OMIT_INCRBLOB + int nOvflAlloc; /* Allocated size of aOverflow[] array */ + u8 bOvflValid; /* True if size and contents of aOverflow[] valid */ Pgno *aOverflow; /* Cache of overflow page locations */ #endif Pgno pgnoRoot; /* The root page of this tree */ diff --git a/src/vdbeblob.c b/src/vdbeblob.c index cf7495e5b4..083f3f413c 100644 --- a/src/vdbeblob.c +++ b/src/vdbeblob.c @@ -77,9 +77,7 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){ p->iOffset = pC->aType[p->iCol + pC->nField]; p->nByte = sqlite3VdbeSerialTypeLen(type); p->pCsr = pC->pCursor; - sqlite3BtreeEnterCursor(p->pCsr); - sqlite3BtreeCacheOverflow(p->pCsr); - sqlite3BtreeLeaveCursor(p->pCsr); + sqlite3BtreeIncrblobCursor(p->pCsr); } } From 036dbec01c083e196725e7fff530e8f8de61914d Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 11 Mar 2014 23:40:44 +0000 Subject: [PATCH 02/17] Combine the various boolean fields of the BtCursor object into a single bit-vector. This allows setting or clearing more than one boolean at a time and makes the overflow-pgno-cache branch faster than trunk on speedtest1. FossilOrigin-Name: 968fec44d7fde3adbd3e9603e4282351f0d4bda1 --- manifest | 21 ++++++------ manifest.uuid | 2 +- src/btree.c | 84 +++++++++++++++++++++++++----------------------- src/btreeInt.h | 27 ++++++++-------- src/test_btree.c | 2 +- 5 files changed, 69 insertions(+), 67 deletions(-) diff --git a/manifest b/manifest index 17e141330e..24561347ec 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enable\sthe\sb-tree\scursor\sobjects\soverflow\spage-number\scache,\swhich\sis\snormally\senabled\sonly\sfor\sincr-blob\scursors,\sfor\sall\scursors. -D 2014-03-11T20:33:04.219 +C Combine\sthe\svarious\sboolean\sfields\sof\sthe\sBtCursor\sobject\sinto\sa\ssingle\nbit-vector.\s\sThis\sallows\ssetting\sor\sclearing\smore\sthan\sone\sboolean\sat\sa\ntime\sand\smakes\sthe\soverflow-pgno-cache\sbranch\sfaster\sthan\strunk\son\s\nspeedtest1. +D 2014-03-11T23:40:44.961 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -164,9 +164,9 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c c748d8387789d01769e442b9da65e52ed61f408e +F src/btree.c 225a3f4d5511d4f5eab38a686f6c7e22290739f3 F src/btree.h 6b0c1a3f0937f9852ec727c820e71dbdd4bd0b27 -F src/btreeInt.h 22a8f07968ec821910ab93cc822d7f0c404c74d1 +F src/btreeInt.h d1784d1e17d08d29e890190dbb9836fa64573381 F src/build.c 0d50ef95aad63f4c4fc47f3fa2670d4557c45db0 F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac @@ -239,7 +239,7 @@ F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60 F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8 F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12 F src/test_backup.c 3875e899222b651e18b662f86e0e50daa946344e -F src/test_btree.c 5b89601dcb42a33ba8b820a6b763cc9cb48bac16 +F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f F src/test_config.c 0336e0bdbe541b4af89d7e3dd0656e8e6b51e585 F src/test_demovfs.c 69b2085076654ebc18014cbc6386f04409c959a9 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc @@ -1156,10 +1156,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 018d317b1257ce68a92908b05c9c7cf1494050d0 -R 9660042129e37a760044c3b5edf13974 -T *branch * overflow-pgno-cache -T *sym-overflow-pgno-cache * -T -sym-trunk * -U dan -Z 262878375cf61ff20b91f83b47f52bc2 +P da59198505990a4fe832be7932117c7e014955b7 +R a9a97bb8415d8a76adacb051af2ccc88 +U drh +Z 90b8a93448c14945f126312bc79eea6f diff --git a/manifest.uuid b/manifest.uuid index 6b4cb8a17f..6cfc27f694 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -da59198505990a4fe832be7932117c7e014955b7 \ No newline at end of file +968fec44d7fde3adbd3e9603e4282351f0d4bda1 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 5716a5199a..bd1a0e1c75 100644 --- a/src/btree.c +++ b/src/btree.c @@ -450,7 +450,7 @@ static int cursorHoldsMutex(BtCursor *p){ ** Invalidate the overflow cache of the cursor passed as the first argument. ** on the shared btree structure pBt. */ -#define invalidateOverflowCache(pCur) (pCur->bOvflValid = 0) +#define invalidateOverflowCache(pCur) (pCur->curFlags &= ~BTCF_ValidOvfl) /* ** Invalidate the overflow page-list cache for all cursors opened @@ -487,7 +487,7 @@ static void invalidateIncrblobCursors( BtShared *pBt = pBtree->pBt; assert( sqlite3BtreeHoldsMutex(pBtree) ); for(p=pBt->pCursor; p; p=p->pNext){ - if( p->isIncrblobHandle && (isClearTable || p->info.nKey==iRow) ){ + if( (p->curFlags & BTCF_Incrblob)!=0 && (isClearTable || p->info.nKey==iRow) ){ p->eState = CURSOR_INVALID; } } @@ -2543,7 +2543,8 @@ static int countValidCursors(BtShared *pBt, int wrOnly){ BtCursor *pCur; int r = 0; for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ - if( (wrOnly==0 || pCur->wrFlag) && pCur->eState!=CURSOR_FAULT ) r++; + if( (wrOnly==0 || (pCur->curFlags & BTCF_WriteFlag)!=0) + && pCur->eState!=CURSOR_FAULT ) r++; } return r; } @@ -3618,7 +3619,7 @@ static int btreeCursor( pCur->pKeyInfo = pKeyInfo; pCur->pBtree = p; pCur->pBt = pBt; - pCur->wrFlag = (u8)wrFlag; + pCur->curFlags = wrFlag ? BTCF_WriteFlag : 0; pCur->pNext = pBt->pCursor; if( pCur->pNext ){ pCur->pNext->pPrev = pCur; @@ -3727,7 +3728,7 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){ if( pCur->info.nSize==0 ){ int iPage = pCur->iPage; btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); - pCur->validNKey = 1; + pCur->curFlags |= BTCF_ValidNKey; }else{ assertCellInfo(pCur); } @@ -3737,8 +3738,8 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){ #define getCellInfo(pCur) \ if( pCur->info.nSize==0 ){ \ int iPage = pCur->iPage; \ - btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); \ - pCur->validNKey = 1; \ + btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); \ + pCur->curFlags |= BTCF_ValidNKey; \ }else{ \ assertCellInfo(pCur); \ } @@ -3987,14 +3988,14 @@ static int accessPayload( nextPage = get4byte(&aPayload[pCur->info.nLocal]); - /* If the isIncrblobHandle flag is set and the BtCursor.aOverflow[] + /* If the BTCF_Incrblob flag is set and the BtCursor.aOverflow[] ** has not been allocated, allocate it now. The array is sized at ** one entry for each overflow page in the overflow chain. The ** page number of the first overflow page is stored in aOverflow[0], ** etc. A value of 0 in the aOverflow[] array means "not yet known" ** (the cache is lazily populated). */ - if( eOp!=2 && !pCur->bOvflValid ){ + if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){ int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; if( nOvfl>pCur->nOvflAlloc ){ Pgno *aNew = (Pgno*)sqlite3DbRealloc( @@ -4009,7 +4010,7 @@ static int accessPayload( } if( rc==SQLITE_OK ){ memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno)); - pCur->bOvflValid = 1; + pCur->curFlags |= BTCF_ValidOvfl; } } @@ -4017,7 +4018,7 @@ static int accessPayload( ** entry for the first required overflow page is valid, skip ** directly to it. */ - if( pCur->bOvflValid && pCur->aOverflow[offset/ovflSize] ){ + if( (pCur->curFlags & BTCF_ValidOvfl)!=0 && pCur->aOverflow[offset/ovflSize] ){ iIdx = (offset/ovflSize); nextPage = pCur->aOverflow[iIdx]; offset = (offset%ovflSize); @@ -4026,7 +4027,7 @@ static int accessPayload( for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){ /* If required, populate the overflow page-list cache. */ - if( pCur->bOvflValid ){ + if( (pCur->curFlags & BTCF_ValidOvfl)!=0 ){ assert(!pCur->aOverflow[iIdx] || pCur->aOverflow[iIdx]==nextPage); pCur->aOverflow[iIdx] = nextPage; } @@ -4038,7 +4039,7 @@ static int accessPayload( ** page-list cache, if any, then fall back to the getOverflowPage() ** function. */ - if( pCur->bOvflValid && pCur->aOverflow[iIdx+1] ){ + if( (pCur->curFlags & BTCF_ValidOvfl)!=0 && pCur->aOverflow[iIdx+1] ){ nextPage = pCur->aOverflow[iIdx+1]; } else rc = getOverflowPage(pBt, nextPage, 0, &nextPage); @@ -4239,14 +4240,14 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){ return SQLITE_CORRUPT_BKPT; } rc = getAndInitPage(pBt, newPgno, &pNewPage, - pCur->wrFlag==0 ? PAGER_GET_READONLY : 0); + (pCur->curFlags & BTCF_WriteFlag)==0 ? PAGER_GET_READONLY : 0); if( rc ) return rc; pCur->apPage[i+1] = pNewPage; pCur->aiIdx[i+1] = 0; pCur->iPage++; pCur->info.nSize = 0; - pCur->validNKey = 0; + pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); if( pNewPage->nCell<1 || pNewPage->intKey!=pCur->apPage[i]->intKey ){ return SQLITE_CORRUPT_BKPT; } @@ -4304,7 +4305,7 @@ static void moveToParent(BtCursor *pCur){ releasePage(pCur->apPage[pCur->iPage]); pCur->iPage--; pCur->info.nSize = 0; - pCur->validNKey = 0; + pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); } /* @@ -4336,7 +4337,7 @@ static int moveToRoot(BtCursor *pCur){ assert( CURSOR_INVALID < CURSOR_REQUIRESEEK ); assert( CURSOR_VALID < CURSOR_REQUIRESEEK ); assert( CURSOR_FAULT > CURSOR_REQUIRESEEK ); - invalidateOverflowCache(pCur); +// invalidateOverflowCache(pCur); if( pCur->eState>=CURSOR_REQUIRESEEK ){ if( pCur->eState==CURSOR_FAULT ){ assert( pCur->skipNext!=SQLITE_OK ); @@ -4352,7 +4353,7 @@ static int moveToRoot(BtCursor *pCur){ return SQLITE_OK; }else{ rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0], - pCur->wrFlag==0 ? PAGER_GET_READONLY : 0); + (pCur->curFlags & BTCF_WriteFlag)==0 ? PAGER_GET_READONLY : 0); if( rc!=SQLITE_OK ){ pCur->eState = CURSOR_INVALID; return rc; @@ -4379,8 +4380,7 @@ static int moveToRoot(BtCursor *pCur){ pCur->aiIdx[0] = 0; pCur->info.nSize = 0; - pCur->atLast = 0; - pCur->validNKey = 0; + pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl); if( pRoot->nCell>0 ){ pCur->eState = CURSOR_VALID; @@ -4443,7 +4443,7 @@ static int moveToRightmost(BtCursor *pCur){ if( rc==SQLITE_OK ){ pCur->aiIdx[pCur->iPage] = pPage->nCell-1; pCur->info.nSize = 0; - pCur->validNKey = 0; + pCur->curFlags &= ~BTCF_ValidNKey; } return rc; } @@ -4482,7 +4482,7 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); /* If the cursor already points to the last entry, this is a no-op. */ - if( CURSOR_VALID==pCur->eState && pCur->atLast ){ + if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){ #ifdef SQLITE_DEBUG /* This block serves to assert() that the cursor really does point ** to the last entry in the b-tree. */ @@ -4505,7 +4505,12 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ assert( pCur->eState==CURSOR_VALID ); *pRes = 0; rc = moveToRightmost(pCur); - pCur->atLast = rc==SQLITE_OK ?1:0; + if( rc==SQLITE_OK ){ + pCur->curFlags |= BTCF_AtLast; + }else{ + pCur->curFlags &= ~BTCF_AtLast; + } + } } return rc; @@ -4556,14 +4561,14 @@ int sqlite3BtreeMovetoUnpacked( /* If the cursor is already positioned at the point we are trying ** to move to, then just return without doing any work */ - if( pCur->eState==CURSOR_VALID && pCur->validNKey + if( pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0 && pCur->apPage[0]->intKey ){ if( pCur->info.nKey==intKey ){ *pRes = 0; return SQLITE_OK; } - if( pCur->atLast && pCur->info.nKeycurFlags & BTCF_AtLast)!=0 && pCur->info.nKeyupr ){ c = +1; break; } }else{ assert( nCellKey==intKey ); - pCur->validNKey = 1; + pCur->curFlags |= BTCF_ValidNKey; pCur->info.nKey = nCellKey; pCur->aiIdx[pCur->iPage] = (u16)idx; if( !pPage->leaf ){ @@ -4731,7 +4736,7 @@ moveto_next_layer: } moveto_finish: pCur->info.nSize = 0; - pCur->validNKey = 0; + pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); return rc; } @@ -4775,8 +4780,8 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ assert( pRes!=0 ); assert( *pRes==0 || *pRes==1 ); assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); - invalidateOverflowCache(pCur); if( pCur->eState!=CURSOR_VALID ){ + invalidateOverflowCache(pCur); rc = restoreCursorPosition(pCur); if( rc!=SQLITE_OK ){ *pRes = 0; @@ -4810,7 +4815,7 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ testcase( idx>pPage->nCell ); pCur->info.nSize = 0; - pCur->validNKey = 0; + pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); if( idx>=pPage->nCell ){ if( !pPage->leaf ){ rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8])); @@ -4871,8 +4876,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ assert( pRes!=0 ); assert( *pRes==0 || *pRes==1 ); assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); - invalidateOverflowCache(pCur); - pCur->atLast = 0; + pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl); if( pCur->eState!=CURSOR_VALID ){ if( ALWAYS(pCur->eState>=CURSOR_REQUIRESEEK) ){ rc = btreeRestoreCursorPosition(pCur); @@ -4917,7 +4921,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ moveToParent(pCur); } pCur->info.nSize = 0; - pCur->validNKey = 0; + pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); pCur->aiIdx[pCur->iPage]--; pPage = pCur->apPage[pCur->iPage]; @@ -6942,7 +6946,7 @@ int sqlite3BtreeInsert( } assert( cursorHoldsMutex(pCur) ); - assert( pCur->wrFlag && pBt->inTransaction==TRANS_WRITE + assert( (pCur->curFlags & BTCF_WriteFlag)!=0 && pBt->inTransaction==TRANS_WRITE && (pBt->btsFlags & BTS_READ_ONLY)==0 ); assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); @@ -6975,7 +6979,7 @@ int sqlite3BtreeInsert( /* If the cursor is currently on the last row and we are appending a ** new row onto the end, set the "loc" to avoid an unnecessary btreeMoveto() ** call */ - if( pCur->validNKey && nKey>0 && pCur->info.nKey==nKey-1 ){ + if( (pCur->curFlags&BTCF_ValidNKey)!=0 && nKey>0 && pCur->info.nKey==nKey-1 ){ loc = -1; } } @@ -7028,7 +7032,7 @@ int sqlite3BtreeInsert( /* If no error has occurred and pPage has an overflow cell, call balance() ** to redistribute the cells within the tree. Since balance() may move - ** the cursor, zero the BtCursor.info.nSize and BtCursor.validNKey + ** the cursor, zero the BtCursor.info.nSize and BTCF_ValidNKey ** variables. ** ** Previous versions of SQLite called moveToRoot() to move the cursor @@ -7048,7 +7052,7 @@ int sqlite3BtreeInsert( */ pCur->info.nSize = 0; if( rc==SQLITE_OK && pPage->nOverflow ){ - pCur->validNKey = 0; + pCur->curFlags &= ~(BTCF_ValidNKey); rc = balance(pCur); /* Must make sure nOverflow is reset to zero even if the balance() @@ -7080,7 +7084,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){ assert( cursorHoldsMutex(pCur) ); assert( pBt->inTransaction==TRANS_WRITE ); assert( (pBt->btsFlags & BTS_READ_ONLY)==0 ); - assert( pCur->wrFlag ); + assert( pCur->curFlags & BTCF_WriteFlag ); assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); assert( !hasReadConflicts(p, pCur->pgnoRoot) ); @@ -8384,7 +8388,7 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ int rc; assert( cursorHoldsMutex(pCsr) ); assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) ); - assert( pCsr->isIncrblobHandle ); + assert( pCsr->curFlags & BTCF_Incrblob ); rc = restoreCursorPosition(pCsr); if( rc!=SQLITE_OK ){ @@ -8413,7 +8417,7 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ ** (d) there are no conflicting read-locks, and ** (e) the cursor points at a valid row of an intKey table. */ - if( !pCsr->wrFlag ){ + if( (pCsr->curFlags & BTCF_WriteFlag)==0 ){ return SQLITE_READONLY; } assert( (pCsr->pBt->btsFlags & BTS_READ_ONLY)==0 @@ -8429,7 +8433,7 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ ** Mark this cursor as an incremental blob cursor. */ void sqlite3BtreeIncrblobCursor(BtCursor *pCur){ - pCur->isIncrblobHandle = 1; + pCur->curFlags |= BTCF_Incrblob; } #endif diff --git a/src/btreeInt.h b/src/btreeInt.h index a41d8ebb55..dff07f145e 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -496,29 +496,30 @@ struct BtCursor { BtShared *pBt; /* The BtShared this cursor points to */ BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */ -#ifndef SQLITE_OMIT_INCRBLOB - int nOvflAlloc; /* Allocated size of aOverflow[] array */ - u8 bOvflValid; /* True if size and contents of aOverflow[] valid */ Pgno *aOverflow; /* Cache of overflow page locations */ -#endif - Pgno pgnoRoot; /* The root page of this tree */ CellInfo info; /* A parse of the cell we are pointing at */ - i64 nKey; /* Size of pKey, or last integer key */ - void *pKey; /* Saved key that was cursor's last known position */ + i64 nKey; /* Size of pKey, or last integer key */ + void *pKey; /* Saved key that was cursor last known position */ + Pgno pgnoRoot; /* The root page of this tree */ + int nOvflAlloc; /* Allocated size of aOverflow[] array */ int skipNext; /* Prev() is noop if negative. Next() is noop if positive */ - u8 wrFlag; /* True if writable */ - u8 atLast; /* Cursor pointing to the last entry */ - u8 validNKey; /* True if info.nKey is valid */ + u8 curFlags; /* zero or more BTCF_* flags defined below */ u8 eState; /* One of the CURSOR_XXX constants (see below) */ -#ifndef SQLITE_OMIT_INCRBLOB - u8 isIncrblobHandle; /* True if this cursor is an incr. io handle */ -#endif u8 hints; /* As configured by CursorSetHints() */ i16 iPage; /* Index of current page in apPage */ u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */ MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */ }; +/* +** Legal values for BtCursor.curFlags +*/ +#define BTCF_ValidNKey 0x01 /* True if info.nKey is valid */ +#define BTCF_ValidOvfl 0x02 /* True if aOverflow is valid */ +#define BTCF_AtLast 0x04 /* Cursor is pointing ot the last entry */ +#define BTCF_WriteFlag 0x08 /* True if a write cursor */ +#define BTCF_Incrblob 0x10 /* True if an incremental I/O handle */ + /* ** Potential values for BtCursor.eState. ** diff --git a/src/test_btree.c b/src/test_btree.c index db72889b2a..dfe77051b6 100644 --- a/src/test_btree.c +++ b/src/test_btree.c @@ -51,7 +51,7 @@ void sqlite3BtreeCursorList(Btree *p){ BtShared *pBt = p->pBt; for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ MemPage *pPage = pCur->apPage[pCur->iPage]; - char *zMode = pCur->wrFlag ? "rw" : "ro"; + char *zMode = (pCur->curFlags & BTCF_WriteFlag) ? "rw" : "ro"; sqlite3DebugPrintf("CURSOR %p rooted at %4d(%s) currently at %d.%d%s\n", pCur, pCur->pgnoRoot, zMode, pPage ? pPage->pgno : 0, pCur->aiIdx[pCur->iPage], From 926345e02761db4fc92b08568cc4c3a80c07953c Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 11 Mar 2014 23:44:10 +0000 Subject: [PATCH 03/17] Remove a stray C99-style comment. FossilOrigin-Name: f500e87d6ec6fa43c13f4e94edf32789f36e4233 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 1 - 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 24561347ec..ff09351dd2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Combine\sthe\svarious\sboolean\sfields\sof\sthe\sBtCursor\sobject\sinto\sa\ssingle\nbit-vector.\s\sThis\sallows\ssetting\sor\sclearing\smore\sthan\sone\sboolean\sat\sa\ntime\sand\smakes\sthe\soverflow-pgno-cache\sbranch\sfaster\sthan\strunk\son\s\nspeedtest1. -D 2014-03-11T23:40:44.961 +C Remove\sa\sstray\sC99-style\scomment. +D 2014-03-11T23:44:10.719 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -164,7 +164,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c 225a3f4d5511d4f5eab38a686f6c7e22290739f3 +F src/btree.c 33b5ad54a14c2b62e8adbc7656dec2b7cd760cbf F src/btree.h 6b0c1a3f0937f9852ec727c820e71dbdd4bd0b27 F src/btreeInt.h d1784d1e17d08d29e890190dbb9836fa64573381 F src/build.c 0d50ef95aad63f4c4fc47f3fa2670d4557c45db0 @@ -1156,7 +1156,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P da59198505990a4fe832be7932117c7e014955b7 -R a9a97bb8415d8a76adacb051af2ccc88 +P 968fec44d7fde3adbd3e9603e4282351f0d4bda1 +R c766c2eb192c274bbd3dc0af3849118d U drh -Z 90b8a93448c14945f126312bc79eea6f +Z 264233dee2a1cd950306c0e6dc59ee29 diff --git a/manifest.uuid b/manifest.uuid index 6cfc27f694..4c7b90b821 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -968fec44d7fde3adbd3e9603e4282351f0d4bda1 \ No newline at end of file +f500e87d6ec6fa43c13f4e94edf32789f36e4233 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index bd1a0e1c75..045e8ba2fd 100644 --- a/src/btree.c +++ b/src/btree.c @@ -4337,7 +4337,6 @@ static int moveToRoot(BtCursor *pCur){ assert( CURSOR_INVALID < CURSOR_REQUIRESEEK ); assert( CURSOR_VALID < CURSOR_REQUIRESEEK ); assert( CURSOR_FAULT > CURSOR_REQUIRESEEK ); -// invalidateOverflowCache(pCur); if( pCur->eState>=CURSOR_REQUIRESEEK ){ if( pCur->eState==CURSOR_FAULT ){ assert( pCur->skipNext!=SQLITE_OK ); From 9bc21b535e9b5578fb4a8ef77f58d0f392a437af Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 20 Mar 2014 18:56:35 +0000 Subject: [PATCH 04/17] Only use the direct-overflow-read optimization if all data from the overflow page in question is being read. FossilOrigin-Name: d8e1f75ddf10f3c0b21acd5455f90fdcea54a948 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/btree.c | 4 ++++ test/func.test | 12 +++++++----- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index ff09351dd2..751024e857 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sa\sstray\sC99-style\scomment. -D 2014-03-11T23:44:10.719 +C Only\suse\sthe\sdirect-overflow-read\soptimization\sif\sall\sdata\sfrom\sthe\soverflow\spage\sin\squestion\sis\sbeing\sread. +D 2014-03-20T18:56:35.309 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -164,7 +164,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c 33b5ad54a14c2b62e8adbc7656dec2b7cd760cbf +F src/btree.c 0384d399cfb12b3767edec355f00996658bb093e F src/btree.h 6b0c1a3f0937f9852ec727c820e71dbdd4bd0b27 F src/btreeInt.h d1784d1e17d08d29e890190dbb9836fa64573381 F src/build.c 0d50ef95aad63f4c4fc47f3fa2670d4557c45db0 @@ -574,7 +574,7 @@ F test/fts4merge4.test c19c85ca1faa7b6d536832b49c12e1867235f584 F test/fts4noti.test aed33ba44808852dcb24bf70fa132e7bf530f057 F test/fts4unicode.test 01ec3fe2a7c3cfff3b4c0581b83caa11b33efa36 F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d -F test/func.test a21814945d32137412b553d98ad2107f9b2173a9 +F test/func.test c2cbfc23d554c5bf8678d0fb271aa4f8ef94839c F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f F test/func3.test dbccee9133cfef1473c59ec07b5f0262b9d72f9a F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f @@ -1156,7 +1156,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 968fec44d7fde3adbd3e9603e4282351f0d4bda1 -R c766c2eb192c274bbd3dc0af3849118d -U drh -Z 264233dee2a1cd950306c0e6dc59ee29 +P f500e87d6ec6fa43c13f4e94edf32789f36e4233 +R 97d65ef8b8853428f883a03b9234ff63 +U dan +Z c025d7be55b561d9bf0252bb6230f9e0 diff --git a/manifest.uuid b/manifest.uuid index 4c7b90b821..16aed852aa 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f500e87d6ec6fa43c13f4e94edf32789f36e4233 \ No newline at end of file +d8e1f75ddf10f3c0b21acd5455f90fdcea54a948 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 045e8ba2fd..cd2df05324 100644 --- a/src/btree.c +++ b/src/btree.c @@ -3951,6 +3951,7 @@ static int accessPayload( int iIdx = 0; MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */ BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */ + int bEnd; /* True if reading to end of data */ assert( pPage ); assert( pCur->eState==CURSOR_VALID ); @@ -3960,6 +3961,7 @@ static int accessPayload( getCellInfo(pCur); aPayload = pCur->info.pCell + pCur->info.nHeader; nKey = (pPage->intKey ? 0 : (int)pCur->info.nKey); + bEnd = (offset+amt==nKey+pCur->info.nData); if( NEVER(offset+amt > nKey+pCur->info.nData) || &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] @@ -4064,6 +4066,7 @@ static int accessPayload( ** 3) the database is file-backed, and ** 4) there is no open write-transaction, and ** 5) the database is not a WAL database, + ** 6) all data from the page is being read. ** ** then data can be read directly from the database file into the ** output buffer, bypassing the page-cache altogether. This speeds @@ -4071,6 +4074,7 @@ static int accessPayload( */ if( (eOp&0x01)==0 /* (1) */ && offset==0 /* (2) */ + && (bEnd || a==ovflSize) /* (6) */ && pBt->inTransaction==TRANS_READ /* (4) */ && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */ && pBt->pPage1->aData[19]==0x01 /* (5) */ diff --git a/test/func.test b/test/func.test index 0fafd1828d..e3cec32153 100644 --- a/test/func.test +++ b/test/func.test @@ -1301,11 +1301,13 @@ do_test func-29.3 { db eval {SELECT typeof(+x) FROM t29 ORDER BY id} } {integer null real blob text} if {[permutation] != "mmap"} { - do_test func-29.4 { - set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1] - if {$x>100} {set x many} - set x - } {many} + ifcapable !direct_read { + do_test func-29.4 { + set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1] + if {$x>100} {set x many} + set x + } {many} + } } do_test func-29.5 { db close From 7a4b1642a732f6ef183931bb51dc5b5a0dcdb502 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 29 Mar 2014 21:16:07 +0000 Subject: [PATCH 05/17] Experiments in picking better query plans, especially when the usage of one index is a subset of another. FossilOrigin-Name: 8f869ca7a6eaa9ca7a08102290e6c606735f9090 --- manifest | 15 +++-- manifest.uuid | 2 +- src/where.c | 176 +++++++++++++++++++++++++++++++------------------- 3 files changed, 119 insertions(+), 74 deletions(-) diff --git a/manifest b/manifest index 52d212de1d..9ef65fa6b9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Disable\sthe\swal64k.test\sscript\sfor\snon-unix\ssystems\ssince\sit\sdepends\son\nunix-only\sfeatures. -D 2014-03-28T14:41:35.536 +C Experiments\sin\spicking\sbetter\squery\splans,\sespecially\swhen\sthe\susage\sof\sone\nindex\sis\sa\ssubset\sof\sanother. +D 2014-03-29T21:16:07.103 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -291,7 +291,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 -F src/where.c 7d539cedb1c6a6d6b5d2075b8fea3a48db4838eb +F src/where.c 26c6f6260b0cc2b0038dcc68ace0d7db20c7dcee F src/whereInt.h 2564055b440e44ebec8b47f237bbccae6719b7af F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1159,7 +1159,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P a4e47150f32b3a4120b1f89ccc66d633d829e3bb -R 578568415288cd31fe0adba6128329da +P 27deb6e49bcc76714dbdc61b34748603155ac770 +R 1df7985395668b26c614cc4e641f29c8 +T *branch * query-plan-experiments +T *sym-query-plan-experiments * +T -sym-trunk * U drh -Z 045e2748905f8bd05ecf1197b97d7f20 +Z 1c5ff3f986da6bbe350c60cf72c963dd diff --git a/manifest.uuid b/manifest.uuid index d9c988d4d5..05916c40aa 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -27deb6e49bcc76714dbdc61b34748603155ac770 \ No newline at end of file +8f869ca7a6eaa9ca7a08102290e6c606735f9090 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 93ee8c59c3..c2b2cf2111 100644 --- a/src/where.c +++ b/src/where.c @@ -3712,59 +3712,24 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ } /* -** Insert or replace a WhereLoop entry using the template supplied. +** Search the list of WhereLoops in *ppPrev looking for one that can be +** supplanted by pTemplate. ** -** An existing WhereLoop entry might be overwritten if the new template -** is better and has fewer dependencies. Or the template will be ignored -** and no insert will occur if an existing WhereLoop is faster and has -** fewer dependencies than the template. Otherwise a new WhereLoop is -** added based on the template. +** Return NULL if the WhereLoop list contains an entry that can supplant +** pTemplate, in other words if pTemplate does not belong on the list. ** -** If pBuilder->pOrSet is not NULL then we only care about only the -** prerequisites and rRun and nOut costs of the N best loops. That -** information is gathered in the pBuilder->pOrSet object. This special -** processing mode is used only for OR clause processing. +** If pX is a WhereLoop that pTemplate can supplant, then return the +** link that points to pX. ** -** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we -** still might overwrite similar loops with the new template if the -** template is better. Loops may be overwritten if the following -** conditions are met: -** -** (1) They have the same iTab. -** (2) They have the same iSortIdx. -** (3) The template has same or fewer dependencies than the current loop -** (4) The template has the same or lower cost than the current loop -** (5) The template uses more terms of the same index but has no additional -** dependencies +** If pTemplate cannot supplant any existing element of the list but needs +** to be added to the list, then return a pointer to the tail of the list. */ -static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ - WhereLoop **ppPrev, *p, *pNext = 0; - WhereInfo *pWInfo = pBuilder->pWInfo; - sqlite3 *db = pWInfo->pParse->db; - - /* If pBuilder->pOrSet is defined, then only keep track of the costs - ** and prereqs. - */ - if( pBuilder->pOrSet!=0 ){ -#if WHERETRACE_ENABLED - u16 n = pBuilder->pOrSet->n; - int x = -#endif - whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun, - pTemplate->nOut); -#if WHERETRACE_ENABLED /* 0x8 */ - if( sqlite3WhereTrace & 0x8 ){ - sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n); - whereLoopPrint(pTemplate, pBuilder->pWC); - } -#endif - return SQLITE_OK; - } - - /* Search for an existing WhereLoop to overwrite, or which takes - ** priority over pTemplate. - */ - for(ppPrev=&pWInfo->pLoops, p=*ppPrev; p; ppPrev=&p->pNextLoop, p=*ppPrev){ +static WhereLoop **whereLoopFindLesser( + WhereLoop **ppPrev, + const WhereLoop *pTemplate +){ + WhereLoop *p; + for(p=(*ppPrev); p; ppPrev=&p->pNextLoop, p=*ppPrev){ if( p->iTab!=pTemplate->iTab || p->iSortIdx!=pTemplate->iSortIdx ){ /* If either the iTab or iSortIdx values for two WhereLoop are different ** then those WhereLoops need to be considered separately. Neither is @@ -3799,12 +3764,10 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ ){ /* Overwrite an existing WhereLoop with an similar one that uses ** more terms of the index */ - pNext = p->pNextLoop; break; }else{ - /* pTemplate is not helpful. - ** Return without changing or adding anything */ - goto whereLoopInsert_noop; + /* There is an existing WhereLoop that is better than pTemplate */ + return 0; } } if( (p->prereq & pTemplate->prereq)==pTemplate->prereq @@ -3816,10 +3779,79 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ ** or (4) number of output rows, and is no worse in any of those ** categories. */ assert( p->rSetup>=pTemplate->rSetup ); /* SETUP-INVARIANT above */ - pNext = p->pNextLoop; break; } } + return ppPrev; +} + +/* +** Insert or replace a WhereLoop entry using the template supplied. +** +** An existing WhereLoop entry might be overwritten if the new template +** is better and has fewer dependencies. Or the template will be ignored +** and no insert will occur if an existing WhereLoop is faster and has +** fewer dependencies than the template. Otherwise a new WhereLoop is +** added based on the template. +** +** If pBuilder->pOrSet is not NULL then we care about only the +** prerequisites and rRun and nOut costs of the N best loops. That +** information is gathered in the pBuilder->pOrSet object. This special +** processing mode is used only for OR clause processing. +** +** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we +** still might overwrite similar loops with the new template if the +** template is better. Loops may be overwritten if the following +** conditions are met: +** +** (1) They have the same iTab. +** (2) They have the same iSortIdx. +** (3) The template has same or fewer dependencies than the current loop +** (4) The template has the same or lower cost than the current loop +** (5) The template uses more terms of the same index but has no additional +** dependencies +*/ +static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ + WhereLoop **ppPrev, *p; + WhereInfo *pWInfo = pBuilder->pWInfo; + sqlite3 *db = pWInfo->pParse->db; + + /* If pBuilder->pOrSet is defined, then only keep track of the costs + ** and prereqs. + */ + if( pBuilder->pOrSet!=0 ){ +#if WHERETRACE_ENABLED + u16 n = pBuilder->pOrSet->n; + int x = +#endif + whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun, + pTemplate->nOut); +#if WHERETRACE_ENABLED /* 0x8 */ + if( sqlite3WhereTrace & 0x8 ){ + sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n); + whereLoopPrint(pTemplate, pBuilder->pWC); + } +#endif + return SQLITE_OK; + } + + /* Look for an existing WhereLoop to replace with pTemplate + */ + ppPrev = whereLoopFindLesser(&pWInfo->pLoops, pTemplate); + + if( ppPrev==0 ){ + /* There already exists a WhereLoop on the list that is better + ** than pTemplate, so just ignore pTemplate */ +#if WHERETRACE_ENABLED /* 0x8 */ + if( sqlite3WhereTrace & 0x8 ){ + sqlite3DebugPrintf("ins-noop: "); + whereLoopPrint(pTemplate, pBuilder->pWC); + } +#endif + return SQLITE_OK; + }else{ + p = *ppPrev; + } /* If we reach this point it means that either p[] should be overwritten ** with pTemplate[] if p[] exists, or if p==NULL then allocate a new @@ -3836,13 +3868,33 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ } #endif if( p==0 ){ - p = sqlite3DbMallocRaw(db, sizeof(WhereLoop)); + /* Allocate a new WhereLoop to add to the end of the list */ + *ppPrev = p = sqlite3DbMallocRaw(db, sizeof(WhereLoop)); if( p==0 ) return SQLITE_NOMEM; whereLoopInit(p); + p->pNextLoop = 0; + }else{ + /* We will be overwriting WhereLoop p[]. But before we do, first + ** go through the rest of the list and delete any other entries besides + ** p[] that are also supplated by pTemplate */ + WhereLoop **ppTail = &p->pNextLoop; + WhereLoop *pToDel; + while( *ppTail ){ + ppTail = whereLoopFindLesser(ppTail, pTemplate); + if( NEVER(ppTail==0) ) break; + pToDel = *ppTail; + if( pToDel==0 ) break; + *ppTail = pToDel->pNextLoop; +#if WHERETRACE_ENABLED /* 0x8 */ + if( sqlite3WhereTrace & 0x8 ){ + sqlite3DebugPrintf("ins-del: "); + whereLoopPrint(pToDel, pBuilder->pWC); + } +#endif + whereLoopDelete(db, pToDel); + } } whereLoopXfer(db, p, pTemplate); - p->pNextLoop = pNext; - *ppPrev = p; if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){ Index *pIndex = p->u.btree.pIndex; if( pIndex && pIndex->tnum==0 ){ @@ -3850,16 +3902,6 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ } } return SQLITE_OK; - - /* Jump here if the insert is a no-op */ -whereLoopInsert_noop: -#if WHERETRACE_ENABLED /* 0x8 */ - if( sqlite3WhereTrace & 0x8 ){ - sqlite3DebugPrintf("ins-noop: "); - whereLoopPrint(pTemplate, pBuilder->pWC); - } -#endif - return SQLITE_OK; } /* From 53cd10afcd77c4ff2296999a9fe5116c51333688 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 31 Mar 2014 18:24:18 +0000 Subject: [PATCH 06/17] Make sure that an index that covers a proper superset of the WHERE clause terms of some other index has a lower cost than the other index. FossilOrigin-Name: ea8b0910040198751551b0b960e6b783913607df --- manifest | 15 ++++---- manifest.uuid | 2 +- src/where.c | 99 ++++++++++++++++++++++++++++++++++----------------- 3 files changed, 74 insertions(+), 42 deletions(-) diff --git a/manifest b/manifest index 9ef65fa6b9..ac1faf182f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Experiments\sin\spicking\sbetter\squery\splans,\sespecially\swhen\sthe\susage\sof\sone\nindex\sis\sa\ssubset\sof\sanother. -D 2014-03-29T21:16:07.103 +C Make\ssure\sthat\san\sindex\sthat\scovers\sa\sproper\ssuperset\sof\sthe\sWHERE\sclause\nterms\sof\ssome\sother\sindex\shas\sa\slower\scost\sthan\sthe\sother\sindex. +D 2014-03-31T18:24:18.867 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -291,7 +291,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 -F src/where.c 26c6f6260b0cc2b0038dcc68ace0d7db20c7dcee +F src/where.c 50ac3154473b5c8df15c7b8dbd19da385fa859e1 F src/whereInt.h 2564055b440e44ebec8b47f237bbccae6719b7af F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1159,10 +1159,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 27deb6e49bcc76714dbdc61b34748603155ac770 -R 1df7985395668b26c614cc4e641f29c8 -T *branch * query-plan-experiments -T *sym-query-plan-experiments * -T -sym-trunk * +P 8f869ca7a6eaa9ca7a08102290e6c606735f9090 +R 76b8d8088ba83ec014dc8bf476fa6749 U drh -Z 1c5ff3f986da6bbe350c60cf72c963dd +Z ecebe13d1c9f7ea1da970c5f6118dc52 diff --git a/manifest.uuid b/manifest.uuid index 05916c40aa..649fc9530b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8f869ca7a6eaa9ca7a08102290e6c606735f9090 \ No newline at end of file +ea8b0910040198751551b0b960e6b783913607df \ No newline at end of file diff --git a/src/where.c b/src/where.c index c2b2cf2111..38c3712977 100644 --- a/src/where.c +++ b/src/where.c @@ -3711,6 +3711,51 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ } } +/* +** Compare every WhereLoop X on the list p against pTemplate. If: +** +** (1) both X and pTemplate refer to the same table, and +** (2) both X and pTemplate use a single index, and +** (3) pTemplate uses all the same WHERE clause terms as X plus +** at least one more term, +** +** then make sure the cost pTemplate is less than the cost of X, adjusting +** the cost of pTemplate downward if necessary. +** +** Example: When computing the query plan for the SELECT below: +** +** CREATE TABLE t1(a,b,c,d); +** CREATE INDEX t1abc ON t1(a,b,c); +** CREATE INDEX t1bc ON t1(b,c); +** SELECT d FROM t1 WHERE a=? AND b=? AND c>=? ORDER BY c; +** +** Make sure the cost of using three three columns of index t1abc is less +** than the cost of using both columns of t1bc. +*/ +static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){ + if( (pTemplate->wsFlags & WHERE_INDEXED)==0 ) return; + if( pTemplate->nLTerm==0 ) return; + for(; p; p=p->pNextLoop){ + if( p->iTab==pTemplate->iTab + && (p->wsFlags & WHERE_INDEXED)!=0 + && p->nLTermnLTerm + && (p->rRunrRun || (p->rRun==pTemplate->rRun && + p->nOut<=pTemplate->nOut)) + ){ + int i, j; + for(j=0, i=p->nLTerm-1; i>=0 && j>=0; i--){ + for(j=pTemplate->nLTerm-1; j>=0; j--){ + if( pTemplate->aLTerm[j]==p->aLTerm[i] ) break; + } + } + if( j>=0 ){ + pTemplate->rRun = p->rRun; + pTemplate->nOut = p->nOut - 1; + } + } + } +} + /* ** Search the list of WhereLoops in *ppPrev looking for one that can be ** supplanted by pTemplate. @@ -3747,39 +3792,30 @@ static WhereLoop **whereLoopFindLesser( ** rSetup. Call this SETUP-INVARIANT */ assert( p->rSetup>=pTemplate->rSetup ); - if( (p->prereq & pTemplate->prereq)==p->prereq - && p->rSetup<=pTemplate->rSetup - && p->rRun<=pTemplate->rRun - && p->nOut<=pTemplate->nOut + /* If existing WhereLoop p is better than pTemplate, pTemplate can be + ** discarded. WhereLoop p is better if: + ** (1) p has no more dependencies than pTemplate, and + ** (2) p has an equal or lower cost than pTemplate + */ + if( (p->prereq & pTemplate->prereq)==p->prereq /* (1) */ + && p->rSetup<=pTemplate->rSetup /* (2a) */ + && p->rRun<=pTemplate->rRun /* (2b) */ + && p->nOut<=pTemplate->nOut /* (2c) */ ){ - /* This branch taken when p is equal or better than pTemplate in - ** all of (1) dependencies (2) setup-cost, (3) run-cost, and - ** (4) number of output rows. */ - assert( p->rSetup==pTemplate->rSetup ); - if( p->prereq==pTemplate->prereq - && p->nLTermnLTerm - && (p->wsFlags & pTemplate->wsFlags & WHERE_INDEXED)!=0 - && (p->u.btree.pIndex==pTemplate->u.btree.pIndex - || pTemplate->rRun+p->nLTerm<=p->rRun+pTemplate->nLTerm) - ){ - /* Overwrite an existing WhereLoop with an similar one that uses - ** more terms of the index */ - break; - }else{ - /* There is an existing WhereLoop that is better than pTemplate */ - return 0; - } + return 0; /* Discard pTemplate */ } - if( (p->prereq & pTemplate->prereq)==pTemplate->prereq - && p->rRun>=pTemplate->rRun - && p->nOut>=pTemplate->nOut + + /* If pTemplate is always better than p, then cause p to be overwritten + ** with pTemplate. pTemplate is better than p if: + ** (1) pTemplate has no more dependences than p, and + ** (2) pTemplate has an equal or lower cost than p. + */ + if( (p->prereq & pTemplate->prereq)==pTemplate->prereq /* (1) */ + && p->rRun>=pTemplate->rRun /* (2a) */ + && p->nOut>=pTemplate->nOut /* (2b) */ ){ - /* Overwrite an existing WhereLoop with a better one: one that is - ** better at one of (1) dependencies, (2) setup-cost, (3) run-cost - ** or (4) number of output rows, and is no worse in any of those - ** categories. */ assert( p->rSetup>=pTemplate->rSetup ); /* SETUP-INVARIANT above */ - break; + break; /* Cause p to be overwritten by pTemplate */ } } return ppPrev; @@ -3801,15 +3837,13 @@ static WhereLoop **whereLoopFindLesser( ** ** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we ** still might overwrite similar loops with the new template if the -** template is better. Loops may be overwritten if the following +** new template is better. Loops may be overwritten if the following ** conditions are met: ** ** (1) They have the same iTab. ** (2) They have the same iSortIdx. ** (3) The template has same or fewer dependencies than the current loop ** (4) The template has the same or lower cost than the current loop -** (5) The template uses more terms of the same index but has no additional -** dependencies */ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ WhereLoop **ppPrev, *p; @@ -3837,6 +3871,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ /* Look for an existing WhereLoop to replace with pTemplate */ + whereLoopAdjustCost(pWInfo->pLoops, pTemplate); ppPrev = whereLoopFindLesser(&pWInfo->pLoops, pTemplate); if( ppPrev==0 ){ From 3fb183d2f7f83cdc9cb406dccbe97d731f1e0644 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 31 Mar 2014 19:49:00 +0000 Subject: [PATCH 07/17] Also make sure an index that is a proper subset of some other index has a higher cost than that other index. Add test cases. FossilOrigin-Name: b7830d232b073a197aa1092e78cb24e88cb10fd3 --- manifest | 13 +++-- manifest.uuid | 2 +- src/where.c | 68 +++++++++++++---------- test/whereH.test | 139 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 185 insertions(+), 37 deletions(-) create mode 100644 test/whereH.test diff --git a/manifest b/manifest index ac1faf182f..7824fe6caa 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\sthat\san\sindex\sthat\scovers\sa\sproper\ssuperset\sof\sthe\sWHERE\sclause\nterms\sof\ssome\sother\sindex\shas\sa\slower\scost\sthan\sthe\sother\sindex. -D 2014-03-31T18:24:18.867 +C Also\smake\ssure\san\sindex\sthat\sis\sa\sproper\ssubset\sof\ssome\sother\sindex\shas\sa\nhigher\scost\sthan\sthat\sother\sindex.\s\sAdd\stest\scases. +D 2014-03-31T19:49:00.374 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -291,7 +291,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 -F src/where.c 50ac3154473b5c8df15c7b8dbd19da385fa859e1 +F src/where.c 182f16d91060418dfcc7401d24e43d8ec24e026c F src/whereInt.h 2564055b440e44ebec8b47f237bbccae6719b7af F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1093,6 +1093,7 @@ F test/whereD.test 6c2feb79ef1f68381b07f39017fe5f9b96da8d62 F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7 F test/whereG.test eb3a46b3eaf38e25e3013433b2db8a25a866c215 +F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2 F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31 F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c @@ -1159,7 +1160,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 8f869ca7a6eaa9ca7a08102290e6c606735f9090 -R 76b8d8088ba83ec014dc8bf476fa6749 +P ea8b0910040198751551b0b960e6b783913607df +R 176e1ff66c14893be5de17b3890f1972 U drh -Z ecebe13d1c9f7ea1da970c5f6118dc52 +Z 3bf4657410567331f2f5534ba4eae60e diff --git a/manifest.uuid b/manifest.uuid index 649fc9530b..a0ffd4b3db 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ea8b0910040198751551b0b960e6b783913607df \ No newline at end of file +b7830d232b073a197aa1092e78cb24e88cb10fd3 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 38c3712977..9882b4873f 100644 --- a/src/where.c +++ b/src/where.c @@ -3712,46 +3712,54 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ } /* -** Compare every WhereLoop X on the list p against pTemplate. If: +** Return TRUE if the set of WHERE clause terms used by pA is a proper +** subset of the WHERE clause terms used by pB. +*/ +static int whereLoopProperSubset(const WhereLoop *pA, const WhereLoop *pB){ + int i, j; + if( pA->nLTerm>=pB->nLTerm ) return 0; + for(j=0, i=pA->nLTerm-1; i>=0 && j>=0; i--){ + for(j=pB->nLTerm-1; j>=0; j--){ + if( pB->aLTerm[j]==pA->aLTerm[i] ) break; + } + } + return j>=0; +} + +/* +** Try to adjust the cost of WhereLoop pTemplate upwards or downwards so +** that: ** -** (1) both X and pTemplate refer to the same table, and -** (2) both X and pTemplate use a single index, and -** (3) pTemplate uses all the same WHERE clause terms as X plus -** at least one more term, +** (1) pTemplate costs less than any other WhereLoops that are a proper +** subset of pTemplate ** -** then make sure the cost pTemplate is less than the cost of X, adjusting -** the cost of pTemplate downward if necessary. +** (2) pTemplate costs more than any other WhereLoops for which pTemplate +** is a proper subset. ** -** Example: When computing the query plan for the SELECT below: -** -** CREATE TABLE t1(a,b,c,d); -** CREATE INDEX t1abc ON t1(a,b,c); -** CREATE INDEX t1bc ON t1(b,c); -** SELECT d FROM t1 WHERE a=? AND b=? AND c>=? ORDER BY c; -** -** Make sure the cost of using three three columns of index t1abc is less -** than the cost of using both columns of t1bc. +** To say "WhereLoop X is a proper subset of Y" means that X uses fewer +** WHERE clause terms than Y and that every WHERE clause term used by X is +** also used by Y. */ static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){ if( (pTemplate->wsFlags & WHERE_INDEXED)==0 ) return; - if( pTemplate->nLTerm==0 ) return; for(; p; p=p->pNextLoop){ - if( p->iTab==pTemplate->iTab - && (p->wsFlags & WHERE_INDEXED)!=0 - && p->nLTermnLTerm + if( p->iTab!=pTemplate->iTab ) continue; + if( (p->wsFlags & WHERE_INDEXED)==0 ) continue; + if( p->nLTermnLTerm && (p->rRunrRun || (p->rRun==pTemplate->rRun && p->nOut<=pTemplate->nOut)) + && whereLoopProperSubset(p, pTemplate) ){ - int i, j; - for(j=0, i=p->nLTerm-1; i>=0 && j>=0; i--){ - for(j=pTemplate->nLTerm-1; j>=0; j--){ - if( pTemplate->aLTerm[j]==p->aLTerm[i] ) break; - } - } - if( j>=0 ){ - pTemplate->rRun = p->rRun; - pTemplate->nOut = p->nOut - 1; - } + pTemplate->rRun = p->rRun; + pTemplate->nOut = p->nOut - 1; + }else + if( p->nLTerm>pTemplate->nLTerm + && (p->rRun>pTemplate->rRun || (p->rRun==pTemplate->rRun && + p->nOut>=pTemplate->nOut)) + && whereLoopProperSubset(pTemplate, p) + ){ + pTemplate->rRun = p->rRun; + pTemplate->nOut = p->nOut + 1; } } } diff --git a/test/whereH.test b/test/whereH.test new file mode 100644 index 0000000000..c252fe1ef7 --- /dev/null +++ b/test/whereH.test @@ -0,0 +1,139 @@ +# 2014-03-31 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# Test cases for query planning decisions where one candidate index +# covers a proper superset of the WHERE clause terms of another +# candidate index. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +do_execsql_test whereH-1.1 { + CREATE TABLE t1(a,b,c,d); + CREATE INDEX t1abc ON t1(a,b,c); + CREATE INDEX t1bc ON t1(b,c); + + EXPLAIN QUERY PLAN + SELECT d FROM t1 WHERE a=? AND b=? AND c>=? ORDER BY c; +} {/INDEX t1abc /} +do_execsql_test whereH-1.2 { + EXPLAIN QUERY PLAN + SELECT d FROM t1 WHERE a=? AND b=? AND c>=? ORDER BY c; +} {~/TEMP B-TREE FOR ORDER BY/} + +do_execsql_test whereH-2.1 { + DROP TABLE t1; + CREATE TABLE t1(a,b,c,d); + CREATE INDEX t1bc ON t1(b,c); + CREATE INDEX t1abc ON t1(a,b,c); + + EXPLAIN QUERY PLAN + SELECT d FROM t1 WHERE a=? AND b=? AND c>=? ORDER BY c; +} {/INDEX t1abc /} +do_execsql_test whereH-2.2 { + EXPLAIN QUERY PLAN + SELECT d FROM t1 WHERE a=? AND b=? AND c>=? ORDER BY c; +} {~/TEMP B-TREE FOR ORDER BY/} + +do_execsql_test whereH-3.1 { + DROP TABLE t1; + CREATE TABLE t1(a,b,c,d,e); + CREATE INDEX t1cd ON t1(c,d); + CREATE INDEX t1bcd ON t1(b,c,d); + CREATE INDEX t1abcd ON t1(a,b,c,d); + + EXPLAIN QUERY PLAN + SELECT d FROM t1 WHERE a=? AND b=? AND c=? AND d>=? ORDER BY d; +} {/INDEX t1abcd /} +do_execsql_test whereH-3.2 { + EXPLAIN QUERY PLAN + SELECT d FROM t1 WHERE a=? AND b=? AND c=? AND d>=? ORDER BY d; +} {~/TEMP B-TREE FOR ORDER BY/} + +do_execsql_test whereH-4.1 { + DROP TABLE t1; + CREATE TABLE t1(a,b,c,d,e); + CREATE INDEX t1cd ON t1(c,d); + CREATE INDEX t1abcd ON t1(a,b,c,d); + CREATE INDEX t1bcd ON t1(b,c,d); + + EXPLAIN QUERY PLAN + SELECT d FROM t1 WHERE a=? AND b=? AND c=? AND d>=? ORDER BY d; +} {/INDEX t1abcd /} +do_execsql_test whereH-4.2 { + EXPLAIN QUERY PLAN + SELECT d FROM t1 WHERE a=? AND b=? AND c=? AND d>=? ORDER BY d; +} {~/TEMP B-TREE FOR ORDER BY/} + +do_execsql_test whereH-5.1 { + DROP TABLE t1; + CREATE TABLE t1(a,b,c,d,e); + CREATE INDEX t1bcd ON t1(b,c,d); + CREATE INDEX t1cd ON t1(c,d); + CREATE INDEX t1abcd ON t1(a,b,c,d); + + EXPLAIN QUERY PLAN + SELECT d FROM t1 WHERE a=? AND b=? AND c=? AND d>=? ORDER BY d; +} {/INDEX t1abcd /} +do_execsql_test whereH-5.2 { + EXPLAIN QUERY PLAN + SELECT d FROM t1 WHERE a=? AND b=? AND c=? AND d>=? ORDER BY d; +} {~/TEMP B-TREE FOR ORDER BY/} + +do_execsql_test whereH-6.1 { + DROP TABLE t1; + CREATE TABLE t1(a,b,c,d,e); + CREATE INDEX t1bcd ON t1(b,c,d); + CREATE INDEX t1abcd ON t1(a,b,c,d); + CREATE INDEX t1cd ON t1(c,d); + + EXPLAIN QUERY PLAN + SELECT d FROM t1 WHERE a=? AND b=? AND c=? AND d>=? ORDER BY d; +} {/INDEX t1abcd /} +do_execsql_test whereH-6.2 { + EXPLAIN QUERY PLAN + SELECT d FROM t1 WHERE a=? AND b=? AND c=? AND d>=? ORDER BY d; +} {~/TEMP B-TREE FOR ORDER BY/} + +do_execsql_test whereH-7.1 { + DROP TABLE t1; + CREATE TABLE t1(a,b,c,d,e); + CREATE INDEX t1abcd ON t1(a,b,c,d); + CREATE INDEX t1bcd ON t1(b,c,d); + CREATE INDEX t1cd ON t1(c,d); + + EXPLAIN QUERY PLAN + SELECT d FROM t1 WHERE a=? AND b=? AND c=? AND d>=? ORDER BY d; +} {/INDEX t1abcd /} +do_execsql_test whereH-7.2 { + EXPLAIN QUERY PLAN + SELECT d FROM t1 WHERE a=? AND b=? AND c=? AND d>=? ORDER BY d; +} {~/TEMP B-TREE FOR ORDER BY/} + +do_execsql_test whereH-8.1 { + DROP TABLE t1; + CREATE TABLE t1(a,b,c,d,e); + CREATE INDEX t1abcd ON t1(a,b,c,d); + CREATE INDEX t1cd ON t1(c,d); + CREATE INDEX t1bcd ON t1(b,c,d); + + EXPLAIN QUERY PLAN + SELECT d FROM t1 WHERE a=? AND b=? AND c=? AND d>=? ORDER BY d; +} {/INDEX t1abcd /} +do_execsql_test whereH-8.2 { + EXPLAIN QUERY PLAN + SELECT d FROM t1 WHERE a=? AND b=? AND c=? AND d>=? ORDER BY d; +} {~/TEMP B-TREE FOR ORDER BY/} + + + +finish_test From d3c156638a227b72ecee81b8d87e539ca044102d Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 31 Mar 2014 20:05:20 +0000 Subject: [PATCH 08/17] Remove an unnecessary conditional. FossilOrigin-Name: 7473c4dfc10a47594affa6f4e071a08dc8838c0c --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 7824fe6caa..35a72e84b6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Also\smake\ssure\san\sindex\sthat\sis\sa\sproper\ssubset\sof\ssome\sother\sindex\shas\sa\nhigher\scost\sthan\sthat\sother\sindex.\s\sAdd\stest\scases. -D 2014-03-31T19:49:00.374 +C Remove\san\sunnecessary\sconditional. +D 2014-03-31T20:05:20.135 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -291,7 +291,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 -F src/where.c 182f16d91060418dfcc7401d24e43d8ec24e026c +F src/where.c 7b5010f5c4d6cf81a8d6fcc9e09b05faad71b395 F src/whereInt.h 2564055b440e44ebec8b47f237bbccae6719b7af F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1160,7 +1160,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P ea8b0910040198751551b0b960e6b783913607df -R 176e1ff66c14893be5de17b3890f1972 +P b7830d232b073a197aa1092e78cb24e88cb10fd3 +R ddf1c9d2d849c5f13c78d81687d216d7 U drh -Z 3bf4657410567331f2f5534ba4eae60e +Z 7ba197d4f98bb2ab782217a2f7675fd9 diff --git a/manifest.uuid b/manifest.uuid index a0ffd4b3db..2b145830ca 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b7830d232b073a197aa1092e78cb24e88cb10fd3 \ No newline at end of file +7473c4dfc10a47594affa6f4e071a08dc8838c0c \ No newline at end of file diff --git a/src/where.c b/src/where.c index 9882b4873f..299acbaf0f 100644 --- a/src/where.c +++ b/src/where.c @@ -3717,7 +3717,7 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ */ static int whereLoopProperSubset(const WhereLoop *pA, const WhereLoop *pB){ int i, j; - if( pA->nLTerm>=pB->nLTerm ) return 0; + assert( pA->nLTermnLTerm ); /* Checked by calling function */ for(j=0, i=pA->nLTerm-1; i>=0 && j>=0; i--){ for(j=pB->nLTerm-1; j>=0; j--){ if( pB->aLTerm[j]==pA->aLTerm[i] ) break; From 4c417181c218c1e469f86bb754045b4134189ee7 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 31 Mar 2014 23:57:41 +0000 Subject: [PATCH 09/17] Fix a compiler warning when SQLITE_DIRECT_OVERFLOW_READ is defined. Minor performance enhancement and size reduction. FossilOrigin-Name: 96385dc460545807a5c8fcf6280a971700f84866 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/btree.c | 9 +++++++-- src/btreeInt.h | 8 ++++---- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 1266012e4a..a1eded678c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sin\sthe\slatest\schanges\sand\sfixes\sfrom\strunk. -D 2014-03-31T22:03:32.269 +C Fix\sa\scompiler\swarning\swhen\sSQLITE_DIRECT_OVERFLOW_READ\sis\sdefined.\nMinor\sperformance\senhancement\sand\ssize\sreduction. +D 2014-03-31T23:57:41.627 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -164,9 +164,9 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c 33338d61b912b5219fc5b466db8e0d7385c0b18b +F src/btree.c b1d6309d6623f4ea8d9466aebd1ec84adc40cb9b F src/btree.h d79306df4ed9181b48916737fe8871a4392c4594 -F src/btreeInt.h d1784d1e17d08d29e890190dbb9836fa64573381 +F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3 F src/build.c 0d50ef95aad63f4c4fc47f3fa2670d4557c45db0 F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac @@ -1159,7 +1159,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P d8e1f75ddf10f3c0b21acd5455f90fdcea54a948 b3296267fb67b9f59719a37093253062edde3746 -R 6014daa58aba2f75bf5f17a4d16cbf23 +P f6211540c9d66a08dc580dd733e4f4a98968ae30 +R a9646e8cad6830bc030ac01ef7720050 U drh -Z 6a8ee270f5925545ed8c5f82edf09850 +Z be4271c513a3efe06acb17f300ec9933 diff --git a/manifest.uuid b/manifest.uuid index 36c381c508..e03a98f749 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f6211540c9d66a08dc580dd733e4f4a98968ae30 \ No newline at end of file +96385dc460545807a5c8fcf6280a971700f84866 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 9b50ebae4f..cbb968ad8b 100644 --- a/src/btree.c +++ b/src/btree.c @@ -3633,7 +3633,8 @@ static int btreeCursor( pCur->pKeyInfo = pKeyInfo; pCur->pBtree = p; pCur->pBt = pBt; - pCur->curFlags = wrFlag ? BTCF_WriteFlag : 0; + assert( wrFlag==0 || wrFlag==BTCF_WriteFlag ); + pCur->curFlags = wrFlag; pCur->pNext = pBt->pCursor; if( pCur->pNext ){ pCur->pNext->pPrev = pCur; @@ -3965,7 +3966,9 @@ static int accessPayload( int iIdx = 0; MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */ BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */ - int bEnd; /* True if reading to end of data */ +#ifdef SQLITE_DIRECT_OVERFLOW_READ + int bEnd; /* True if reading to end of data */ +#endif assert( pPage ); assert( pCur->eState==CURSOR_VALID ); @@ -3975,7 +3978,9 @@ static int accessPayload( getCellInfo(pCur); aPayload = pCur->info.pCell + pCur->info.nHeader; nKey = (pPage->intKey ? 0 : (int)pCur->info.nKey); +#ifdef SQLITE_DIRECT_OVERFLOW_READ bEnd = (offset+amt==nKey+pCur->info.nData); +#endif if( NEVER(offset+amt > nKey+pCur->info.nData) || &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] diff --git a/src/btreeInt.h b/src/btreeInt.h index dff07f145e..d1cdd46983 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -514,10 +514,10 @@ struct BtCursor { /* ** Legal values for BtCursor.curFlags */ -#define BTCF_ValidNKey 0x01 /* True if info.nKey is valid */ -#define BTCF_ValidOvfl 0x02 /* True if aOverflow is valid */ -#define BTCF_AtLast 0x04 /* Cursor is pointing ot the last entry */ -#define BTCF_WriteFlag 0x08 /* True if a write cursor */ +#define BTCF_WriteFlag 0x01 /* True if a write cursor */ +#define BTCF_ValidNKey 0x02 /* True if info.nKey is valid */ +#define BTCF_ValidOvfl 0x04 /* True if aOverflow is valid */ +#define BTCF_AtLast 0x08 /* Cursor is pointing ot the last entry */ #define BTCF_Incrblob 0x10 /* True if an incremental I/O handle */ /* From a38c9516e847f90d914dce229b7c601698e94102 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 1 Apr 2014 01:24:34 +0000 Subject: [PATCH 10/17] Remove an unnecessary conditional, replacing it with an assert(). Improvements to comments. FossilOrigin-Name: 834bf1c367e1ccd498c7f9f843be2d2aa11ffb3c --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 24 ++++++++++++++++-------- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index a1eded678c..dbe10602d3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\scompiler\swarning\swhen\sSQLITE_DIRECT_OVERFLOW_READ\sis\sdefined.\nMinor\sperformance\senhancement\sand\ssize\sreduction. -D 2014-03-31T23:57:41.627 +C Remove\san\sunnecessary\sconditional,\sreplacing\sit\swith\san\sassert().\nImprovements\sto\scomments. +D 2014-04-01T01:24:34.512 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -164,7 +164,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 -F src/btree.c b1d6309d6623f4ea8d9466aebd1ec84adc40cb9b +F src/btree.c 6c9b51abd404ce5b78b173b6f2248e8cb824758c F src/btree.h d79306df4ed9181b48916737fe8871a4392c4594 F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3 F src/build.c 0d50ef95aad63f4c4fc47f3fa2670d4557c45db0 @@ -1159,7 +1159,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P f6211540c9d66a08dc580dd733e4f4a98968ae30 -R a9646e8cad6830bc030ac01ef7720050 +P 96385dc460545807a5c8fcf6280a971700f84866 +R 193f537069a669cf49d79f97b46daa7e U drh -Z be4271c513a3efe06acb17f300ec9933 +Z 9306db9f51cd1c998fccb67bf7fedc94 diff --git a/manifest.uuid b/manifest.uuid index e03a98f749..44d48365ac 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -96385dc460545807a5c8fcf6280a971700f84866 \ No newline at end of file +834bf1c367e1ccd498c7f9f843be2d2aa11ffb3c \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index cbb968ad8b..2bf026b840 100644 --- a/src/btree.c +++ b/src/btree.c @@ -3974,6 +3974,7 @@ static int accessPayload( assert( pCur->eState==CURSOR_VALID ); assert( pCur->aiIdx[pCur->iPage]nCell ); assert( cursorHoldsMutex(pCur) ); + assert( eOp!=2 || offset==0 ); /* Always start from beginning for eOp==2 */ getCellInfo(pCur); aPayload = pCur->info.pCell + pCur->info.nHeader; @@ -4009,12 +4010,13 @@ static int accessPayload( nextPage = get4byte(&aPayload[pCur->info.nLocal]); - /* If the BTCF_Incrblob flag is set and the BtCursor.aOverflow[] - ** has not been allocated, allocate it now. The array is sized at - ** one entry for each overflow page in the overflow chain. The - ** page number of the first overflow page is stored in aOverflow[0], - ** etc. A value of 0 in the aOverflow[] array means "not yet known" - ** (the cache is lazily populated). + /* If the BtCursor.aOverflow[] has not been allocated, allocate it now. + ** Except, do not allocate aOverflow[] for eOp==2. + ** + ** The aOverflow[] array is sized at one entry for each overflow page + ** in the overflow chain. The page number of the first overflow page is + ** stored in aOverflow[0], etc. A value of 0 in the aOverflow[] array + ** means "not yet known" (the cache is lazily populated). */ if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){ int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; @@ -4059,11 +4061,17 @@ static int accessPayload( ** data is not required. So first try to lookup the overflow ** page-list cache, if any, then fall back to the getOverflowPage() ** function. + ** + ** Note that the aOverflow[] array must be allocated because eOp!=2 + ** here. If eOp==2, then offset==0 and this branch is never taken. */ - if( (pCur->curFlags & BTCF_ValidOvfl)!=0 && pCur->aOverflow[iIdx+1] ){ + assert( eOp!=2 ); + assert( pCur->curFlags & BTCF_ValidOvfl ); + if( pCur->aOverflow[iIdx+1] ){ nextPage = pCur->aOverflow[iIdx+1]; - } else + }else{ rc = getOverflowPage(pBt, nextPage, 0, &nextPage); + } offset -= ovflSize; }else{ /* Need to read this page properly. It contains some of the From 1fb6a11072900e7f347980ee07612d2e37ae2c54 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 4 Apr 2014 14:12:52 +0000 Subject: [PATCH 11/17] Ensure the "PRAGMA journal_mode=WAL" works coming from any other journal_mode with ATTACH-ed databases. FossilOrigin-Name: e54330b43127e46fc6494748cbb353a6fc91cfd7 --- manifest | 15 +++++++-------- manifest.uuid | 2 +- src/pager.c | 3 +-- test/wal.test | 13 +++++++++++++ 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 4bcee0a832..26b58d03cf 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Use\sOP_Copy\sinstead\sof\sOP_SCopy\swhen\smoving\sresults\sout\sof\sa\ssubquery,\nto\sprevent\sthe\ssubquery\sresults\sfrom\schanging\sout\sfrom\sunder\sthe\souter\nquery.\s\sFix\sfor\sticket\s[1e64dd782a126f48d78]. -D 2014-04-03T16:29:31.330 +C Ensure\sthe\s"PRAGMA\sjournal_mode=WAL"\sworks\scoming\sfrom\sany\sother\sjournal_mode\nwith\sATTACH-ed\sdatabases. +D 2014-04-04T14:12:52.073 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -205,7 +205,7 @@ F src/os.h 4a46270a64e9193af4a0aaa3bc2c66dc07c29b3f F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 F src/os_unix.c ae4b5240af4619d711301d7992396e182585269f F src/os_win.c e71678ac927d0a0fb11d993db20a9748eabf808e -F src/pager.c 97a8908bf4e6e7c3adea09d3597cfa48ae33ab4e +F src/pager.c ab62a24218d87dda1be641f6c5ad291bff78fd94 F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428 F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0 F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2 @@ -1050,7 +1050,7 @@ F test/vtabF.test fd5ad376f5a34fe0891df1f3cddb4fe7c3eb077e F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5 F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8 F test/vtab_shared.test ea8778d5b0df200adef2ca7c00c3c37d4375f772 -F test/wal.test 40073e54359d43354925b2b700b7eebd5e207285 +F test/wal.test 885f32b2b390b30b4aa3dbb0e568f8f78d40f5cc F test/wal2.test a8e3963abf6b232cf0b852b09b53665ef34007af F test/wal3.test b22eb662bcbc148c5f6d956eaf94b047f7afe9c0 F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c @@ -1159,8 +1159,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 48ecdd4aff03741f96c070dced69c3c273b652cb -Q +ec6a06246e04eee5f25f1c28507df73b697099c0 -R b6a2fefa5b61ea0e64da4db2aaa10286 +P d5513dfa23baa0b0a095aaf17d19aacd30dcef61 +R dda37fe73fefd9a3a9bbbb33bf2f4700 U drh -Z f1f1ceb5f31f4e26d736a13a2a5aca0f +Z ec7ec754ade71c9dc3d6dc5092f63d72 diff --git a/manifest.uuid b/manifest.uuid index 601b0b4f2e..f9214073e9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d5513dfa23baa0b0a095aaf17d19aacd30dcef61 \ No newline at end of file +e54330b43127e46fc6494748cbb353a6fc91cfd7 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index c6485a4d45..b09d6cb930 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1624,12 +1624,11 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){ if( !zMaster || pPager->journalMode==PAGER_JOURNALMODE_MEMORY - || pPager->journalMode==PAGER_JOURNALMODE_OFF + || !isOpen(pPager->jfd) ){ return SQLITE_OK; } pPager->setMaster = 1; - assert( isOpen(pPager->jfd) ); assert( pPager->journalHdr <= pPager->journalOff ); /* Calculate the length in bytes and the checksum of zMaster */ diff --git a/test/wal.test b/test/wal.test index 3a69de54f5..675be73791 100644 --- a/test/wal.test +++ b/test/wal.test @@ -1574,4 +1574,17 @@ sqlite3_shutdown test_sqlite3_log sqlite3_initialize +# Make sure PRAGMA journal_mode=WAL works with ATTACHED databases in +# all journal modes. +# +foreach mode {OFF MEMORY PERSIST DELETE TRUNCATE WAL} { + delete_file test.db test2.db + sqlite3 db test.db + do_test wal-25.$mode { + db eval "PRAGMA journal_mode=$mode" + db eval {ATTACH 'test2.db' AS t2; PRAGMA journal_mode=WAL;} + } {wal} + db close +} + finish_test From d83cad235a5360fe670057d5a70da65b43aea793 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 10 Apr 2014 02:24:48 +0000 Subject: [PATCH 12/17] Modify the OR-clause handling so that it can safely deal with OR-clause with 17 or more terms. Fix for ticket [10fb063b1179be53ea0b53bb]. FossilOrigin-Name: a67b5312f63909737c052fe58ab5772d45530d49 --- manifest | 19 ++++++++--------- manifest.uuid | 2 +- src/rowset.c | 6 +++--- src/sqliteInt.h | 2 +- src/vdbe.c | 4 +--- test/whereD.test | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 68 insertions(+), 18 deletions(-) diff --git a/manifest b/manifest index 51582695c0..0b43c2f6e5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\simprovements\swhen\sreading\slarge\sblobs,\sespecially\sif\nSQLITE_DIRECT_OVERFLOW_READ\sis\sdefined. -D 2014-04-04T18:49:19.417 +C Modify\sthe\sOR-clause\shandling\sso\sthat\sit\scan\ssafely\sdeal\swith\sOR-clause\s\nwith\s17\sor\smore\sterms.\s\sFix\sfor\sticket\s[10fb063b1179be53ea0b53bb]. +D 2014-04-10T02:24:48.549 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -216,13 +216,13 @@ F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337 F src/printf.c e5a0005f8b3de21f85da6a709d2fbee76775bf4b F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c 273d5f47c4e2c05b2d3d2bffeda939551ab59e66 -F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 +F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be F src/select.c 269c3e31a450fce642a10569221a49180348c88e F src/shell.c 5260f2ada8dd06e9f5ae0a448c8c01e7a75dd881 F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h cc9582a91b2910404ccda7b7e198815ea0f75948 +F src/sqliteInt.h 9b1361478e821b1a68f7993047a922e3155ca87d F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -278,7 +278,7 @@ F src/update.c 5b3e74a03b3811e586b4f2b4cbd7c49f01c93115 F src/utf.c 6dc9ec9f1b3db43ae8ba0365377f11df1ee4c01c F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c e811a0081149fb90db367026d154cd7efb3c7098 +F src/vdbe.c bf284edea1cee0508dc93c79a73498e0f317edb7 F src/vdbe.h 394464909ed682334aa3d5831aae0c2fe2abef94 F src/vdbeInt.h e6d83e5bfd62fc6685ba1ed6153f7099f82de9f7 F src/vdbeapi.c 0ed6053f947edd0b30f64ce5aeb811872a3450a4 @@ -1089,7 +1089,7 @@ F test/where9.test 4f3eab951353a3ae164befc521c777dfa903e46c F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5 F test/whereC.test d6f4ecd4fa2d9429681a5b22a25d2bda8e86ab8a -F test/whereD.test 6c2feb79ef1f68381b07f39017fe5f9b96da8d62 +F test/whereD.test fd9120e262f9da3c45940f52aefeef4d15b904e5 F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7 F test/whereG.test 2533b72ed4a31fd1687230a499b557b911525344 @@ -1160,8 +1160,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 683dd379a293b2f330e1e4cd746f190527fe48ee 834bf1c367e1ccd498c7f9f843be2d2aa11ffb3c -R 3de83004edd963c4959934c7f5a61b03 -T +closed 834bf1c367e1ccd498c7f9f843be2d2aa11ffb3c +P 2312eb6a9eb31051db4e0baf19e033ba39adc7b1 +R 2f4de3ec11a98155d746ed7623586007 U drh -Z f4df6ef034f1a63bb656a3ddc69e0011 +Z d44fb7b759451f899c9b9bdcaf2f6d96 diff --git a/manifest.uuid b/manifest.uuid index 0466f25ed2..41b50df795 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2312eb6a9eb31051db4e0baf19e033ba39adc7b1 \ No newline at end of file +a67b5312f63909737c052fe58ab5772d45530d49 \ No newline at end of file diff --git a/src/rowset.c b/src/rowset.c index 5761f98550..ba2e056bd4 100644 --- a/src/rowset.c +++ b/src/rowset.c @@ -112,8 +112,8 @@ struct RowSet { struct RowSetEntry *pFresh; /* Source of new entry objects */ struct RowSetEntry *pForest; /* List of binary trees of entries */ u16 nFresh; /* Number of objects on pFresh */ - u8 rsFlags; /* Various flags */ - u8 iBatch; /* Current insert batch */ + u16 rsFlags; /* Various flags */ + int iBatch; /* Current insert batch */ }; /* @@ -447,7 +447,7 @@ int sqlite3RowSetNext(RowSet *p, i64 *pRowid){ ** on pRowSet->pEntry, then sort those entires into the forest at ** pRowSet->pForest so that they can be tested. */ -int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 iRowid){ +int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 iRowid){ struct RowSetEntry *p, *pTree; /* This routine is never called after sqlite3RowSetNext() */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 0f67748fc8..57481b1084 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3019,7 +3019,7 @@ int sqlite3BitvecBuiltinTest(int,int*); RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int); void sqlite3RowSetClear(RowSet*); void sqlite3RowSetInsert(RowSet*, i64); -int sqlite3RowSetTest(RowSet*, u8 iBatch, i64); +int sqlite3RowSetTest(RowSet*, int iBatch, i64); int sqlite3RowSetNext(RowSet*, i64*); void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int); diff --git a/src/vdbe.c b/src/vdbe.c index 2d1d23e079..6102cf3c7e 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -5227,9 +5227,7 @@ case OP_RowSetTest: { /* jump, in1, in3 */ assert( pOp->p4type==P4_INT32 ); assert( iSet==-1 || iSet>=0 ); if( iSet ){ - exists = sqlite3RowSetTest(pIn1->u.pRowSet, - (u8)(iSet>=0 ? iSet & 0xf : 0xff), - pIn3->u.i); + exists = sqlite3RowSetTest(pIn1->u.pRowSet, iSet, pIn3->u.i); VdbeBranchTaken(exists!=0,2); if( exists ){ pc = pOp->p2 - 1; diff --git a/test/whereD.test b/test/whereD.test index eb0f864025..db993040b0 100644 --- a/test/whereD.test +++ b/test/whereD.test @@ -217,6 +217,59 @@ do_execsql_test 4.7 { ORDER BY a; } {3 4 3 4} +# Verify fix of a bug reported on the mailing list by Peter Reid +# +do_execsql_test 5.1 { + DROP TABLE IF EXISTS t; + CREATE TABLE t(c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15,c16,c17); + CREATE INDEX tc0 ON t(c0); + CREATE INDEX tc1 ON t(c1); + CREATE INDEX tc2 ON t(c2); + CREATE INDEX tc3 ON t(c3); + CREATE INDEX tc4 ON t(c4); + CREATE INDEX tc5 ON t(c5); + CREATE INDEX tc6 ON t(c6); + CREATE INDEX tc7 ON t(c7); + CREATE INDEX tc8 ON t(c8); + CREATE INDEX tc9 ON t(c9); + CREATE INDEX tc10 ON t(c10); + CREATE INDEX tc11 ON t(c11); + CREATE INDEX tc12 ON t(c12); + CREATE INDEX tc13 ON t(c13); + CREATE INDEX tc14 ON t(c14); + CREATE INDEX tc15 ON t(c15); + CREATE INDEX tc16 ON t(c16); + CREATE INDEX tc17 ON t(c17); + + INSERT INTO t(c0, c16) VALUES (1,1); + + SELECT * FROM t WHERE + c0=1 or c1=1 or c2=1 or c3=1 or + c4=1 or c5=1 or c6=1 or c7=1 or + c8=1 or c9=1 or c10=1 or c11=1 or + c12=1 or c13=1 or c14=1 or c15=1 or + c16=1 or c17=1; +} {1 {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} 1 {}} +do_execsql_test 5.2 { + DELETE FROM t; + INSERT INTO t(c0,c17) VALUES(1,1); + SELECT * FROM t WHERE + c0=1 or c1=1 or c2=1 or c3=1 or + c4=1 or c5=1 or c6=1 or c7=1 or + c8=1 or c9=1 or c10=1 or c11=1 or + c12=1 or c13=1 or c14=1 or c15=1 or + c16=1 or c17=1; +} {1 {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} 1} +do_execsql_test 5.3 { + DELETE FROM t; + INSERT INTO t(c0,c15) VALUES(1,1); + SELECT * FROM t WHERE + c0=1 or c1=1 or c2=1 or c3=1 or + c4=1 or c5=1 or c6=1 or c7=1 or + c8=1 or c9=1 or c10=1 or c11=1 or + c12=1 or c13=1 or c14=1 or c15=1 or + c16=1 or c17=1; +} {1 {} {} {} {} {} {} {} {} {} {} {} {} {} {} 1 {} {}} finish_test From 87744513e7374cae5f2df94d4ac1b014483683bc Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 13 Apr 2014 19:15:49 +0000 Subject: [PATCH 13/17] Make sure column cache elements are cleared correctly when jumping over code for key generation in a partial index. Fix for ticket [2ea3e9fe6379fc3f6]. FossilOrigin-Name: 3122b8364082be783821da01d4af2af6a9586327 --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/build.c | 2 +- src/delete.c | 18 ++++++++++++++++-- src/pragma.c | 2 +- src/sqliteInt.h | 1 + test/index6.test | 19 +++++++++++++++++++ 7 files changed, 49 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index 0b43c2f6e5..80d510a4f9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Modify\sthe\sOR-clause\shandling\sso\sthat\sit\scan\ssafely\sdeal\swith\sOR-clause\s\nwith\s17\sor\smore\sterms.\s\sFix\sfor\sticket\s[10fb063b1179be53ea0b53bb]. -D 2014-04-10T02:24:48.549 +C Make\ssure\scolumn\scache\selements\sare\scleared\scorrectly\swhen\sjumping\sover\ncode\sfor\skey\sgeneration\sin\sa\spartial\sindex.\s\nFix\sfor\sticket\s[2ea3e9fe6379fc3f6]. +D 2014-04-13T19:15:49.713 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -167,12 +167,12 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btree.c 6c9b51abd404ce5b78b173b6f2248e8cb824758c F src/btree.h d79306df4ed9181b48916737fe8871a4392c4594 F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3 -F src/build.c 0d50ef95aad63f4c4fc47f3fa2670d4557c45db0 +F src/build.c 5bfeea8f302ec2926c9eea321a61daea92a29fa4 F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 -F src/delete.c cdd57149543bb28304d8f717c243f2a86b1fc280 +F src/delete.c d5e3a958519677049a752ed37657240b55ce5806 F src/expr.c da2b3cb41081af6b56e95e7c9e95949564ce2e21 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 5269ef07b100763134f71b889327c333bd0989cf @@ -211,7 +211,7 @@ F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0 F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c -F src/pragma.c 10f169b9650f0930a7a6df67e1387a4c2c449f38 +F src/pragma.c 21ece94d4f3e76e8e150deecafb9c7abd398ec67 F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337 F src/printf.c e5a0005f8b3de21f85da6a709d2fbee76775bf4b F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece @@ -222,7 +222,7 @@ F src/shell.c 5260f2ada8dd06e9f5ae0a448c8c01e7a75dd881 F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 9b1361478e821b1a68f7993047a922e3155ca87d +F src/sqliteInt.h 97df117e13dea9d2fe8a8e32376222e03fe4a4c9 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -610,7 +610,7 @@ F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6 F test/index3.test 55a90cff99834305e8141df7afaef39674b57062 F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6 F test/index5.test fc07c14193c0430814e7a08b5da46888ee795c33 -F test/index6.test 936979c3a1e87b81feaed2d00505665bf142d764 +F test/index6.test a0a2d286ffa6d35813f5003fdb7be124825b4422 F test/index7.test a3baf9a625bda7fd49471e99aeae04095fbfeecf F test/indexedby.test b2f22f3e693a53813aa3f50b812eb609ba6df1ec F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d @@ -1160,7 +1160,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 2312eb6a9eb31051db4e0baf19e033ba39adc7b1 -R 2f4de3ec11a98155d746ed7623586007 +P a67b5312f63909737c052fe58ab5772d45530d49 +R 47ced825f4356f6492f482f71c0fa4e8 U drh -Z d44fb7b759451f899c9b9bdcaf2f6d96 +Z d6e06c047caf6d5aab62e0b2ec59c712 diff --git a/manifest.uuid b/manifest.uuid index 41b50df795..6f61a4975d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a67b5312f63909737c052fe58ab5772d45530d49 \ No newline at end of file +3122b8364082be783821da01d4af2af6a9586327 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 10077e5018..4d4155ba90 100644 --- a/src/build.c +++ b/src/build.c @@ -2680,7 +2680,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0); sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord); - sqlite3VdbeResolveLabel(v, iPartIdxLabel); + sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel); sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); if( memRootPage<0 ) sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb); diff --git a/src/delete.c b/src/delete.c index 79e83cae52..c6e1762215 100644 --- a/src/delete.c +++ b/src/delete.c @@ -739,7 +739,7 @@ void sqlite3GenerateRowIndexDelete( &iPartIdxLabel, pPrior, r1); sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1, pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn); - sqlite3VdbeResolveLabel(v, iPartIdxLabel); + sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel); pPrior = pIdx; } } @@ -758,10 +758,11 @@ void sqlite3GenerateRowIndexDelete( ** ** If *piPartIdxLabel is not NULL, fill it in with a label and jump ** to that label if pIdx is a partial index that should be skipped. +** The label should be resolved using sqlite3ResolvePartIdxLabel(). ** A partial index should be skipped if its WHERE clause evaluates ** to false or null. If pIdx is not a partial index, *piPartIdxLabel ** will be set to zero which is an empty label that is ignored by -** sqlite3VdbeResolveLabel(). +** sqlite3ResolvePartIdxLabel(). ** ** The pPrior and regPrior parameters are used to implement a cache to ** avoid unnecessary register loads. If pPrior is not NULL, then it is @@ -794,6 +795,7 @@ int sqlite3GenerateIndexKey( if( pIdx->pPartIdxWhere ){ *piPartIdxLabel = sqlite3VdbeMakeLabel(v); pParse->iPartIdxTab = iDataCur; + sqlite3ExprCachePush(pParse); sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel, SQLITE_JUMPIFNULL); }else{ @@ -821,3 +823,15 @@ int sqlite3GenerateIndexKey( sqlite3ReleaseTempRange(pParse, regBase, nCol); return regBase; } + +/* +** If a prior call to sqlite3GenerateIndexKey() generated a jump-over label +** because it was a partial index, then this routine should be called to +** resolve that label. +*/ +void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){ + if( iLabel ){ + sqlite3VdbeResolveLabel(pParse->pVdbe, iLabel); + sqlite3ExprCachePop(pParse, 1); + } +} diff --git a/src/pragma.c b/src/pragma.c index 20da9a6892..66d0c3328e 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1928,7 +1928,7 @@ void sqlite3Pragma( sqlite3VdbeAddOp0(v, OP_Halt); sqlite3VdbeJumpHere(v, jmp4); sqlite3VdbeJumpHere(v, jmp2); - sqlite3VdbeResolveLabel(v, jmp3); + sqlite3ResolvePartIdxLabel(pParse, jmp3); } sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v); sqlite3VdbeJumpHere(v, loopTop-1); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 57481b1084..7d3302eeb7 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3135,6 +3135,7 @@ int sqlite3IsRowid(const char*); void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8); void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*); int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int); +void sqlite3ResolvePartIdxLabel(Parse*,int); void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int, u8,u8,int,int*); void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int); diff --git a/test/index6.test b/test/index6.test index 48706be3cc..3451e5c1df 100644 --- a/test/index6.test +++ b/test/index6.test @@ -248,4 +248,23 @@ do_execsql_test index6-5.0 { SELECT stat+0 FROM sqlite_stat1 WHERE idx='t3b'; } {6 6} +# Test case for ticket [2ea3e9fe6379fc3f6ce7e090ce483c1a3a80d6c9] from +# 2014-04-13: Partial index causes assertion fault on UPDATE OR REPLACE. +# +do_execsql_test index6-6.0 { + CREATE TABLE t6(a,b); + CREATE UNIQUE INDEX t6ab ON t1(a,b); + CREATE INDEX t6b ON t6(b) WHERE b=1; + INSERT INTO t6(a,b) VALUES(123,456); + SELECT * FROM t6; +} {123 456} +do_execsql_test index6-6.1 { + UPDATE OR REPLACE t6 SET b=789; + SELECT * FROM t6; +} {123 789} +do_execsql_test index6-6.2 { + PRAGMA integrity_check; +} {ok} + + finish_test From d2490904507b0f9abeb077a40c2d91ad3a222f7f Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 13 Apr 2014 19:28:15 +0000 Subject: [PATCH 14/17] Remove the unused second argument from sqlite3ExprCachePop(). Add an ALWAYS() on an always-true conditional in sqlite3VdbeResolveLabel(). FossilOrigin-Name: ab23abf392175d3e256ff619b13abbbe732a49ed --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/delete.c | 2 +- src/expr.c | 31 +++++++++++++++---------------- src/sqliteInt.h | 2 +- src/vdbeaux.c | 2 +- src/where.c | 2 +- 7 files changed, 30 insertions(+), 31 deletions(-) diff --git a/manifest b/manifest index 80d510a4f9..3301b08ca6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\scolumn\scache\selements\sare\scleared\scorrectly\swhen\sjumping\sover\ncode\sfor\skey\sgeneration\sin\sa\spartial\sindex.\s\nFix\sfor\sticket\s[2ea3e9fe6379fc3f6]. -D 2014-04-13T19:15:49.713 +C Remove\sthe\sunused\ssecond\sargument\sfrom\ssqlite3ExprCachePop().\s\sAdd\san\nALWAYS()\son\san\salways-true\sconditional\sin\ssqlite3VdbeResolveLabel(). +D 2014-04-13T19:28:15.499 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -172,8 +172,8 @@ F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 -F src/delete.c d5e3a958519677049a752ed37657240b55ce5806 -F src/expr.c da2b3cb41081af6b56e95e7c9e95949564ce2e21 +F src/delete.c bcf8f72126cea80fc3d5bc5494cf19b3f8935aaf +F src/expr.c 4f9e497c66e2f25a4d139357a778c84d5713207c F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 5269ef07b100763134f71b889327c333bd0989cf F src/func.c 2945bb2c4cdc0ac43733046285a4434310be1811 @@ -222,7 +222,7 @@ F src/shell.c 5260f2ada8dd06e9f5ae0a448c8c01e7a75dd881 F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 97df117e13dea9d2fe8a8e32376222e03fe4a4c9 +F src/sqliteInt.h dadd17dbd05fd17cad157a7d96339bf4a0b41172 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -282,7 +282,7 @@ F src/vdbe.c bf284edea1cee0508dc93c79a73498e0f317edb7 F src/vdbe.h 394464909ed682334aa3d5831aae0c2fe2abef94 F src/vdbeInt.h e6d83e5bfd62fc6685ba1ed6153f7099f82de9f7 F src/vdbeapi.c 0ed6053f947edd0b30f64ce5aeb811872a3450a4 -F src/vdbeaux.c 1153175fb57a8454e1c8cf79b59b7bf92b26779d +F src/vdbeaux.c e493f38758c4b8f4ca2007cf6a700bd405d192f3 F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac F src/vdbemem.c 6fc77594c60f6155404f3f8d71bf36d1fdeb4447 F src/vdbesort.c 4abb7c0f8f19b7d7d82f4558d5da1a30fdf9ea38 @@ -291,7 +291,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 -F src/where.c 70eb10da08cebbd6a576ced18edb7c8f79d41597 +F src/where.c 7614c4383d8b6143558dc349da286d0325704d35 F src/whereInt.h 2564055b440e44ebec8b47f237bbccae6719b7af F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1160,7 +1160,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P a67b5312f63909737c052fe58ab5772d45530d49 -R 47ced825f4356f6492f482f71c0fa4e8 +P 3122b8364082be783821da01d4af2af6a9586327 +R e1df7805a07beb887bab893b56a4a7f9 U drh -Z d6e06c047caf6d5aab62e0b2ec59c712 +Z 77065e6cb595843b2b0b90941a9d16f6 diff --git a/manifest.uuid b/manifest.uuid index 6f61a4975d..39f1fc5832 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3122b8364082be783821da01d4af2af6a9586327 \ No newline at end of file +ab23abf392175d3e256ff619b13abbbe732a49ed \ No newline at end of file diff --git a/src/delete.c b/src/delete.c index c6e1762215..c74d8eab7d 100644 --- a/src/delete.c +++ b/src/delete.c @@ -832,6 +832,6 @@ int sqlite3GenerateIndexKey( void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){ if( iLabel ){ sqlite3VdbeResolveLabel(pParse->pVdbe, iLabel); - sqlite3ExprCachePop(pParse, 1); + sqlite3ExprCachePop(pParse); } } diff --git a/src/expr.c b/src/expr.c index b070621ebd..08c121e386 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1883,7 +1883,7 @@ int sqlite3CodeSubselect( if( testAddr>=0 ){ sqlite3VdbeJumpHere(v, testAddr); } - sqlite3ExprCachePop(pParse, 1); + sqlite3ExprCachePop(pParse); return rReg; } @@ -2018,7 +2018,7 @@ static void sqlite3ExprCodeIN( } } sqlite3ReleaseTempReg(pParse, r1); - sqlite3ExprCachePop(pParse, 1); + sqlite3ExprCachePop(pParse); VdbeComment((v, "end IN expr")); } #endif /* SQLITE_OMIT_SUBQUERY */ @@ -2201,15 +2201,14 @@ void sqlite3ExprCachePush(Parse *pParse){ /* ** Remove from the column cache any entries that were added since the -** the previous N Push operations. In other words, restore the cache -** to the state it was in N Pushes ago. +** the previous sqlite3ExprCachePush operation. In other words, restore +** the cache to the state it was in prior the most recent Push. */ -void sqlite3ExprCachePop(Parse *pParse, int N){ +void sqlite3ExprCachePop(Parse *pParse){ int i; struct yColCache *p; - assert( N>0 ); - assert( pParse->iCacheLevel>=N ); - pParse->iCacheLevel -= N; + assert( pParse->iCacheLevel>=1 ); + pParse->iCacheLevel--; #ifdef SQLITE_DEBUG if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ printf("POP to %d\n", pParse->iCacheLevel); @@ -2687,7 +2686,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ sqlite3ExprCacheRemove(pParse, target, 1); sqlite3ExprCachePush(pParse); sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target); - sqlite3ExprCachePop(pParse, 1); + sqlite3ExprCachePop(pParse); } sqlite3VdbeResolveLabel(v, endCoalesce); break; @@ -2741,7 +2740,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */ sqlite3ExprCodeExprList(pParse, pFarg, r1, SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR); - sqlite3ExprCachePop(pParse, 1); /* Ticket 2ea2425d34be */ + sqlite3ExprCachePop(pParse); /* Ticket 2ea2425d34be */ }else{ r1 = 0; } @@ -2961,13 +2960,13 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ testcase( aListelem[i+1].pExpr->op==TK_COLUMN ); sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target); sqlite3VdbeAddOp2(v, OP_Goto, 0, endLabel); - sqlite3ExprCachePop(pParse, 1); + sqlite3ExprCachePop(pParse); sqlite3VdbeResolveLabel(v, nextCase); } if( (nExpr&1)!=0 ){ sqlite3ExprCachePush(pParse); sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target); - sqlite3ExprCachePop(pParse, 1); + sqlite3ExprCachePop(pParse); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, target); } @@ -3546,7 +3545,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ sqlite3ExprCachePush(pParse); sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); sqlite3VdbeResolveLabel(v, d2); - sqlite3ExprCachePop(pParse, 1); + sqlite3ExprCachePop(pParse); break; } case TK_OR: { @@ -3554,7 +3553,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); sqlite3ExprCachePush(pParse); sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); - sqlite3ExprCachePop(pParse, 1); + sqlite3ExprCachePop(pParse); break; } case TK_NOT: { @@ -3700,7 +3699,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); sqlite3ExprCachePush(pParse); sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); - sqlite3ExprCachePop(pParse, 1); + sqlite3ExprCachePop(pParse); break; } case TK_OR: { @@ -3710,7 +3709,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ sqlite3ExprCachePush(pParse); sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); sqlite3VdbeResolveLabel(v, d2); - sqlite3ExprCachePop(pParse, 1); + sqlite3ExprCachePop(pParse); break; } case TK_NOT: { diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 7d3302eeb7..da46676adf 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3083,7 +3083,7 @@ void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int); void sqlite3ExprCodeMove(Parse*, int, int, int); void sqlite3ExprCacheStore(Parse*, int, int, int); void sqlite3ExprCachePush(Parse*); -void sqlite3ExprCachePop(Parse*, int); +void sqlite3ExprCachePop(Parse*); void sqlite3ExprCacheRemove(Parse*, int, int); void sqlite3ExprCacheClear(Parse*); void sqlite3ExprCacheAffinityChange(Parse*, int, int); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 0ce21378d5..0a6b536720 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -276,7 +276,7 @@ void sqlite3VdbeResolveLabel(Vdbe *v, int x){ int j = -1-x; assert( v->magic==VDBE_MAGIC_INIT ); assert( jnLabel ); - if( j>=0 && p->aLabel ){ + if( ALWAYS(j>=0) && p->aLabel ){ p->aLabel[j] = v->nOp; } p->iFixedOp = v->nOp - 1; diff --git a/src/where.c b/src/where.c index 16db3e7f29..e51eee5350 100644 --- a/src/where.c +++ b/src/where.c @@ -2841,7 +2841,7 @@ static Bitmask codeOneLoopStart( pLevel->p1 = iCur; pLevel->p2 = sqlite3VdbeCurrentAddr(v); sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); - sqlite3ExprCachePop(pParse, 1); + sqlite3ExprCachePop(pParse); }else #endif /* SQLITE_OMIT_VIRTUALTABLE */ From 65b9ac522430cdc55855b24de406c54d12199346 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 14 Apr 2014 19:48:25 +0000 Subject: [PATCH 15/17] Make sure the undocumented sqlite_rename_parent() function does not crash even if it is invoked with NULL arguments. Ticket [264b970c4379fd4b94] FossilOrigin-Name: c6fa8d0d82805be230f672eabccdfa5680d4ddfd --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/alter.c | 1 + test/alter.test | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 3301b08ca6..5ba411e0a6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sthe\sunused\ssecond\sargument\sfrom\ssqlite3ExprCachePop().\s\sAdd\san\nALWAYS()\son\san\salways-true\sconditional\sin\ssqlite3VdbeResolveLabel(). -D 2014-04-13T19:28:15.499 +C Make\ssure\sthe\sundocumented\ssqlite_rename_parent()\sfunction\sdoes\snot\ncrash\seven\sif\sit\sis\sinvoked\swith\sNULL\sarguments.\nTicket\s[264b970c4379fd4b94] +D 2014-04-14T19:48:25.984 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -157,7 +157,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c 5d99edbac5bc416032772b723ee30182ee6e5de0 +F src/alter.c b00900877f766f116f9e16116f1ccacdc21d82f1 F src/analyze.c 663e0b291d27eb03c9fd6b421e2d61ba348a2389 F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 @@ -298,7 +298,7 @@ F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87 F test/all.test 6ff7b43c2b4b905c74dc4a813d201d0fa64c5783 -F test/alter.test e88dfa77e020c2b48e52a8020c70171ab828e079 +F test/alter.test 547dc2d292644301ac9a7dda22b319b74f9c08d2 F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060 F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d F test/alter4.test d6c011fa0d6227abba762498cafbb607c9609e93 @@ -1160,7 +1160,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 3122b8364082be783821da01d4af2af6a9586327 -R e1df7805a07beb887bab893b56a4a7f9 +P ab23abf392175d3e256ff619b13abbbe732a49ed +R 410ec05c8f2a9918dc68eaaf465de80d U drh -Z 77065e6cb595843b2b0b90941a9d16f6 +Z 8590c3c7b25dad5b568a22b07ca7e219 diff --git a/manifest.uuid b/manifest.uuid index 39f1fc5832..1f38f99a6e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ab23abf392175d3e256ff619b13abbbe732a49ed \ No newline at end of file +c6fa8d0d82805be230f672eabccdfa5680d4ddfd \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 1a83e570db..64204b7b24 100644 --- a/src/alter.c +++ b/src/alter.c @@ -116,6 +116,7 @@ static void renameParentFunc( int token; /* Type of token */ UNUSED_PARAMETER(NotUsed); + if( zInput==0 || zOld==0 ) return; for(z=zInput; *z; z=z+n){ n = sqlite3GetToken(z, &token); if( token==TK_REFERENCES ){ diff --git a/test/alter.test b/test/alter.test index 557162f837..ddf1698824 100644 --- a/test/alter.test +++ b/test/alter.test @@ -875,4 +875,42 @@ do_execsql_test alter-16.2 { SELECT * FROM t16a_rn ORDER BY a; } {abc 1.25 99 xyzzy cba 5.5 98 fizzle} +#------------------------------------------------------------------------- +# Verify that NULL values into the internal-use-only sqlite_rename_*() +# functions do not cause problems. +# +do_execsql_test alter-17.1 { + SELECT sqlite_rename_table('CREATE TABLE xyz(a,b,c)','abc'); +} {{CREATE TABLE "abc"(a,b,c)}} +do_execsql_test alter-17.2 { + SELECT sqlite_rename_table('CREATE TABLE xyz(a,b,c)',NULL); +} {{CREATE TABLE "(NULL)"(a,b,c)}} +do_execsql_test alter-17.3 { + SELECT sqlite_rename_table(NULL,'abc'); +} {{}} +do_execsql_test alter-17.4 { + SELECT sqlite_rename_trigger('CREATE TRIGGER r1 ON xyz WHEN','abc'); +} {{CREATE TRIGGER r1 ON "abc" WHEN}} +do_execsql_test alter-17.5 { + SELECT sqlite_rename_trigger('CREATE TRIGGER r1 ON xyz WHEN',NULL); +} {{CREATE TRIGGER r1 ON "(NULL)" WHEN}} +do_execsql_test alter-17.6 { + SELECT sqlite_rename_trigger(NULL,'abc'); +} {{}} +do_execsql_test alter-17.7 { + SELECT sqlite_rename_parent('CREATE TABLE t1(a REFERENCES "xyzzy")', + 'xyzzy','lmnop'); +} {{CREATE TABLE t1(a REFERENCES "lmnop")}} +do_execsql_test alter-17.8 { + SELECT sqlite_rename_parent('CREATE TABLE t1(a REFERENCES "xyzzy")', + 'xyzzy',NULL); +} {{CREATE TABLE t1(a REFERENCES "(NULL)")}} +do_execsql_test alter-17.9 { + SELECT sqlite_rename_parent('CREATE TABLE t1(a REFERENCES "xyzzy")', + NULL, 'lmnop'); +} {{}} +do_execsql_test alter-17.10 { + SELECT sqlite_rename_parent(NULL,'abc','xyz'); +} {{}} + finish_test From 2cf4acbd9f774e1c7bbaa232edbbdf93cff553ee Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 18 Apr 2014 00:06:02 +0000 Subject: [PATCH 16/17] Add the SQLITE_TESTCTRL_BYTEORDER test control to interrogate SQLite's notion of the processor byte order and whether the byte order is known at compile-time or determined at run-time. FossilOrigin-Name: 9c6961967ae00e563ebe2859eaf2639a79f2cb01 --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/main.c | 16 ++++++++++++++++ src/shell.c | 6 ++++-- src/sqlite.h.in | 3 ++- src/sqliteInt.h | 9 ++++++--- 6 files changed, 38 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index 5ba411e0a6..a1452995b3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\sthe\sundocumented\ssqlite_rename_parent()\sfunction\sdoes\snot\ncrash\seven\sif\sit\sis\sinvoked\swith\sNULL\sarguments.\nTicket\s[264b970c4379fd4b94] -D 2014-04-14T19:48:25.984 +C Add\sthe\sSQLITE_TESTCTRL_BYTEORDER\stest\scontrol\sto\sinterrogate\sSQLite's\snotion\nof\sthe\sprocessor\sbyte\sorder\sand\swhether\sthe\sbyte\sorder\sis\sknown\sat\scompile-time\nor\sdetermined\sat\srun-time. +D 2014-04-18T00:06:02.110 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -186,7 +186,7 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303 -F src/main.c 691b25754bef596108fe60ff1bcbe8445369c9db +F src/main.c 0a8cfb6b2899649880e5874ac9bfd1c6f7c6a4a3 F src/malloc.c 0203ebce9152c6a0e5de520140b8ba65187350be F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b @@ -218,11 +218,11 @@ F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c 273d5f47c4e2c05b2d3d2bffeda939551ab59e66 F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be F src/select.c 269c3e31a450fce642a10569221a49180348c88e -F src/shell.c 5260f2ada8dd06e9f5ae0a448c8c01e7a75dd881 -F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80 +F src/shell.c 2afe7a7154e97be0c74c5feacf09626bda8493be +F src/sqlite.h.in bde98816e1ba0c9ffef50afe7b32f4e5a8f54fe0 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h dadd17dbd05fd17cad157a7d96339bf4a0b41172 +F src/sqliteInt.h 35a265ef6e137e9af289d6e3b55745323148ad66 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -1160,7 +1160,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P ab23abf392175d3e256ff619b13abbbe732a49ed -R 410ec05c8f2a9918dc68eaaf465de80d +P c6fa8d0d82805be230f672eabccdfa5680d4ddfd +R f2d9932522491a86ed313bf5e3a1693d U drh -Z 8590c3c7b25dad5b568a22b07ca7e219 +Z 4f6d25a564bc084e4d5fbc71ec75b6b1 diff --git a/manifest.uuid b/manifest.uuid index 1f38f99a6e..c03388d6de 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c6fa8d0d82805be230f672eabccdfa5680d4ddfd \ No newline at end of file +9c6961967ae00e563ebe2859eaf2639a79f2cb01 \ No newline at end of file diff --git a/src/main.c b/src/main.c index 9e83d4963a..65521f4466 100644 --- a/src/main.c +++ b/src/main.c @@ -3205,6 +3205,22 @@ int sqlite3_test_control(int op, ...){ break; } + /* + ** sqlite3_test_control(SQLITE_TESTCTRL_BYTEORDER); + ** + ** The integer returned reveals the byte-order of the computer on which + ** SQLite is running: + ** + ** 1 big-endian, determined at run-time + ** 10 little-endian, determined at run-time + ** 432101 big-endian, determined at compile-time + ** 123410 little-endian, determined at compile-time + */ + case SQLITE_TESTCTRL_BYTEORDER: { + rc = SQLITE_BYTEORDER*100 + SQLITE_LITTLEENDIAN*10 + SQLITE_BIGENDIAN; + break; + } + /* sqlite3_test_control(SQLITE_TESTCTRL_RESERVE, sqlite3 *db, int N) ** ** Set the nReserve size to N for the main database on the database diff --git a/src/shell.c b/src/shell.c index f380962a86..61965d2d39 100644 --- a/src/shell.c +++ b/src/shell.c @@ -3027,6 +3027,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){ { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS }, { "iskeyword", SQLITE_TESTCTRL_ISKEYWORD }, { "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC }, + { "byteorder", SQLITE_TESTCTRL_BYTEORDER }, }; int testctrl = -1; int rc = 0; @@ -3067,9 +3068,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){ break; /* sqlite3_test_control(int) */ - case SQLITE_TESTCTRL_PRNG_SAVE: - case SQLITE_TESTCTRL_PRNG_RESTORE: + case SQLITE_TESTCTRL_PRNG_SAVE: + case SQLITE_TESTCTRL_PRNG_RESTORE: case SQLITE_TESTCTRL_PRNG_RESET: + case SQLITE_TESTCTRL_BYTEORDER: if( nArg==2 ){ rc = sqlite3_test_control(testctrl); fprintf(p->out, "%d (0x%08x)\n", rc, rc); diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 5d2c87552c..e8dddc468c 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -6118,7 +6118,8 @@ int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 #define SQLITE_TESTCTRL_NEVER_CORRUPT 20 #define SQLITE_TESTCTRL_VDBE_COVERAGE 21 -#define SQLITE_TESTCTRL_LAST 21 +#define SQLITE_TESTCTRL_BYTEORDER 22 +#define SQLITE_TESTCTRL_LAST 22 /* ** CAPI3REF: SQLite Runtime Status diff --git a/src/sqliteInt.h b/src/sqliteInt.h index da46676adf..2a12466a4e 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -553,15 +553,18 @@ const int sqlite3one = 1; #else extern const int sqlite3one; #endif -#if defined(i386) || defined(__i386__) || defined(_M_IX86)\ - || defined(__x86_64) || defined(__x86_64__) +#if defined(i386) || defined(__i386__) || defined(_M_IX86) \ + || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) \ + || defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) +# define SQLITE_BYTEORDER 1234 # define SQLITE_BIGENDIAN 0 # define SQLITE_LITTLEENDIAN 1 # define SQLITE_UTF16NATIVE SQLITE_UTF16LE #else +# define SQLITE_BYTEORDER 0 /* 0 means "unknown at compile-time" */ # define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0) # define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1) -# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE) +# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE) #endif /* From 71794dbaeb73f594ef704fa265715b207f98edc7 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 18 Apr 2014 00:49:29 +0000 Subject: [PATCH 17/17] Add the SQLITE_RUNTIME_BYTEORDER compile-time option to force SQLite to check the processor byte-order at run-time. Add additional compile-time byte order checks for ARM, PPC, and SPARC. FossilOrigin-Name: 2c5363873a6f990a0abaacac6303acd46b48befc --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/sqliteInt.h | 24 +++++++++++++++++++----- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index a1452995b3..97b4f2b46f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sSQLITE_TESTCTRL_BYTEORDER\stest\scontrol\sto\sinterrogate\sSQLite's\snotion\nof\sthe\sprocessor\sbyte\sorder\sand\swhether\sthe\sbyte\sorder\sis\sknown\sat\scompile-time\nor\sdetermined\sat\srun-time. -D 2014-04-18T00:06:02.110 +C Add\sthe\sSQLITE_RUNTIME_BYTEORDER\scompile-time\soption\sto\sforce\sSQLite\sto\scheck\nthe\sprocessor\sbyte-order\sat\srun-time.\s\sAdd\sadditional\scompile-time\sbyte\sorder\nchecks\sfor\sARM,\sPPC,\sand\sSPARC. +D 2014-04-18T00:49:29.419 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -222,7 +222,7 @@ F src/shell.c 2afe7a7154e97be0c74c5feacf09626bda8493be F src/sqlite.h.in bde98816e1ba0c9ffef50afe7b32f4e5a8f54fe0 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 35a265ef6e137e9af289d6e3b55745323148ad66 +F src/sqliteInt.h d3ca0bdd6743c9af2f333cb372b4bf95b19cd1fd F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -1160,7 +1160,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P c6fa8d0d82805be230f672eabccdfa5680d4ddfd -R f2d9932522491a86ed313bf5e3a1693d +P 9c6961967ae00e563ebe2859eaf2639a79f2cb01 +R 1b4cbcab83595d3a8147d0a70e1ae961 U drh -Z 4f6d25a564bc084e4d5fbc71ec75b6b1 +Z a694f54c65c4a003c92caa29b70309b3 diff --git a/manifest.uuid b/manifest.uuid index c03388d6de..05a8b60e7e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9c6961967ae00e563ebe2859eaf2639a79f2cb01 \ No newline at end of file +2c5363873a6f990a0abaacac6303acd46b48befc \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 2a12466a4e..8197a61eb5 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -546,21 +546,35 @@ typedef INT16_TYPE LogEst; /* ** Macros to determine whether the machine is big or little endian, -** evaluated at runtime. +** and whether or not that determination is run-time or compile-time. +** +** For best performance, an attempt is made to guess at the byte-order +** using C-preprocessor macros. If that is unsuccessful, or if +** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined +** at run-time. */ #ifdef SQLITE_AMALGAMATION const int sqlite3one = 1; #else extern const int sqlite3one; #endif -#if defined(i386) || defined(__i386__) || defined(_M_IX86) \ - || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) \ - || defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) +#if (defined(i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ + defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ + defined(__arm__)) && !defined(SQLITE_RUNTIME_BYTEORDER) # define SQLITE_BYTEORDER 1234 # define SQLITE_BIGENDIAN 0 # define SQLITE_LITTLEENDIAN 1 # define SQLITE_UTF16NATIVE SQLITE_UTF16LE -#else +#endif +#if (defined(sparc) || defined(__ppc__)) \ + && !defined(SQLITE_RUNTIME_BYTEORDER) +# define SQLITE_BYTEORDER 4321 +# define SQLITE_BIGENDIAN 1 +# define SQLITE_LITTLEENDIAN 0 +# define SQLITE_UTF16NATIVE SQLITE_UTF16BE +#endif +#if !defined(SQLITE_BYTEORDER) # define SQLITE_BYTEORDER 0 /* 0 means "unknown at compile-time" */ # define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0) # define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1)