From acbcb7e013b0c2d54f8b0977a464badc260d7048 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 21 Aug 2014 20:26:37 +0000 Subject: [PATCH 01/29] Simplify the interface to the symbol table, saving 600 bytes of code space. FossilOrigin-Name: 14b0f561fe15622b61c6676c9c455dca6b9ba5f0 --- manifest | 26 ++++++++++---------- manifest.uuid | 2 +- src/build.c | 24 ++++++------------ src/callback.c | 8 +++--- src/fkey.c | 5 ++-- src/hash.c | 66 ++++++++++++++++++++------------------------------ src/hash.h | 6 ++--- src/main.c | 3 +-- src/trigger.c | 17 +++++-------- src/vtab.c | 11 ++++----- 10 files changed, 69 insertions(+), 99 deletions(-) diff --git a/manifest b/manifest index 1e5132fbcf..bcba60c6c2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sfaulty\sassert()\sstatement.\s\sAdd\scomments\sto\sclarify\sthe\sbehavior\sof\nthe\ssqlite3OpenTableAndIndices()\sroutine\sin\sinsert.c.\s\sAdd\stest\scases\sto\nverify\sthat\sthe\sassert()\sstatement\sis\snot\sfiring\sinappropriately.\nTicket\s[369d57fb8e5ccdff06f1]. -D 2014-08-21T14:10:23.770 +C Simplify\sthe\sinterface\sto\sthe\ssymbol\stable,\ssaving\s600\sbytes\sof\scode\sspace. +D 2014-08-21T20:26:37.728 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -171,26 +171,26 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btree.c 4195fed5741b4dbcc9831b623aec487258f3e62d F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3 -F src/build.c 5abf794fe8a605f2005b422e98a3cedad9b9ef5b -F src/callback.c fcff28cf0df2403dd2f313bb8d1b8f31f6f3cd64 +F src/build.c 058e3aadb1376521ff291735237edf4c10f438fb +F src/callback.c b97d0695ffcf6a8710ee445ffe56ee387d4d8a6f F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 F src/delete.c 5adcd322c6b08fc25d215d780ca62cebce66304d F src/expr.c f749009cf4a8534efb5e0d5cd7c9fb1fb0f2836c F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c 8545f3b36da47473e10800ea4fb0810fd4062514 +F src/fkey.c 8d81a780ad78d16ec9082585758a8f1d6bf02ca3 F src/func.c bbb724b74ed96ca42675a7274646a71dd52bcda7 F src/global.c 1e4bd956dc2f608f87d2a929abc4a20db65f30e4 -F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd -F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22 +F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 +F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/insert.c d1a104e67b33314d4cc5c1356147446086ab9fc8 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c febc2a9e7ad6c1a6191c7b5b9170b325d263f343 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303 -F src/main.c 1cf92c5c6468f2b6ed99b638706781ccc9c60b42 +F src/main.c 1e5d34fb6dee85019b4bcc44e8576457b5075174 F src/malloc.c 0203ebce9152c6a0e5de520140b8ba65187350be F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b @@ -279,7 +279,7 @@ F src/test_vfs.c f84075a388527892ff184988f43b69ce69b8083c F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c ae45399d6252b4d736af43bee1576ce7bff86aec -F src/trigger.c 66f3470b03b52b395e839155786966e3e037fddb +F src/trigger.c 4bddd12803275aa98f1c7ce0118fceb02b2167f6 F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059 F src/utf.c a0314e637768a030e6e84a957d0c4f6ba910cc05 F src/util.c 3076bdd51cdbf60a6e2e57fada745be37133c73e @@ -293,7 +293,7 @@ F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac F src/vdbemem.c d90a1e8acf8b63dc9d14cbbea12bfec6cec31394 F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 -F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd +F src/vtab.c 180bfc5e69c92f2014c094bc49a66e8c37c188ac F src/wal.c 264df50a1b33124130b23180ded2e2c5663c652a F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 91594aae0725388765070c80039dfe1bf126392d -R 25e887863ed8cfd2c8a241fac46385f1 +P 7029b3404d3f5f698a496934f3a3f2972051b257 +R 818f77c3be876451b2dad41de8a59565 U drh -Z ed55b6e966354470a11e6c95fe10b90c +Z cb34ea9e2178e12926edef43b644d982 diff --git a/manifest.uuid b/manifest.uuid index 944f894bbc..98b1fd2ac2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7029b3404d3f5f698a496934f3a3f2972051b257 \ No newline at end of file +14b0f561fe15622b61c6676c9c455dca6b9ba5f0 \ No newline at end of file diff --git a/src/build.c b/src/build.c index a9a8f21793..af776cb3d8 100644 --- a/src/build.c +++ b/src/build.c @@ -286,16 +286,14 @@ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){ Table *p = 0; int i; - int nName; assert( zName!=0 ); - nName = sqlite3Strlen30(zName); /* All mutexes are required for schema access. Make sure we hold them. */ assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) ); for(i=OMIT_TEMPDB; inDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue; assert( sqlite3SchemaMutexHeld(db, j, 0) ); - p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName, nName); + p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName); if( p ) break; } return p; @@ -378,7 +376,6 @@ Table *sqlite3LocateTableItem( Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){ Index *p = 0; int i; - int nName = sqlite3Strlen30(zName); /* All mutexes are required for schema access. Make sure we hold them. */ assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); for(i=OMIT_TEMPDB; inDb; i++){ @@ -387,7 +384,7 @@ Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){ assert( pSchema ); if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue; assert( sqlite3SchemaMutexHeld(db, j, 0) ); - p = sqlite3HashFind(&pSchema->idxHash, zName, nName); + p = sqlite3HashFind(&pSchema->idxHash, zName); if( p ) break; } return p; @@ -415,13 +412,11 @@ static void freeIndex(sqlite3 *db, Index *p){ */ void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ Index *pIndex; - int len; Hash *pHash; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); pHash = &db->aDb[iDb].pSchema->idxHash; - len = sqlite3Strlen30(zIdxName); - pIndex = sqlite3HashInsert(pHash, zIdxName, len, 0); + pIndex = sqlite3HashInsert(pHash, zIdxName, 0); if( ALWAYS(pIndex) ){ if( pIndex->pTable->pIndex==pIndex ){ pIndex->pTable->pIndex = pIndex->pNext; @@ -581,7 +576,7 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ if( !db || db->pnBytesFreed==0 ){ char *zName = pIndex->zName; TESTONLY ( Index *pOld = ) sqlite3HashInsert( - &pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0 + &pIndex->pSchema->idxHash, zName, 0 ); assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); assert( pOld==pIndex || pOld==0 ); @@ -624,8 +619,7 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); testcase( zTabName[0]==0 ); /* Zero-length table names are allowed */ pDb = &db->aDb[iDb]; - p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, - sqlite3Strlen30(zTabName),0); + p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, 0); sqlite3DeleteTable(db, p); db->flags |= SQLITE_InternChanges; } @@ -1947,8 +1941,7 @@ void sqlite3EndTable( Table *pOld; Schema *pSchema = p->pSchema; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, - sqlite3Strlen30(p->zName),p); + pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p); if( pOld ){ assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ db->mallocFailed = 1; @@ -2598,7 +2591,7 @@ void sqlite3CreateForeignKey( assert( sqlite3SchemaMutexHeld(db, 0, p->pSchema) ); pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash, - pFKey->zTo, sqlite3Strlen30(pFKey->zTo), (void *)pFKey + pFKey->zTo, (void *)pFKey ); if( pNextTo==pFKey ){ db->mallocFailed = 1; @@ -3146,8 +3139,7 @@ Index *sqlite3CreateIndex( Index *p; assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); p = sqlite3HashInsert(&pIndex->pSchema->idxHash, - pIndex->zName, sqlite3Strlen30(pIndex->zName), - pIndex); + pIndex->zName, pIndex); if( p ){ assert( p==pIndex ); /* Malloc must have failed */ db->mallocFailed = 1; diff --git a/src/callback.c b/src/callback.c index 46fbe2c21a..63090899fb 100644 --- a/src/callback.c +++ b/src/callback.c @@ -154,11 +154,11 @@ static CollSeq *findCollSeqEntry( int create /* Create a new entry if true */ ){ CollSeq *pColl; - int nName = sqlite3Strlen30(zName); - pColl = sqlite3HashFind(&db->aCollSeq, zName, nName); + pColl = sqlite3HashFind(&db->aCollSeq, zName); if( 0==pColl && create ){ - pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1 ); + int nName = sqlite3Strlen30(zName); + pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1); if( pColl ){ CollSeq *pDel = 0; pColl[0].zName = (char*)&pColl[3]; @@ -169,7 +169,7 @@ static CollSeq *findCollSeqEntry( pColl[2].enc = SQLITE_UTF16BE; memcpy(pColl[0].zName, zName, nName); pColl[0].zName[nName] = 0; - pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl); + pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, pColl); /* If a malloc() failure occurred in sqlite3HashInsert(), it will ** return the pColl pointer to be deleted (because it wasn't added diff --git a/src/fkey.c b/src/fkey.c index 50c10da822..415f35d2f8 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -659,8 +659,7 @@ static void fkScanChildren( ** table). */ FKey *sqlite3FkReferences(Table *pTab){ - int nName = sqlite3Strlen30(pTab->zName); - return (FKey *)sqlite3HashFind(&pTab->pSchema->fkeyHash, pTab->zName, nName); + return (FKey *)sqlite3HashFind(&pTab->pSchema->fkeyHash, pTab->zName); } /* @@ -1338,7 +1337,7 @@ void sqlite3FkDelete(sqlite3 *db, Table *pTab){ }else{ void *p = (void *)pFKey->pNextTo; const char *z = (p ? pFKey->pNextTo->zTo : pFKey->zTo); - sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, sqlite3Strlen30(z), p); + sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, p); } if( pFKey->pNextTo ){ pFKey->pNextTo->pPrevTo = pFKey->pPrevTo; diff --git a/src/hash.c b/src/hash.c index f9901fee8f..b5886e0641 100644 --- a/src/hash.c +++ b/src/hash.c @@ -52,12 +52,11 @@ void sqlite3HashClear(Hash *pH){ /* ** The hashing function. */ -static unsigned int strHash(const char *z, int nKey){ +static unsigned int strHash(const char *z){ unsigned int h = 0; - assert( nKey>=0 ); - while( nKey > 0 ){ - h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++]; - nKey--; + unsigned char c; + while( (c = (unsigned char)*z++)!=0 ){ + h = (h<<3) ^ h ^ sqlite3UpperToLower[c]; } return h; } @@ -129,7 +128,7 @@ static int rehash(Hash *pH, unsigned int new_size){ pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht); memset(new_ht, 0, new_size*sizeof(struct _ht)); for(elem=pH->first, pH->first=0; elem; elem = next_elem){ - unsigned int h = strHash(elem->pKey, elem->nKey) % new_size; + unsigned int h = strHash(elem->pKey) % new_size; next_elem = elem->next; insertElement(pH, &new_ht[h], elem); } @@ -137,28 +136,33 @@ static int rehash(Hash *pH, unsigned int new_size){ } /* This function (for internal use only) locates an element in an -** hash table that matches the given key. The hash for this key has -** already been computed and is passed as the 4th parameter. +** hash table that matches the given key. The hash for this key is +** also computed and returned in the *pH parameter. */ -static HashElem *findElementGivenHash( +static HashElem *findElementWithHash( const Hash *pH, /* The pH to be searched */ const char *pKey, /* The key we are searching for */ - int nKey, /* Bytes in key (not counting zero terminator) */ - unsigned int h /* The hash for this key. */ + unsigned int *pHash /* Write the hash value here */ ){ HashElem *elem; /* Used to loop thru the element list */ int count; /* Number of elements left to test */ + unsigned int h; /* The computed hash */ if( pH->ht ){ - struct _ht *pEntry = &pH->ht[h]; + struct _ht *pEntry; + h = strHash(pKey) % pH->htsize; + pEntry = &pH->ht[h]; elem = pEntry->chain; count = pEntry->count; }else{ + h = 0; elem = pH->first; count = pH->count; } - while( count-- && ALWAYS(elem) ){ - if( elem->nKey==nKey && sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){ + *pHash = h; + while( count-- ){ + assert( elem!=0 ); + if( sqlite3StrICmp(elem->pKey,pKey)==0 ){ return elem; } elem = elem->next; @@ -201,26 +205,20 @@ static void removeElementGivenHash( } /* Attempt to locate an element of the hash table pH with a key -** that matches pKey,nKey. Return the data for this element if it is +** that matches pKey. Return the data for this element if it is ** found, or NULL if there is no match. */ -void *sqlite3HashFind(const Hash *pH, const char *pKey, int nKey){ +void *sqlite3HashFind(const Hash *pH, const char *pKey){ HashElem *elem; /* The element that matches key */ unsigned int h; /* A hash on key */ assert( pH!=0 ); assert( pKey!=0 ); - assert( nKey>=0 ); - if( pH->ht ){ - h = strHash(pKey, nKey) % pH->htsize; - }else{ - h = 0; - } - elem = findElementGivenHash(pH, pKey, nKey, h); + elem = findElementWithHash(pH, pKey, &h); return elem ? elem->data : 0; } -/* Insert an element into the hash table pH. The key is pKey,nKey +/* Insert an element into the hash table pH. The key is pKey ** and the data is "data". ** ** If no element exists with a matching key, then a new @@ -234,20 +232,14 @@ void *sqlite3HashFind(const Hash *pH, const char *pKey, int nKey){ ** If the "data" parameter to this function is NULL, then the ** element corresponding to "key" is removed from the hash table. */ -void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, void *data){ +void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){ unsigned int h; /* the hash of the key modulo hash table size */ HashElem *elem; /* Used to loop thru the element list */ HashElem *new_elem; /* New element added to the pH */ assert( pH!=0 ); assert( pKey!=0 ); - assert( nKey>=0 ); - if( pH->htsize ){ - h = strHash(pKey, nKey) % pH->htsize; - }else{ - h = 0; - } - elem = findElementGivenHash(pH,pKey,nKey,h); + elem = findElementWithHash(pH,pKey,&h); if( elem ){ void *old_data = elem->data; if( data==0 ){ @@ -255,7 +247,6 @@ void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, void *data){ }else{ elem->data = data; elem->pKey = pKey; - assert(nKey==elem->nKey); } return old_data; } @@ -263,19 +254,14 @@ void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, void *data){ new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) ); if( new_elem==0 ) return data; new_elem->pKey = pKey; - new_elem->nKey = nKey; new_elem->data = data; pH->count++; if( pH->count>=10 && pH->count > 2*pH->htsize ){ if( rehash(pH, pH->count*2) ){ assert( pH->htsize>0 ); - h = strHash(pKey, nKey) % pH->htsize; + h = strHash(pKey) % pH->htsize; } } - if( pH->ht ){ - insertElement(pH, &pH->ht[h], new_elem); - }else{ - insertElement(pH, 0, new_elem); - } + insertElement(pH, pH->ht ? &pH->ht[h] : 0, new_elem); return 0; } diff --git a/src/hash.h b/src/hash.h index 82b7c58c71..6dfa4e035c 100644 --- a/src/hash.h +++ b/src/hash.h @@ -59,15 +59,15 @@ struct Hash { struct HashElem { HashElem *next, *prev; /* Next and previous elements in the table */ void *data; /* Data associated with this element */ - const char *pKey; int nKey; /* Key associated with this element */ + const char *pKey; /* Key associated with this element */ }; /* ** Access routines. To delete, insert a NULL pointer. */ void sqlite3HashInit(Hash*); -void *sqlite3HashInsert(Hash*, const char *pKey, int nKey, void *pData); -void *sqlite3HashFind(const Hash*, const char *pKey, int nKey); +void *sqlite3HashInsert(Hash*, const char *pKey, void *pData); +void *sqlite3HashFind(const Hash*, const char *pKey); void sqlite3HashClear(Hash*); /* diff --git a/src/main.c b/src/main.c index cea72829df..2472321759 100644 --- a/src/main.c +++ b/src/main.c @@ -1998,7 +1998,6 @@ static int createCollation( ){ CollSeq *pColl; int enc2; - int nName = sqlite3Strlen30(zName); assert( sqlite3_mutex_held(db->mutex) ); @@ -2037,7 +2036,7 @@ static int createCollation( ** to be called. */ if( (pColl->enc & ~SQLITE_UTF16_ALIGNED)==enc2 ){ - CollSeq *aColl = sqlite3HashFind(&db->aCollSeq, zName, nName); + CollSeq *aColl = sqlite3HashFind(&db->aCollSeq, zName); int j; for(j=0; j<3; j++){ CollSeq *p = &aColl[j]; diff --git a/src/trigger.c b/src/trigger.c index 01f7b21f74..fc32a663bf 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -180,8 +180,7 @@ void sqlite3BeginTrigger( goto trigger_cleanup; } assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash), - zName, sqlite3Strlen30(zName)) ){ + if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){ if( !noErr ){ sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); }else{ @@ -324,13 +323,12 @@ void sqlite3FinishTrigger( Trigger *pLink = pTrig; Hash *pHash = &db->aDb[iDb].pSchema->trigHash; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - pTrig = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), pTrig); + pTrig = sqlite3HashInsert(pHash, zName, pTrig); if( pTrig ){ db->mallocFailed = 1; }else if( pLink->pSchema==pLink->pTabSchema ){ Table *pTab; - int n = sqlite3Strlen30(pLink->table); - pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table, n); + pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table); assert( pTab!=0 ); pLink->pNext = pTab->pTrigger; pTab->pTrigger = pLink; @@ -489,7 +487,6 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){ int i; const char *zDb; const char *zName; - int nName; sqlite3 *db = pParse->db; if( db->mallocFailed ) goto drop_trigger_cleanup; @@ -500,13 +497,12 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){ assert( pName->nSrc==1 ); zDb = pName->a[0].zDatabase; zName = pName->a[0].zName; - nName = sqlite3Strlen30(zName); assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); for(i=OMIT_TEMPDB; inDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue; assert( sqlite3SchemaMutexHeld(db, j, 0) ); - pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName); + pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName); if( pTrigger ) break; } if( !pTrigger ){ @@ -529,8 +525,7 @@ drop_trigger_cleanup: ** is set on. */ static Table *tableOfTrigger(Trigger *pTrigger){ - int n = sqlite3Strlen30(pTrigger->table); - return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n); + return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table); } @@ -602,7 +597,7 @@ void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); pHash = &(db->aDb[iDb].pSchema->trigHash); - pTrigger = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), 0); + pTrigger = sqlite3HashInsert(pHash, zName, 0); if( ALWAYS(pTrigger) ){ if( pTrigger->pSchema==pTrigger->pTabSchema ){ Table *pTab = tableOfTrigger(pTrigger); diff --git a/src/vtab.c b/src/vtab.c index ca0db214cc..ad18af48a4 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -43,7 +43,7 @@ static int createModule( sqlite3_mutex_enter(db->mutex); nName = sqlite3Strlen30(zName); - if( sqlite3HashFind(&db->aModule, zName, nName) ){ + if( sqlite3HashFind(&db->aModule, zName) ){ rc = SQLITE_MISUSE_BKPT; }else{ Module *pMod; @@ -56,7 +56,7 @@ static int createModule( pMod->pModule = pModule; pMod->pAux = pAux; pMod->xDestroy = xDestroy; - pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,nName,(void*)pMod); + pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); assert( pDel==0 || pDel==pMod ); if( pDel ){ db->mallocFailed = 1; @@ -425,9 +425,8 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ Table *pOld; Schema *pSchema = pTab->pSchema; const char *zName = pTab->zName; - int nName = sqlite3Strlen30(zName); assert( sqlite3SchemaMutexHeld(db, 0, pSchema) ); - pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab); + pOld = sqlite3HashInsert(&pSchema->tblHash, zName, pTab); if( pOld ){ db->mallocFailed = 1; assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */ @@ -593,7 +592,7 @@ int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){ /* Locate the required virtual table module */ zMod = pTab->azModuleArg[0]; - pMod = (Module*)sqlite3HashFind(&db->aModule, zMod, sqlite3Strlen30(zMod)); + pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); if( !pMod ){ const char *zModule = pTab->azModuleArg[0]; @@ -661,7 +660,7 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){ /* Locate the required virtual table module */ zMod = pTab->azModuleArg[0]; - pMod = (Module*)sqlite3HashFind(&db->aModule, zMod, sqlite3Strlen30(zMod)); + pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); /* If the module has been registered and includes a Create method, ** invoke it now. If the module has not been registered, return an From 5ab567078a924d9eeff3616433532dd2905a21c7 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 11:11:30 +0000 Subject: [PATCH 02/29] Enhance the spellfix extension with the ability to specify a rowid when inserting new rows. FossilOrigin-Name: 369c480cda6fa66394b995346bbf51f3298446e1 --- ext/misc/spellfix.c | 22 ++++++++++++++++------ manifest | 14 +++++++------- manifest.uuid | 2 +- test/spellfix.test | 16 ++++++++++++++++ 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/ext/misc/spellfix.c b/ext/misc/spellfix.c index 2e6743e4f7..2a26e08391 100644 --- a/ext/misc/spellfix.c +++ b/ext/misc/spellfix.c @@ -2736,12 +2736,22 @@ static int spellfix1Update( return SQLITE_NOMEM; } if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ - spellfix1DbExec(&rc, db, - "INSERT INTO \"%w\".\"%w_vocab\"(rank,langid,word,k1,k2) " - "VALUES(%d,%d,%Q,%Q,%Q)", - p->zDbName, p->zTableName, - iRank, iLang, zWord, zK1, zK2 - ); + if( sqlite3_value_type(argv[1])==SQLITE_NULL ){ + spellfix1DbExec(&rc, db, + "INSERT INTO \"%w\".\"%w_vocab\"(rank,langid,word,k1,k2) " + "VALUES(%d,%d,%Q,%Q,%Q)", + p->zDbName, p->zTableName, + iRank, iLang, zWord, zK1, zK2 + ); + }else{ + newRowid = sqlite3_value_int64(argv[1]); + spellfix1DbExec(&rc, db, + "INSERT INTO \"%w\".\"%w_vocab\"(id,rank,langid,word,k1,k2) " + "VALUES(%lld,%d,%d,%Q,%Q,%Q)", + p->zDbName, p->zTableName, + newRowid, iRank, iLang, zWord, zK1, zK2 + ); + } *pRowid = sqlite3_last_insert_rowid(db); }else{ rowid = sqlite3_value_int64(argv[0]); diff --git a/manifest b/manifest index bcba60c6c2..c3d516552f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Simplify\sthe\sinterface\sto\sthe\ssymbol\stable,\ssaving\s600\sbytes\sof\scode\sspace. -D 2014-08-21T20:26:37.728 +C Enhance\sthe\sspellfix\sextension\swith\sthe\sability\sto\sspecify\sa\srowid\swhen\ninserting\snew\srows. +D 2014-08-22T11:11:30.047 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -116,7 +116,7 @@ F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63 F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a -F ext/misc/spellfix.c cb016c2dab951ffd7b819a7bc8a750ebd6c26c0f +F ext/misc/spellfix.c 56739fab8c2ed6a9e2dac5592a88d281a999c43b F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512 F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e @@ -847,7 +847,7 @@ F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715 F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b F test/speedtest1.c d29c8048beb7ea9254191f3fde9414709166a920 -F test/spellfix.test 61309f5efbec53603b3f86457d34a504f80abafe +F test/spellfix.test 24f676831acddd2f4056a598fd731a72c6311f49 F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298 F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 7029b3404d3f5f698a496934f3a3f2972051b257 -R 818f77c3be876451b2dad41de8a59565 +P 14b0f561fe15622b61c6676c9c455dca6b9ba5f0 +R e9738e2157edd7ced31f8162753e2f5b U drh -Z cb34ea9e2178e12926edef43b644d982 +Z 9671128edfd421e5d7e75c6453894b1f diff --git a/manifest.uuid b/manifest.uuid index 98b1fd2ac2..85d3cf892f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -14b0f561fe15622b61c6676c9c455dca6b9ba5f0 \ No newline at end of file +369c480cda6fa66394b995346bbf51f3298446e1 \ No newline at end of file diff --git a/test/spellfix.test b/test/spellfix.test index 21383c2d33..954bdb21f1 100644 --- a/test/spellfix.test +++ b/test/spellfix.test @@ -124,6 +124,22 @@ do_execsql_test 1.23 { SELECT next_char('ab','vocab2','w',null,'binary'); } {c} +do_execsql_test 1.30 { + SELECT rowid FROM t1 WHERE word='rabbit'; +} {2} +do_execsql_test 1.31 { + UPDATE t1 SET rowid=2000 WHERE word='rabbit'; + SELECT rowid FROM t1 WHERE word='rabbit'; +} {2000} +do_execsql_test 1.32 { + INSERT INTO t1(rowid, word) VALUES(3000,'melody'); + SELECT rowid, word, matchlen FROM t1 WHERE word MATCH 'melotti' + ORDER BY score LIMIT 3; +} {3000 melody 6} +do_test 1.33 { + catchsql {INSERT INTO t1(rowid, word) VALUES(3000,'garden');} +} {1 {constraint failed}} + do_execsql_test 2.1 { CREATE VIRTUAL TABLE t2 USING spellfix1; INSERT INTO t2 (word, soundslike) VALUES('school', 'skuul'); From 3f5b199eb596a6e8031647d93e00451ade43806e Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 13:22:32 +0000 Subject: [PATCH 03/29] Change a while-loop into a do-loop in sqlite3VdbeSerialPut() for a small size reduction and performance improvement. FossilOrigin-Name: 750bb0a0960606ab24037e0992e9f7a17524cc3e --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbeaux.c | 7 ++++--- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index c3d516552f..0e059ae46c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\sspellfix\sextension\swith\sthe\sability\sto\sspecify\sa\srowid\swhen\ninserting\snew\srows. -D 2014-08-22T11:11:30.047 +C Change\sa\swhile-loop\sinto\sa\sdo-loop\sin\ssqlite3VdbeSerialPut()\sfor\sa\ssmall\nsize\sreduction\sand\sperformance\simprovement. +D 2014-08-22T13:22:32.819 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -288,7 +288,7 @@ F src/vdbe.c f7f4066e4d6e3858878d76ce9288ea603e12ddf6 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 F src/vdbeInt.h f5513f2b5ac1e2c5128996c7ea23add256a301df F src/vdbeapi.c 7858d7e7cd23267d3fbca18e3a28cce8e0d162a8 -F src/vdbeaux.c 25d62ef82cf1be2a1255eacac636fa0d943d8b3d +F src/vdbeaux.c 9c9571706aaf0e5debab5b01629ef569cde40920 F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac F src/vdbemem.c d90a1e8acf8b63dc9d14cbbea12bfec6cec31394 F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 14b0f561fe15622b61c6676c9c455dca6b9ba5f0 -R e9738e2157edd7ced31f8162753e2f5b +P 369c480cda6fa66394b995346bbf51f3298446e1 +R 9c1a6f648ddd3ddf03093ccb99facf2b U drh -Z 9671128edfd421e5d7e75c6453894b1f +Z 453b7d6a328e84b291043b75c1b3327d diff --git a/manifest.uuid b/manifest.uuid index 85d3cf892f..6ea1746008 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -369c480cda6fa66394b995346bbf51f3298446e1 \ No newline at end of file +750bb0a0960606ab24037e0992e9f7a17524cc3e \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index fb3f7c3a8c..83c6e1f65a 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2933,10 +2933,11 @@ u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ v = pMem->u.i; } len = i = sqlite3VdbeSerialTypeLen(serial_type); - while( i-- ){ - buf[i] = (u8)(v&0xFF); + assert( i>0 ); + do{ + buf[--i] = (u8)(v&0xFF); v >>= 8; - } + }while( i ); return len; } From 14a924a5cd77e353ebae67d3b4bc7e64b7bd715a Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 14:34:05 +0000 Subject: [PATCH 04/29] Get the sqlite3VdbeSerialGet() routine to run faster by avoiding the use of local variables. FossilOrigin-Name: 8267d82174099e548a4f78d06af0c6324c89b83d --- manifest | 17 ++++++---- manifest.uuid | 2 +- src/sqliteInt.h | 12 +++++++ src/vdbeaux.c | 89 +++++++++++++++++++++++++++---------------------- 4 files changed, 73 insertions(+), 47 deletions(-) diff --git a/manifest b/manifest index 0e059ae46c..66e4c0b1b6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sa\swhile-loop\sinto\sa\sdo-loop\sin\ssqlite3VdbeSerialPut()\sfor\sa\ssmall\nsize\sreduction\sand\sperformance\simprovement. -D 2014-08-22T13:22:32.819 +C Get\sthe\ssqlite3VdbeSerialGet()\sroutine\sto\srun\sfaster\sby\savoiding\sthe\suse\nof\slocal\svariables. +D 2014-08-22T14:34:05.936 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -228,7 +228,7 @@ F src/shell.c 728d2226594d356bf4fbdbdfd08538fd78fd06f3 F src/sqlite.h.in ed9d35990c61f0388ca6405706455c4095310553 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 641f8fbb65ca2084c8df95b525f6f82c7a1e91ae +F src/sqliteInt.h 99bd20e5a12dce7ba290e938123d27e87b5eae27 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -288,7 +288,7 @@ F src/vdbe.c f7f4066e4d6e3858878d76ce9288ea603e12ddf6 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 F src/vdbeInt.h f5513f2b5ac1e2c5128996c7ea23add256a301df F src/vdbeapi.c 7858d7e7cd23267d3fbca18e3a28cce8e0d162a8 -F src/vdbeaux.c 9c9571706aaf0e5debab5b01629ef569cde40920 +F src/vdbeaux.c f83d5c265aea19d2e49ba018beaf99acff934020 F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac F src/vdbemem.c d90a1e8acf8b63dc9d14cbbea12bfec6cec31394 F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 @@ -1188,7 +1188,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 369c480cda6fa66394b995346bbf51f3298446e1 -R 9c1a6f648ddd3ddf03093ccb99facf2b +P 750bb0a0960606ab24037e0992e9f7a17524cc3e +R 6bc6a7681a89a137c23142249db6cf86 +T *branch * experimental +T *sym-experimental * +T -sym-trunk * U drh -Z 453b7d6a328e84b291043b75c1b3327d +Z 612ca7a9b67c6d8d8dbe2b7affb6d3eb diff --git a/manifest.uuid b/manifest.uuid index 6ea1746008..9538f73f10 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -750bb0a0960606ab24037e0992e9f7a17524cc3e \ No newline at end of file +8267d82174099e548a4f78d06af0c6324c89b83d \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index ee52487d66..5202beff78 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -153,6 +153,18 @@ # define SQLITE_PTR_TO_INT(X) ((int)(X)) #endif +/* +** A macro to hint to the compiler that a function should not be +** inlined. +*/ +#if defined(__GNUC__) +# define SQLITE_NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) +# define SQLITE_NOINLINE __declspec(noinline) +#else +# define SQLITE_NOINLINE +#endif + /* ** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2. ** 0 means mutexes are permanently disable and the library is never diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 83c6e1f65a..d338806962 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2965,14 +2965,55 @@ u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ /* ** Deserialize the data blob pointed to by buf as serial type serial_type ** and store the result in pMem. Return the number of bytes read. +** +** This function is implemented as two separate routines for performance. +** The few cases that require local variables are broken out into a separate +** routine so that in most cases the overhead of moving the stack pointer +** is avoided. */ -u32 sqlite3VdbeSerialGet( +static u32 SQLITE_NOINLINE serialGet( const unsigned char *buf, /* Buffer to deserialize from */ u32 serial_type, /* Serial type to deserialize */ Mem *pMem /* Memory cell to write value into */ ){ u64 x; - u32 y; + u32 y = FOUR_BYTE_UINT(buf); + if( serial_type==4 ){ + pMem->u.i = (i64)*(int*)&y; + pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); + return 4; + } + x = (((u64)y)<<32)|FOUR_BYTE_UINT(buf+4); + if( serial_type==6 ){ + pMem->u.i = *(i64*)&x; + pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); + }else{ +#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT) + /* Verify that integers and floating point values use the same + ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is + ** defined that 64-bit floating point values really are mixed + ** endian. + */ + static const u64 t1 = ((u64)0x3ff00000)<<32; + static const double r1 = 1.0; + u64 t2 = t1; + swapMixedEndianFloat(t2); + assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 ); +#endif + assert( sizeof(x)==8 && sizeof(pMem->r)==8 ); + swapMixedEndianFloat(x); + memcpy(&pMem->r, &x, sizeof(x)); + pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real; + } + return 8; +} +u32 sqlite3VdbeSerialGet( + const unsigned char *buf, /* Buffer to deserialize from */ + u32 serial_type, /* Serial type to deserialize */ + Mem *pMem /* Memory cell to write value into */ +){ switch( serial_type ){ case 10: /* Reserved for future use */ case 11: /* Reserved for future use */ @@ -2998,47 +3039,19 @@ u32 sqlite3VdbeSerialGet( testcase( pMem->u.i<0 ); return 3; } - case 4: { /* 4-byte signed integer */ - y = FOUR_BYTE_UINT(buf); - pMem->u.i = (i64)*(int*)&y; - pMem->flags = MEM_Int; - testcase( pMem->u.i<0 ); - return 4; - } case 5: { /* 6-byte signed integer */ pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); return 6; } + case 4: /* 4-byte signed integer */ case 6: /* 8-byte signed integer */ case 7: { /* IEEE floating point */ -#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT) - /* Verify that integers and floating point values use the same - ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is - ** defined that 64-bit floating point values really are mixed - ** endian. - */ - static const u64 t1 = ((u64)0x3ff00000)<<32; - static const double r1 = 1.0; - u64 t2 = t1; - swapMixedEndianFloat(t2); - assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 ); -#endif - x = FOUR_BYTE_UINT(buf); - y = FOUR_BYTE_UINT(buf+4); - x = (x<<32) | y; - if( serial_type==6 ){ - pMem->u.i = *(i64*)&x; - pMem->flags = MEM_Int; - testcase( pMem->u.i<0 ); - }else{ - assert( sizeof(x)==8 && sizeof(pMem->r)==8 ); - swapMixedEndianFloat(x); - memcpy(&pMem->r, &x, sizeof(x)); - pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real; - } - return 8; + /* These three cases require local variables, so do them in a + ** separate routine to avoid having to move the frame pointer in + ** the common case */ + return serialGet(buf,serial_type,pMem); } case 8: /* Integer 0 */ case 9: { /* Integer 1 */ @@ -3048,17 +3061,15 @@ u32 sqlite3VdbeSerialGet( } default: { static const u16 aFlag[] = { MEM_Blob|MEM_Ephem, MEM_Str|MEM_Ephem }; - u32 len = (serial_type-12)/2; pMem->z = (char *)buf; - pMem->n = len; + pMem->n = (serial_type-12)/2; pMem->xDel = 0; pMem->flags = aFlag[serial_type&1]; - return len; + return pMem->n; } } return 0; } - /* ** This routine is used to allocate sufficient space for an UnpackedRecord ** structure large enough to be used with sqlite3VdbeRecordUnpack() if From 8932becbef8458f91b9316249e2ac9a3d24ed816 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 14:56:13 +0000 Subject: [PATCH 05/29] Handle the 4-byte integer case in the stackless routine. FossilOrigin-Name: 3f55484e81000c75e231f5580632a68e782ded4f --- manifest | 15 ++++++--------- manifest.uuid | 2 +- src/vdbeaux.c | 25 ++++++++++++------------- 3 files changed, 19 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index 66e4c0b1b6..2e7b46977a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Get\sthe\ssqlite3VdbeSerialGet()\sroutine\sto\srun\sfaster\sby\savoiding\sthe\suse\nof\slocal\svariables. -D 2014-08-22T14:34:05.936 +C Handle\sthe\s4-byte\sinteger\scase\sin\sthe\sstackless\sroutine. +D 2014-08-22T14:56:13.720 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -288,7 +288,7 @@ F src/vdbe.c f7f4066e4d6e3858878d76ce9288ea603e12ddf6 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 F src/vdbeInt.h f5513f2b5ac1e2c5128996c7ea23add256a301df F src/vdbeapi.c 7858d7e7cd23267d3fbca18e3a28cce8e0d162a8 -F src/vdbeaux.c f83d5c265aea19d2e49ba018beaf99acff934020 +F src/vdbeaux.c d0b20a85d1ab8c951e5c8b2400a45252d6d2750c F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac F src/vdbemem.c d90a1e8acf8b63dc9d14cbbea12bfec6cec31394 F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 @@ -1188,10 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 750bb0a0960606ab24037e0992e9f7a17524cc3e -R 6bc6a7681a89a137c23142249db6cf86 -T *branch * experimental -T *sym-experimental * -T -sym-trunk * +P 8267d82174099e548a4f78d06af0c6324c89b83d +R 3e2300d1a615c65baf7081c06688a5fd U drh -Z 612ca7a9b67c6d8d8dbe2b7affb6d3eb +Z 9f4fad73eafc2d2adf27281640f7d1a1 diff --git a/manifest.uuid b/manifest.uuid index 9538f73f10..301ab7c9f7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8267d82174099e548a4f78d06af0c6324c89b83d \ No newline at end of file +3f55484e81000c75e231f5580632a68e782ded4f \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index d338806962..513481bf00 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2961,6 +2961,7 @@ u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ #define TWO_BYTE_INT(x) (256*(i8)((x)[0])|(x)[1]) #define THREE_BYTE_INT(x) (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2]) #define FOUR_BYTE_UINT(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) +#define FOUR_BYTE_INT(x) (16777216*(i8)((x)[0])|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) /* ** Deserialize the data blob pointed to by buf as serial type serial_type @@ -2976,15 +2977,9 @@ static u32 SQLITE_NOINLINE serialGet( u32 serial_type, /* Serial type to deserialize */ Mem *pMem /* Memory cell to write value into */ ){ - u64 x; - u32 y = FOUR_BYTE_UINT(buf); - if( serial_type==4 ){ - pMem->u.i = (i64)*(int*)&y; - pMem->flags = MEM_Int; - testcase( pMem->u.i<0 ); - return 4; - } - x = (((u64)y)<<32)|FOUR_BYTE_UINT(buf+4); + u64 x = FOUR_BYTE_UINT(buf); + u32 y = FOUR_BYTE_UINT(buf+4); + x = (x<<32) + y; if( serial_type==6 ){ pMem->u.i = *(i64*)&x; pMem->flags = MEM_Int; @@ -3039,18 +3034,22 @@ u32 sqlite3VdbeSerialGet( testcase( pMem->u.i<0 ); return 3; } + case 4: { /* 4-byte signed integer */ + pMem->u.i = FOUR_BYTE_INT(buf); + pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); + return 4; + } case 5: { /* 6-byte signed integer */ pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); return 6; } - case 4: /* 4-byte signed integer */ case 6: /* 8-byte signed integer */ case 7: { /* IEEE floating point */ - /* These three cases require local variables, so do them in a - ** separate routine to avoid having to move the frame pointer in - ** the common case */ + /* These use local variables, so do them in a separate routine + ** to avoid having to move the frame pointer in the common case */ return serialGet(buf,serial_type,pMem); } case 8: /* Integer 0 */ From 172087fb733f54d025fe6a112898cdcabada7e47 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 15:40:20 +0000 Subject: [PATCH 06/29] Performance improvement in the printf() logic by avoiding unnecessary stack pointer movement. FossilOrigin-Name: f7f2160db014f0ae11ad13c8ad70ad3444124e3e --- manifest | 13 ++++++------- manifest.uuid | 2 +- src/printf.c | 10 +++++----- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index ceff9d8346..5d853a3262 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\sthe\sperformance\sand\sreduce\sthe\ssize\sof\sthe\ssqlite3VdbeSerialGet()\nroutine\sby\savoiding\sthe\suse\sof\sstack. -D 2014-08-22T15:19:59.113 +C Performance\simprovement\sin\sthe\sprintf()\slogic\sby\savoiding\sunnecessary\sstack\npointer\smovement. +D 2014-08-22T15:40:20.728 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -219,7 +219,7 @@ F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c F src/pragma.c d10ef67c4de79f78188b965b4b7988aff1d66f2e F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337 -F src/printf.c af06f66927919730f03479fed6ae9854f73419f4 +F src/printf.c 00986c86ddfffefc2fd3c73667ff51b3b9709c74 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c 0ea356d32a5e884add23d1b9b4e8736681dd5697 F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be @@ -1188,8 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 750bb0a0960606ab24037e0992e9f7a17524cc3e 3f55484e81000c75e231f5580632a68e782ded4f -R 3e2300d1a615c65baf7081c06688a5fd -T +closed 3f55484e81000c75e231f5580632a68e782ded4f +P ebc10e46c15017d7cd232b5f4f3ef67ef740d87f +R 200d7eb44581fc5fc17c5cd337adb810 U drh -Z 0797c3bb55e4f93e4c54043857e85ca3 +Z f2b0948089d8fe6b11165afcc09478da diff --git a/manifest.uuid b/manifest.uuid index 3b49bd178d..a75c3b426e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ebc10e46c15017d7cd232b5f4f3ef67ef740d87f \ No newline at end of file +f7f2160db014f0ae11ad13c8ad70ad3444124e3e \ No newline at end of file diff --git a/src/printf.c b/src/printf.c index 37910804d2..72ace932ba 100644 --- a/src/printf.c +++ b/src/printf.c @@ -784,7 +784,7 @@ void sqlite3AppendSpace(StrAccum *p, int N){ ** work (enlarging the buffer) using tail recursion, so that the ** sqlite3StrAccumAppend() routine can use fast calling semantics. */ -static void enlargeAndAppend(StrAccum *p, const char *z, int N){ +static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){ N = sqlite3StrAccumEnlarge(p, N); if( N>0 ){ memcpy(&p->zText[p->nChar], z, N); @@ -803,11 +803,11 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ assert( p->accError==0 || p->nAlloc==0 ); if( p->nChar+N >= p->nAlloc ){ enlargeAndAppend(p,z,N); - return; + }else{ + assert( p->zText ); + p->nChar += N; + memcpy(&p->zText[p->nChar-N], z, N); } - assert( p->zText ); - memcpy(&p->zText[p->nChar], z, N); - p->nChar += N; } /* From 13f40da31d9692a96dcab00f85afee9fd68bae12 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 18:00:11 +0000 Subject: [PATCH 07/29] Split the sqlite3Error() routine into sqlite3Error() and sqlite3ErrorWithMsg(), for a slight size reduction and performance increase. FossilOrigin-Name: cf561d1f0bb60b3d638632d20bd686dda4fa4a04 --- manifest | 36 ++++++++++++++++++------------------ manifest.uuid | 2 +- src/backup.c | 12 ++++++------ src/legacy.c | 6 +++--- src/loadext.c | 2 +- src/main.c | 26 +++++++++++++------------- src/malloc.c | 2 +- src/notify.c | 2 +- src/prepare.c | 8 ++++---- src/sqliteInt.h | 3 ++- src/util.c | 23 ++++++++++++++++------- src/vdbeapi.c | 10 +++++----- src/vdbeaux.c | 4 ++-- src/vdbeblob.c | 6 +++--- src/vtab.c | 6 +++--- 15 files changed, 79 insertions(+), 69 deletions(-) diff --git a/manifest b/manifest index 5d853a3262..2ec516f887 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\simprovement\sin\sthe\sprintf()\slogic\sby\savoiding\sunnecessary\sstack\npointer\smovement. -D 2014-08-22T15:40:20.728 +C Split\sthe\ssqlite3Error()\sroutine\sinto\ssqlite3Error()\sand\nsqlite3ErrorWithMsg(),\sfor\sa\sslight\ssize\sreduction\sand\sperformance\sincrease. +D 2014-08-22T18:00:11.621 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -165,7 +165,7 @@ F src/alter.c b00900877f766f116f9e16116f1ccacdc21d82f1 F src/analyze.c f98a351908da29f7b44741cfeb9eb20dda648ba0 F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 -F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 +F src/backup.c a31809c65623cc41849b94d368917f8bb66e6a7e F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btree.c 4195fed5741b4dbcc9831b623aec487258f3e62d @@ -187,11 +187,11 @@ F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/insert.c d1a104e67b33314d4cc5c1356147446086ab9fc8 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d -F src/legacy.c febc2a9e7ad6c1a6191c7b5b9170b325d263f343 +F src/legacy.c 87c92f4a08e2f70220e3b22a9c3b2482d36a134a F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b -F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303 -F src/main.c 1e5d34fb6dee85019b4bcc44e8576457b5075174 -F src/malloc.c 0203ebce9152c6a0e5de520140b8ba65187350be +F src/loadext.c 31c2122b7dd05a179049bbf163fd4839f181cbab +F src/main.c 900dd06e41d22795cbb23ab0240397f1e2901bf7 +F src/malloc.c 0a88a97fc5ae621ca9659d38b080e0b9ddbb80ad F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f @@ -203,7 +203,7 @@ F src/mutex.h 5bc526e19dccc412b7ff04642f6fdad3fdfdabea F src/mutex_noop.c f3f09fd7a2eb4287cfc799753ffc30380e7b71a1 F src/mutex_unix.c 1b10d5413dfc794364a8adf3eb3a192926b43fa3 F src/mutex_w32.c 06bfff9a3a83b53389a51a967643db3967032e1e -F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30 +F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7 F src/os.c 1b147e4cf7cc39e618115c14a086aed44bc91ace F src/os.h 60d419395e32a8029fa380a80a3da2e9030f635e F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 @@ -218,7 +218,7 @@ F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c F src/pragma.c d10ef67c4de79f78188b965b4b7988aff1d66f2e -F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337 +F src/prepare.c 3842c1dfc0b053458e3adcf9f6efc48e03e3fe3d F src/printf.c 00986c86ddfffefc2fd3c73667ff51b3b9709c74 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c 0ea356d32a5e884add23d1b9b4e8736681dd5697 @@ -228,7 +228,7 @@ F src/shell.c 728d2226594d356bf4fbdbdfd08538fd78fd06f3 F src/sqlite.h.in ed9d35990c61f0388ca6405706455c4095310553 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 99bd20e5a12dce7ba290e938123d27e87b5eae27 +F src/sqliteInt.h 937869c407c61026443c879e8c90a9dff05d2d27 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -282,18 +282,18 @@ F src/tokenize.c ae45399d6252b4d736af43bee1576ce7bff86aec F src/trigger.c 4bddd12803275aa98f1c7ce0118fceb02b2167f6 F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059 F src/utf.c a0314e637768a030e6e84a957d0c4f6ba910cc05 -F src/util.c 3076bdd51cdbf60a6e2e57fada745be37133c73e +F src/util.c 524127b3c330b9f490a505ff6eb7f80dfc873a3a F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 F src/vdbe.c f7f4066e4d6e3858878d76ce9288ea603e12ddf6 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 F src/vdbeInt.h f5513f2b5ac1e2c5128996c7ea23add256a301df -F src/vdbeapi.c 7858d7e7cd23267d3fbca18e3a28cce8e0d162a8 -F src/vdbeaux.c d0b20a85d1ab8c951e5c8b2400a45252d6d2750c -F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac +F src/vdbeapi.c 49b8d2943d02d276b4efef114578251a3277f47d +F src/vdbeaux.c f7fdc59e2eefa6fc4ba7324b03ea6f8f66e98d62 +F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4 F src/vdbemem.c d90a1e8acf8b63dc9d14cbbea12bfec6cec31394 F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 -F src/vtab.c 180bfc5e69c92f2014c094bc49a66e8c37c188ac +F src/vtab.c 019dbfd0406a7447c990e1f7bd1dfcdb8895697f F src/wal.c 264df50a1b33124130b23180ded2e2c5663c652a F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P ebc10e46c15017d7cd232b5f4f3ef67ef740d87f -R 200d7eb44581fc5fc17c5cd337adb810 +P f7f2160db014f0ae11ad13c8ad70ad3444124e3e +R 668369bbbf2d81407f36345226c5d2a9 U drh -Z f2b0948089d8fe6b11165afcc09478da +Z bddb035a8072a327798c78fbe23bcf26 diff --git a/manifest.uuid b/manifest.uuid index a75c3b426e..5842d66545 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f7f2160db014f0ae11ad13c8ad70ad3444124e3e \ No newline at end of file +cf561d1f0bb60b3d638632d20bd686dda4fa4a04 \ No newline at end of file diff --git a/src/backup.c b/src/backup.c index 4a6bc7493c..92c6334bde 100644 --- a/src/backup.c +++ b/src/backup.c @@ -87,12 +87,12 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ int rc = 0; pParse = sqlite3StackAllocZero(pErrorDb, sizeof(*pParse)); if( pParse==0 ){ - sqlite3Error(pErrorDb, SQLITE_NOMEM, "out of memory"); + sqlite3ErrorWithMsg(pErrorDb, SQLITE_NOMEM, "out of memory"); rc = SQLITE_NOMEM; }else{ pParse->db = pDb; if( sqlite3OpenTempDatabase(pParse) ){ - sqlite3Error(pErrorDb, pParse->rc, "%s", pParse->zErrMsg); + sqlite3ErrorWithMsg(pErrorDb, pParse->rc, "%s", pParse->zErrMsg); rc = SQLITE_ERROR; } sqlite3DbFree(pErrorDb, pParse->zErrMsg); @@ -105,7 +105,7 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ } if( i<0 ){ - sqlite3Error(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb); + sqlite3ErrorWithMsg(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb); return 0; } @@ -150,7 +150,7 @@ sqlite3_backup *sqlite3_backup_init( sqlite3_mutex_enter(pDestDb->mutex); if( pSrcDb==pDestDb ){ - sqlite3Error( + sqlite3ErrorWithMsg( pDestDb, SQLITE_ERROR, "source and destination must be distinct" ); p = 0; @@ -161,7 +161,7 @@ sqlite3_backup *sqlite3_backup_init( ** sqlite3_backup_finish(). */ p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup)); if( !p ){ - sqlite3Error(pDestDb, SQLITE_NOMEM, 0); + sqlite3Error(pDestDb, SQLITE_NOMEM); } } @@ -602,7 +602,7 @@ int sqlite3_backup_finish(sqlite3_backup *p){ /* Set the error code of the destination database handle. */ rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc; if( p->pDestDb ){ - sqlite3Error(p->pDestDb, rc, 0); + sqlite3Error(p->pDestDb, rc); /* Exit the mutexes and free the backup context structure. */ sqlite3LeaveMutexAndCloseZombie(p->pDestDb); diff --git a/src/legacy.c b/src/legacy.c index 1913f0b5af..b8cb90d707 100644 --- a/src/legacy.c +++ b/src/legacy.c @@ -44,7 +44,7 @@ int sqlite3_exec( if( zSql==0 ) zSql = ""; sqlite3_mutex_enter(db->mutex); - sqlite3Error(db, SQLITE_OK, 0); + sqlite3Error(db, SQLITE_OK); while( rc==SQLITE_OK && zSql[0] ){ int nCol; char **azVals = 0; @@ -102,7 +102,7 @@ int sqlite3_exec( rc = SQLITE_ABORT; sqlite3VdbeFinalize((Vdbe *)pStmt); pStmt = 0; - sqlite3Error(db, SQLITE_ABORT, 0); + sqlite3Error(db, SQLITE_ABORT); goto exec_out; } } @@ -132,7 +132,7 @@ exec_out: memcpy(*pzErrMsg, sqlite3_errmsg(db), nErrMsg); }else{ rc = SQLITE_NOMEM; - sqlite3Error(db, SQLITE_NOMEM, 0); + sqlite3Error(db, SQLITE_NOMEM); } }else if( pzErrMsg ){ *pzErrMsg = 0; diff --git a/src/loadext.c b/src/loadext.c index 828e865b61..05045dedb3 100644 --- a/src/loadext.c +++ b/src/loadext.c @@ -749,7 +749,7 @@ void sqlite3AutoLoadExtensions(sqlite3 *db){ sqlite3_mutex_leave(mutex); zErrmsg = 0; if( xInit && (rc = xInit(db, &zErrmsg, &sqlite3Apis))!=0 ){ - sqlite3Error(db, rc, + sqlite3ErrorWithMsg(db, rc, "automatic extension loading failed: %s", zErrmsg); go = 0; } diff --git a/src/main.c b/src/main.c index 2472321759..219a8bec92 100644 --- a/src/main.c +++ b/src/main.c @@ -852,7 +852,7 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){ ** SQLITE_BUSY if the connection can not be closed immediately. */ if( !forceZombie && connectionIsBusy(db) ){ - sqlite3Error(db, SQLITE_BUSY, "unable to close due to unfinalized " + sqlite3ErrorWithMsg(db, SQLITE_BUSY, "unable to close due to unfinalized " "statements or unfinished backups"); sqlite3_mutex_leave(db->mutex); return SQLITE_BUSY; @@ -982,7 +982,7 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ sqlite3HashClear(&db->aModule); #endif - sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */ + sqlite3Error(db, SQLITE_OK); /* Deallocates any cached error strings. */ sqlite3ValueFree(db->pErr); sqlite3CloseExtensions(db); @@ -1415,7 +1415,7 @@ int sqlite3CreateFunc( p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 0); if( p && (p->funcFlags & SQLITE_FUNC_ENCMASK)==enc && p->nArg==nArg ){ if( db->nVdbeActive ){ - sqlite3Error(db, SQLITE_BUSY, + sqlite3ErrorWithMsg(db, SQLITE_BUSY, "unable to delete/modify user-function due to active statements"); assert( !db->mallocFailed ); return SQLITE_BUSY; @@ -1753,10 +1753,10 @@ int sqlite3_wal_checkpoint_v2( } if( iDb<0 ){ rc = SQLITE_ERROR; - sqlite3Error(db, SQLITE_ERROR, "unknown database: %s", zDb); + sqlite3ErrorWithMsg(db, SQLITE_ERROR, "unknown database: %s", zDb); }else{ rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt); - sqlite3Error(db, rc, 0); + sqlite3Error(db, rc); } rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); @@ -1911,7 +1911,7 @@ const void *sqlite3_errmsg16(sqlite3 *db){ }else{ z = sqlite3_value_text16(db->pErr); if( z==0 ){ - sqlite3Error(db, db->errCode, sqlite3ErrStr(db->errCode)); + sqlite3ErrorWithMsg(db, db->errCode, sqlite3ErrStr(db->errCode)); z = sqlite3_value_text16(db->pErr); } /* A malloc() may have failed within the call to sqlite3_value_text16() @@ -2022,7 +2022,7 @@ static int createCollation( pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 0); if( pColl && pColl->xCmp ){ if( db->nVdbeActive ){ - sqlite3Error(db, SQLITE_BUSY, + sqlite3ErrorWithMsg(db, SQLITE_BUSY, "unable to delete/modify collation sequence due to active statements"); return SQLITE_BUSY; } @@ -2056,7 +2056,7 @@ static int createCollation( pColl->pUser = pCtx; pColl->xDel = xDel; pColl->enc = (u8)(enc2 | (enc & SQLITE_UTF16_ALIGNED)); - sqlite3Error(db, SQLITE_OK, 0); + sqlite3Error(db, SQLITE_OK); return SQLITE_OK; } @@ -2541,7 +2541,7 @@ static int openDatabase( rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg); if( rc!=SQLITE_OK ){ if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; - sqlite3Error(db, rc, zErrMsg ? "%s" : 0, zErrMsg); + sqlite3ErrorWithMsg(db, rc, zErrMsg ? "%s" : 0, zErrMsg); sqlite3_free(zErrMsg); goto opendb_out; } @@ -2553,7 +2553,7 @@ static int openDatabase( if( rc==SQLITE_IOERR_NOMEM ){ rc = SQLITE_NOMEM; } - sqlite3Error(db, rc, 0); + sqlite3Error(db, rc); goto opendb_out; } db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt); @@ -2577,7 +2577,7 @@ static int openDatabase( ** database schema yet. This is delayed until the first time the database ** is accessed. */ - sqlite3Error(db, SQLITE_OK, 0); + sqlite3Error(db, SQLITE_OK); sqlite3RegisterBuiltinFunctions(db); /* Load automatic extensions - extensions that have been registered @@ -2634,7 +2634,7 @@ static int openDatabase( SQLITE_DEFAULT_LOCKING_MODE); #endif - if( rc ) sqlite3Error(db, rc, 0); + if( rc ) sqlite3Error(db, rc); /* Enable the lookaside-malloc subsystem */ setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside, @@ -2996,7 +2996,7 @@ error_out: zColumnName); rc = SQLITE_ERROR; } - sqlite3Error(db, rc, (zErrMsg?"%s":0), zErrMsg); + sqlite3ErrorWithMsg(db, rc, (zErrMsg?"%s":0), zErrMsg); sqlite3DbFree(db, zErrMsg); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); diff --git a/src/malloc.c b/src/malloc.c index 9c11d07767..9fb4303979 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -776,7 +776,7 @@ int sqlite3ApiExit(sqlite3* db, int rc){ */ assert( !db || sqlite3_mutex_held(db->mutex) ); if( db && (db->mallocFailed || rc==SQLITE_IOERR_NOMEM) ){ - sqlite3Error(db, SQLITE_NOMEM, 0); + sqlite3Error(db, SQLITE_NOMEM); db->mallocFailed = 0; rc = SQLITE_NOMEM; } diff --git a/src/notify.c b/src/notify.c index fcab5bfaf0..8137226f35 100644 --- a/src/notify.c +++ b/src/notify.c @@ -184,7 +184,7 @@ int sqlite3_unlock_notify( leaveMutex(); assert( !db->mallocFailed ); - sqlite3Error(db, rc, (rc?"database is deadlocked":0)); + sqlite3ErrorWithMsg(db, rc, (rc?"database is deadlocked":0)); sqlite3_mutex_leave(db->mutex); return rc; } diff --git a/src/prepare.c b/src/prepare.c index c7ba53a1f5..5b92e88513 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -593,7 +593,7 @@ static int sqlite3Prepare( rc = sqlite3BtreeSchemaLocked(pBt); if( rc ){ const char *zDb = db->aDb[i].zName; - sqlite3Error(db, rc, "database schema is locked: %s", zDb); + sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb); testcase( db->flags & SQLITE_ReadUncommitted ); goto end_prepare; } @@ -610,7 +610,7 @@ static int sqlite3Prepare( testcase( nBytes==mxLen ); testcase( nBytes==mxLen+1 ); if( nBytes>mxLen ){ - sqlite3Error(db, SQLITE_TOOBIG, "statement too long"); + sqlite3ErrorWithMsg(db, SQLITE_TOOBIG, "statement too long"); rc = sqlite3ApiExit(db, SQLITE_TOOBIG); goto end_prepare; } @@ -677,10 +677,10 @@ static int sqlite3Prepare( } if( zErrMsg ){ - sqlite3Error(db, rc, "%s", zErrMsg); + sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg); sqlite3DbFree(db, zErrMsg); }else{ - sqlite3Error(db, rc, 0); + sqlite3Error(db, rc); } /* Delete any TriggerPrg structures allocated while parsing this statement. */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5202beff78..65dd7a9279 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3350,7 +3350,8 @@ int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); char sqlite3ExprAffinity(Expr *pExpr); int sqlite3Atoi64(const char*, i64*, int, u8); int sqlite3DecOrHexToI64(const char*, i64*); -void sqlite3Error(sqlite3*, int, const char*,...); +void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...); +void sqlite3Error(sqlite3*,int); void *sqlite3HexToBlob(sqlite3*, const char *z, int n); u8 sqlite3HexToInt(int h); int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); diff --git a/src/util.c b/src/util.c index 619af7f758..1c75e4cfbe 100644 --- a/src/util.c +++ b/src/util.c @@ -111,6 +111,15 @@ int sqlite3Strlen30(const char *z){ return 0x3fffffff & (int)(z2 - z); } +/* +** Set the current error code to err_code and clear any prior error message. +*/ +void sqlite3Error(sqlite3 *db, int err_code){ + assert( db!=0 ); + db->errCode = err_code; + if( db->pErr ) sqlite3ValueSetNull(db->pErr); +} + /* ** Set the most recent error code and error string for the sqlite ** handle "db". The error code is set to "err_code". @@ -132,18 +141,18 @@ int sqlite3Strlen30(const char *z){ ** should be called with err_code set to SQLITE_OK and zFormat set ** to NULL. */ -void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){ +void sqlite3ErrorWithMsg(sqlite3 *db, int err_code, const char *zFormat, ...){ assert( db!=0 ); db->errCode = err_code; - if( zFormat && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){ + if( zFormat==0 ){ + sqlite3Error(db, err_code); + }else if( db->pErr || (db->pErr = sqlite3ValueNew(db))!=0 ){ char *z; va_list ap; va_start(ap, zFormat); z = sqlite3VMPrintf(db, zFormat, ap); va_end(ap); sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC); - }else if( db->pErr ){ - sqlite3ValueSetNull(db->pErr); } } @@ -157,12 +166,12 @@ void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){ ** %T Insert a token ** %S Insert the first element of a SrcList ** -** This function should be used to report any error that occurs whilst +** This function should be used to report any error that occurs while ** compiling an SQL statement (i.e. within sqlite3_prepare()). The ** last thing the sqlite3_prepare() function does is copy the error ** stored by this function into the database handle using sqlite3Error(). -** Function sqlite3Error() should be used during statement execution -** (sqlite3_step() etc.). +** Functions sqlite3Error() or sqlite3ErrorWithMsg() should be used +** during statement execution (sqlite3_step() etc.). */ void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ char *zMsg; diff --git a/src/vdbeapi.c b/src/vdbeapi.c index f6cc2d8c05..675361013a 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -770,7 +770,7 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){ }else{ if( pVm && ALWAYS(pVm->db) ){ sqlite3_mutex_enter(pVm->db->mutex); - sqlite3Error(pVm->db, SQLITE_RANGE, 0); + sqlite3Error(pVm->db, SQLITE_RANGE); } pOut = (Mem*)columnNullValue(); } @@ -1035,14 +1035,14 @@ static int vdbeUnbind(Vdbe *p, int i){ } sqlite3_mutex_enter(p->db->mutex); if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){ - sqlite3Error(p->db, SQLITE_MISUSE, 0); + sqlite3Error(p->db, SQLITE_MISUSE); sqlite3_mutex_leave(p->db->mutex); sqlite3_log(SQLITE_MISUSE, "bind on a busy prepared statement: [%s]", p->zSql); return SQLITE_MISUSE_BKPT; } if( i<1 || i>p->nVar ){ - sqlite3Error(p->db, SQLITE_RANGE, 0); + sqlite3Error(p->db, SQLITE_RANGE); sqlite3_mutex_leave(p->db->mutex); return SQLITE_RANGE; } @@ -1050,7 +1050,7 @@ static int vdbeUnbind(Vdbe *p, int i){ pVar = &p->aVar[i]; sqlite3VdbeMemRelease(pVar); pVar->flags = MEM_Null; - sqlite3Error(p->db, SQLITE_OK, 0); + sqlite3Error(p->db, SQLITE_OK); /* If the bit corresponding to this variable in Vdbe.expmask is set, then ** binding a new value to this variable invalidates the current query plan. @@ -1092,7 +1092,7 @@ static int bindText( if( rc==SQLITE_OK && encoding!=0 ){ rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); } - sqlite3Error(p->db, rc, 0); + sqlite3Error(p->db, rc); rc = sqlite3ApiExit(p->db, rc); } sqlite3_mutex_leave(p->db->mutex); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 513481bf00..58f39a48a8 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2497,7 +2497,7 @@ int sqlite3VdbeTransferError(Vdbe *p){ db->mallocFailed = mallocFailed; db->errCode = rc; }else{ - sqlite3Error(db, rc, 0); + sqlite3Error(db, rc); } return rc; } @@ -2560,7 +2560,7 @@ int sqlite3VdbeReset(Vdbe *p){ ** to sqlite3_step(). For consistency (since sqlite3_step() was ** called), set the database error in this case as well. */ - sqlite3Error(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg); + sqlite3ErrorWithMsg(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg); sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = 0; } diff --git a/src/vdbeblob.c b/src/vdbeblob.c index 083f3f413c..71bd8816d5 100644 --- a/src/vdbeblob.c +++ b/src/vdbeblob.c @@ -318,7 +318,7 @@ blob_open_out: if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt); sqlite3DbFree(db, pBlob); } - sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr); + sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); sqlite3ParserReset(pParse); sqlite3StackFree(db, pParse); @@ -371,7 +371,7 @@ static int blobReadWrite( if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){ /* Request is out of range. Return a transient error. */ rc = SQLITE_ERROR; - sqlite3Error(db, SQLITE_ERROR, 0); + sqlite3Error(db, SQLITE_ERROR); }else if( v==0 ){ /* If there is no statement handle, then the blob-handle has ** already been invalidated. Return SQLITE_ABORT in this case. @@ -451,7 +451,7 @@ int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ char *zErr; rc = blobSeekToRow(p, iRow, &zErr); if( rc!=SQLITE_OK ){ - sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr); + sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); } assert( rc!=SQLITE_SCHEMA ); diff --git a/src/vtab.c b/src/vtab.c index ad18af48a4..c7a8a5a33f 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -699,7 +699,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ sqlite3_mutex_enter(db->mutex); if( !db->pVtabCtx || !(pTab = db->pVtabCtx->pTab) ){ - sqlite3Error(db, SQLITE_MISUSE, 0); + sqlite3Error(db, SQLITE_MISUSE); sqlite3_mutex_leave(db->mutex); return SQLITE_MISUSE_BKPT; } @@ -727,7 +727,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ } db->pVtabCtx->pTab = 0; }else{ - sqlite3Error(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); + sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); rc = SQLITE_ERROR; } @@ -1088,7 +1088,7 @@ int sqlite3_vtab_config(sqlite3 *db, int op, ...){ } va_end(ap); - if( rc!=SQLITE_OK ) sqlite3Error(db, rc, 0); + if( rc!=SQLITE_OK ) sqlite3Error(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } From 2f2b2b85800866c9cebde588d09706feed6462eb Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 18:48:25 +0000 Subject: [PATCH 08/29] Performance enhancement in sqlite3PutVarint(). FossilOrigin-Name: a929be551924144c9bc7aab608404d59e479abb5 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/sqliteInt.h | 25 +++++-------------------- src/util.c | 27 ++++++++------------------- src/vdbemem.c | 2 +- 5 files changed, 23 insertions(+), 49 deletions(-) diff --git a/manifest b/manifest index 2ec516f887..4718b15953 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Split\sthe\ssqlite3Error()\sroutine\sinto\ssqlite3Error()\sand\nsqlite3ErrorWithMsg(),\sfor\sa\sslight\ssize\sreduction\sand\sperformance\sincrease. -D 2014-08-22T18:00:11.621 +C Performance\senhancement\sin\ssqlite3PutVarint(). +D 2014-08-22T18:48:25.634 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -228,7 +228,7 @@ F src/shell.c 728d2226594d356bf4fbdbdfd08538fd78fd06f3 F src/sqlite.h.in ed9d35990c61f0388ca6405706455c4095310553 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 937869c407c61026443c879e8c90a9dff05d2d27 +F src/sqliteInt.h d8a9be2aa123a78c90ad4aba09b23e7dd3f8cc9f F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -282,7 +282,7 @@ F src/tokenize.c ae45399d6252b4d736af43bee1576ce7bff86aec F src/trigger.c 4bddd12803275aa98f1c7ce0118fceb02b2167f6 F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059 F src/utf.c a0314e637768a030e6e84a957d0c4f6ba910cc05 -F src/util.c 524127b3c330b9f490a505ff6eb7f80dfc873a3a +F src/util.c 068dcd26354a3898ccc64ad5c4bdb95a7a15d33a F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 F src/vdbe.c f7f4066e4d6e3858878d76ce9288ea603e12ddf6 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 @@ -290,7 +290,7 @@ F src/vdbeInt.h f5513f2b5ac1e2c5128996c7ea23add256a301df F src/vdbeapi.c 49b8d2943d02d276b4efef114578251a3277f47d F src/vdbeaux.c f7fdc59e2eefa6fc4ba7324b03ea6f8f66e98d62 F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4 -F src/vdbemem.c d90a1e8acf8b63dc9d14cbbea12bfec6cec31394 +F src/vdbemem.c 4a64659ed8e4c3b18a9238e038145ab1bdcd146f F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 F src/vtab.c 019dbfd0406a7447c990e1f7bd1dfcdb8895697f @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f7f2160db014f0ae11ad13c8ad70ad3444124e3e -R 668369bbbf2d81407f36345226c5d2a9 +P cf561d1f0bb60b3d638632d20bd686dda4fa4a04 +R 892fbe852e37f91de1b9f5afa35c0502 U drh -Z bddb035a8072a327798c78fbe23bcf26 +Z c70614e9322ab39ef4e9fbe07eb13b05 diff --git a/manifest.uuid b/manifest.uuid index 5842d66545..12c08a2c09 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cf561d1f0bb60b3d638632d20bd686dda4fa4a04 \ No newline at end of file +a929be551924144c9bc7aab608404d59e479abb5 \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 65dd7a9279..a534c5cebc 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3307,38 +3307,23 @@ u64 sqlite3LogEstToInt(LogEst); /* ** Routines to read and write variable-length integers. These used to ** be defined locally, but now we use the varint routines in the util.c -** file. Code should use the MACRO forms below, as the Varint32 versions -** are coded to assume the single byte case is already handled (which -** the MACRO form does). +** file. */ int sqlite3PutVarint(unsigned char*, u64); -int sqlite3PutVarint32(unsigned char*, u32); u8 sqlite3GetVarint(const unsigned char *, u64 *); u8 sqlite3GetVarint32(const unsigned char *, u32 *); int sqlite3VarintLen(u64 v); /* -** The header of a record consists of a sequence variable-length integers. -** These integers are almost always small and are encoded as a single byte. -** The following macros take advantage this fact to provide a fast encode -** and decode of the integers in a record header. It is faster for the common -** case where the integer is a single byte. It is a little slower when the -** integer is two or more bytes. But overall it is faster. -** -** The following expressions are equivalent: -** -** x = sqlite3GetVarint32( A, &B ); -** x = sqlite3PutVarint32( A, B ); -** -** x = getVarint32( A, B ); -** x = putVarint32( A, B ); -** +** The common case is for a varint to be a single byte. They following +** macros handle the common case without a procedure call, but then call +** the procedure for larger varints. */ #define getVarint32(A,B) \ (u8)((*(A)<(u8)0x80)?((B)=(u32)*(A)),1:sqlite3GetVarint32((A),(u32 *)&(B))) #define putVarint32(A,B) \ (u8)(((u32)(B)<(u32)0x80)?(*(A)=(unsigned char)(B)),1:\ - sqlite3PutVarint32((A),(B))) + sqlite3PutVarint((A),(B))) #define getVarint sqlite3GetVarint #define putVarint sqlite3PutVarint diff --git a/src/util.c b/src/util.c index 1c75e4cfbe..839a4a4636 100644 --- a/src/util.c +++ b/src/util.c @@ -708,7 +708,7 @@ int sqlite3Atoi(const char *z){ ** bit clear. Except, if we get to the 9th byte, it stores the full ** 8 bits and is the last byte. */ -int sqlite3PutVarint(unsigned char *p, u64 v){ +static int SQLITE_NOINLINE putVarint64(unsigned char *p, u64 v){ int i, j, n; u8 buf[10]; if( v & (((u64)0xff000000)<<32) ){ @@ -732,28 +732,17 @@ int sqlite3PutVarint(unsigned char *p, u64 v){ } return n; } - -/* -** This routine is a faster version of sqlite3PutVarint() that only -** works for 32-bit positive integers and which is optimized for -** the common case of small integers. A MACRO version, putVarint32, -** is provided which inlines the single-byte case. All code should use -** the MACRO version as this function assumes the single-byte case has -** already been handled. -*/ -int sqlite3PutVarint32(unsigned char *p, u32 v){ -#ifndef putVarint32 - if( (v & ~0x7f)==0 ){ - p[0] = v; +int sqlite3PutVarint(unsigned char *p, u64 v){ + if( v<=0x7f ){ + p[0] = v&0x7f; return 1; } -#endif - if( (v & ~0x3fff)==0 ){ - p[0] = (u8)((v>>7) | 0x80); - p[1] = (u8)(v & 0x7f); + if( v<=0x3fff ){ + p[0] = ((v>>7)&0x7f)|0x80; + p[1] = v&0x7f; return 2; } - return sqlite3PutVarint(p, v); + return putVarint64(p,v); } /* diff --git a/src/vdbemem.c b/src/vdbemem.c index cf44aa7e2d..08cf40eaa8 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -1130,7 +1130,7 @@ static void recordFunc( sqlite3_result_error_nomem(context); }else{ aRet[0] = nSerial+1; - sqlite3PutVarint(&aRet[1], iSerial); + putVarint32(&aRet[1], iSerial); sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial); sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT); sqlite3DbFree(db, aRet); From a8dcba9199cef12aa979e6be7c98c50d5a777c9e Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 20:35:29 +0000 Subject: [PATCH 09/29] Combine the pcacheAddToDirtyList() and pcacheRemoveFromDirtyList() routines into a single pcacheManageDirtyList() routine. The resulting binary code is slightly faster and a few bytes smaller. FossilOrigin-Name: 6bcf1af6a48dbda5ac6f6b3b02810bdfc4730000 --- manifest | 12 ++-- manifest.uuid | 2 +- src/pcache.c | 150 ++++++++++++++++++++++++-------------------------- 3 files changed, 80 insertions(+), 84 deletions(-) diff --git a/manifest b/manifest index 4718b15953..63a01156f0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\senhancement\sin\ssqlite3PutVarint(). -D 2014-08-22T18:48:25.634 +C Combine\sthe\spcacheAddToDirtyList()\sand\spcacheRemoveFromDirtyList()\sroutines\ninto\sa\ssingle\spcacheManageDirtyList()\sroutine.\s\sThe\sresulting\sbinary\scode\sis\nslightly\sfaster\sand\sa\sfew\sbytes\ssmaller. +D 2014-08-22T20:35:29.948 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -214,7 +214,7 @@ F src/os_win.h 09e751b20bbc107ffbd46e13555dc73576d88e21 F src/pager.c f6bb1fa6cdf2062f2d8aec3e64db302bca519ab8 F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428 F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0 -F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2 +F src/pcache.c da602c5447051705cab41604bf3276815eb569d0 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c F src/pragma.c d10ef67c4de79f78188b965b4b7988aff1d66f2e @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P cf561d1f0bb60b3d638632d20bd686dda4fa4a04 -R 892fbe852e37f91de1b9f5afa35c0502 +P a929be551924144c9bc7aab608404d59e479abb5 +R 2ac5f67b7ba10391163889b9ff4c4145 U drh -Z c70614e9322ab39ef4e9fbe07eb13b05 +Z 6bffc4c72a94895b60e52defb6944efd diff --git a/manifest.uuid b/manifest.uuid index 12c08a2c09..da73897dba 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a929be551924144c9bc7aab608404d59e479abb5 \ No newline at end of file +6bcf1af6a48dbda5ac6f6b3b02810bdfc4730000 \ No newline at end of file diff --git a/src/pcache.c b/src/pcache.c index e18bf93be0..2e4b5d78b2 100644 --- a/src/pcache.c +++ b/src/pcache.c @@ -62,71 +62,73 @@ static int pcacheCheckSynced(PCache *pCache){ } #endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */ -/* -** Remove page pPage from the list of dirty pages. -*/ -static void pcacheRemoveFromDirtyList(PgHdr *pPage){ - PCache *p = pPage->pCache; - - assert( pPage->pDirtyNext || pPage==p->pDirtyTail ); - assert( pPage->pDirtyPrev || pPage==p->pDirty ); - - /* Update the PCache1.pSynced variable if necessary. */ - if( p->pSynced==pPage ){ - PgHdr *pSynced = pPage->pDirtyPrev; - while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){ - pSynced = pSynced->pDirtyPrev; - } - p->pSynced = pSynced; - } - - if( pPage->pDirtyNext ){ - pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev; - }else{ - assert( pPage==p->pDirtyTail ); - p->pDirtyTail = pPage->pDirtyPrev; - } - if( pPage->pDirtyPrev ){ - pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext; - }else{ - assert( pPage==p->pDirty ); - p->pDirty = pPage->pDirtyNext; - if( p->pDirty==0 && p->bPurgeable ){ - assert( p->eCreate==1 ); - p->eCreate = 2; - } - } - pPage->pDirtyNext = 0; - pPage->pDirtyPrev = 0; - - expensive_assert( pcacheCheckSynced(p) ); -} +/* Allowed values for second argument to pcacheManageDirtyList() */ +#define PCACHE_DIRTYLIST_REMOVE 1 /* Remove pPage from dirty list */ +#define PCACHE_DIRTYLIST_ADD 2 /* Add pPage to the dirty list */ +#define PCACHE_DIRTYLIST_FRONT 3 /* Move pPage to the front of the list */ /* -** Add page pPage to the head of the dirty list (PCache1.pDirty is set to -** pPage). +** Manage pPage's participation on the dirty list. Bits of the addRemove +** argument determines what operation to do. The 0x01 bit means first +** remove pPage from the dirty list. The 0x02 means add pPage back to +** the dirty list. Doing both moves pPage to the front of the dirty list. */ -static void pcacheAddToDirtyList(PgHdr *pPage){ +static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){ PCache *p = pPage->pCache; - assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage ); - - pPage->pDirtyNext = p->pDirty; - if( pPage->pDirtyNext ){ - assert( pPage->pDirtyNext->pDirtyPrev==0 ); - pPage->pDirtyNext->pDirtyPrev = pPage; - }else if( p->bPurgeable ){ - assert( p->eCreate==2 ); - p->eCreate = 1; + if( addRemove & PCACHE_DIRTYLIST_REMOVE ){ + assert( pPage->pDirtyNext || pPage==p->pDirtyTail ); + assert( pPage->pDirtyPrev || pPage==p->pDirty ); + + /* Update the PCache1.pSynced variable if necessary. */ + if( p->pSynced==pPage ){ + PgHdr *pSynced = pPage->pDirtyPrev; + while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){ + pSynced = pSynced->pDirtyPrev; + } + p->pSynced = pSynced; + } + + if( pPage->pDirtyNext ){ + pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev; + }else{ + assert( pPage==p->pDirtyTail ); + p->pDirtyTail = pPage->pDirtyPrev; + } + if( pPage->pDirtyPrev ){ + pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext; + }else{ + assert( pPage==p->pDirty ); + p->pDirty = pPage->pDirtyNext; + if( p->pDirty==0 && p->bPurgeable ){ + assert( p->eCreate==1 ); + p->eCreate = 2; + } + } + pPage->pDirtyNext = 0; + pPage->pDirtyPrev = 0; + expensive_assert( pcacheCheckSynced(p) ); } - p->pDirty = pPage; - if( !p->pDirtyTail ){ - p->pDirtyTail = pPage; + if( addRemove & PCACHE_DIRTYLIST_ADD ){ + assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage ); + + pPage->pDirtyNext = p->pDirty; + if( pPage->pDirtyNext ){ + assert( pPage->pDirtyNext->pDirtyPrev==0 ); + pPage->pDirtyNext->pDirtyPrev = pPage; + }else if( p->bPurgeable ){ + assert( p->eCreate==2 ); + p->eCreate = 1; + } + p->pDirty = pPage; + if( !p->pDirtyTail ){ + p->pDirtyTail = pPage; + } + if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){ + p->pSynced = pPage; + } + expensive_assert( pcacheCheckSynced(p) ); } - if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){ - p->pSynced = pPage; - } - expensive_assert( pcacheCheckSynced(p) ); } /* @@ -134,12 +136,11 @@ static void pcacheAddToDirtyList(PgHdr *pPage){ ** being used for an in-memory database, this function is a no-op. */ static void pcacheUnpin(PgHdr *p){ - PCache *pCache = p->pCache; - if( pCache->bPurgeable ){ + if( p->pCache->bPurgeable ){ if( p->pgno==1 ){ - pCache->pPage1 = 0; + p->pCache->pPage1 = 0; } - sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 0); + sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 0); } } @@ -332,18 +333,16 @@ int sqlite3PcacheFetch( ** Decrement the reference count on a page. If the page is clean and the ** reference count drops to 0, then it is made elible for recycling. */ -void sqlite3PcacheRelease(PgHdr *p){ +void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){ assert( p->nRef>0 ); p->nRef--; if( p->nRef==0 ){ - PCache *pCache = p->pCache; - pCache->nRef--; + p->pCache->nRef--; if( (p->flags&PGHDR_DIRTY)==0 ){ pcacheUnpin(p); }else{ /* Move the page to the head of the dirty list. */ - pcacheRemoveFromDirtyList(p); - pcacheAddToDirtyList(p); + pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT); } } } @@ -362,17 +361,15 @@ void sqlite3PcacheRef(PgHdr *p){ ** page pointed to by p is invalid. */ void sqlite3PcacheDrop(PgHdr *p){ - PCache *pCache; assert( p->nRef==1 ); if( p->flags&PGHDR_DIRTY ){ - pcacheRemoveFromDirtyList(p); + pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE); } - pCache = p->pCache; - pCache->nRef--; + p->pCache->nRef--; if( p->pgno==1 ){ - pCache->pPage1 = 0; + p->pCache->pPage1 = 0; } - sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 1); + sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 1); } /* @@ -384,7 +381,7 @@ void sqlite3PcacheMakeDirty(PgHdr *p){ assert( p->nRef>0 ); if( 0==(p->flags & PGHDR_DIRTY) ){ p->flags |= PGHDR_DIRTY; - pcacheAddToDirtyList( p); + pcacheManageDirtyList(p, PCACHE_DIRTYLIST_ADD); } } @@ -394,7 +391,7 @@ void sqlite3PcacheMakeDirty(PgHdr *p){ */ void sqlite3PcacheMakeClean(PgHdr *p){ if( (p->flags & PGHDR_DIRTY) ){ - pcacheRemoveFromDirtyList(p); + pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE); p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC); if( p->nRef==0 ){ pcacheUnpin(p); @@ -433,8 +430,7 @@ void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){ sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno); p->pgno = newPgno; if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){ - pcacheRemoveFromDirtyList(p); - pcacheAddToDirtyList(p); + pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT); } } From 75e2a2d362175e222873a90d1d356bac92b31037 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 21:58:10 +0000 Subject: [PATCH 10/29] Performance enhancements in the b-tree mutex logic. FossilOrigin-Name: 8914530644f938a7a98e25ea1fb0bca1f9d79101 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btmutex.c | 19 ++++++++++++++++--- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 63a01156f0..812c653a73 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Combine\sthe\spcacheAddToDirtyList()\sand\spcacheRemoveFromDirtyList()\sroutines\ninto\sa\ssingle\spcacheManageDirtyList()\sroutine.\s\sThe\sresulting\sbinary\scode\sis\nslightly\sfaster\sand\sa\sfew\sbytes\ssmaller. -D 2014-08-22T20:35:29.948 +C Performance\senhancements\sin\sthe\sb-tree\smutex\slogic. +D 2014-08-22T21:58:10.354 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -167,7 +167,7 @@ F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a31809c65623cc41849b94d368917f8bb66e6a7e F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb -F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 +F src/btmutex.c ec9d3f1295dafeb278c3830211cc5584132468f4 F src/btree.c 4195fed5741b4dbcc9831b623aec487258f3e62d F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a929be551924144c9bc7aab608404d59e479abb5 -R 2ac5f67b7ba10391163889b9ff4c4145 +P 6bcf1af6a48dbda5ac6f6b3b02810bdfc4730000 +R 24d5ffe2f1d9679a613707454c70f45a U drh -Z 6bffc4c72a94895b60e52defb6944efd +Z 6801ae93f83fb9ed7a247305de8bd03a diff --git a/manifest.uuid b/manifest.uuid index da73897dba..5367fb5584 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6bcf1af6a48dbda5ac6f6b3b02810bdfc4730000 \ No newline at end of file +8914530644f938a7a98e25ea1fb0bca1f9d79101 \ No newline at end of file diff --git a/src/btmutex.c b/src/btmutex.c index d87d4d5fee..9672687fe0 100644 --- a/src/btmutex.c +++ b/src/btmutex.c @@ -38,7 +38,7 @@ static void lockBtreeMutex(Btree *p){ ** Release the BtShared mutex associated with B-Tree handle p and ** clear the p->locked boolean. */ -static void unlockBtreeMutex(Btree *p){ +static void SQLITE_NOINLINE unlockBtreeMutex(Btree *p){ BtShared *pBt = p->pBt; assert( p->locked==1 ); assert( sqlite3_mutex_held(pBt->mutex) ); @@ -49,6 +49,9 @@ static void unlockBtreeMutex(Btree *p){ p->locked = 0; } +/* Forward reference */ +static void SQLITE_NOINLINE btreeLockCarefully(Btree *p); + /* ** Enter a mutex on the given BTree object. ** @@ -66,8 +69,6 @@ static void unlockBtreeMutex(Btree *p){ ** subsequent Btrees that desire a lock. */ void sqlite3BtreeEnter(Btree *p){ - Btree *pLater; - /* Some basic sanity checking on the Btree. The list of Btrees ** connected by pNext and pPrev should be in sorted order by ** Btree.pBt value. All elements of the list should belong to @@ -92,6 +93,17 @@ void sqlite3BtreeEnter(Btree *p){ if( !p->sharable ) return; p->wantToLock++; if( p->locked ) return; + btreeLockCarefully(p); +} + +/* This is a helper function for sqlite3BtreeLock(). By moving +** complex, but seldom used logic, out of sqlite3BtreeLock() and +** into this routine, we avoid unnecessary stack pointer changes +** and thus help the sqlite3BtreeLock() routine to run much faster +** in the common case. +*/ +static void SQLITE_NOINLINE btreeLockCarefully(Btree *p){ + Btree *pLater; /* In most cases, we should be able to acquire the lock we ** want without having to go throught the ascending lock @@ -124,6 +136,7 @@ void sqlite3BtreeEnter(Btree *p){ } } + /* ** Exit the recursive mutex on a Btree. */ From 637f3d83b9455eeb87bce698877f9d8c03ec912b Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 22:26:07 +0000 Subject: [PATCH 11/29] Factor the saveAllCursors() routine of btree.c into two separate routines, for a noticable performance improvement. FossilOrigin-Name: 3eb084390382c108e9b0ff0b29dede58ebb149bc --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 35 +++++++++++++++++++++++++++++++---- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 812c653a73..a0fd1d8b2e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\senhancements\sin\sthe\sb-tree\smutex\slogic. -D 2014-08-22T21:58:10.354 +C Factor\sthe\ssaveAllCursors()\sroutine\sof\sbtree.c\sinto\stwo\sseparate\sroutines,\nfor\sa\snoticable\sperformance\simprovement. +D 2014-08-22T22:26:07.834 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -168,7 +168,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a31809c65623cc41849b94d368917f8bb66e6a7e F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c ec9d3f1295dafeb278c3830211cc5584132468f4 -F src/btree.c 4195fed5741b4dbcc9831b623aec487258f3e62d +F src/btree.c 776885dfef3033af7e8eabbf004481f219870a1d F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3 F src/build.c 058e3aadb1376521ff291735237edf4c10f438fb @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 6bcf1af6a48dbda5ac6f6b3b02810bdfc4730000 -R 24d5ffe2f1d9679a613707454c70f45a +P 8914530644f938a7a98e25ea1fb0bca1f9d79101 +R 036983fb95199f1ba06f1397f389a453 U drh -Z 6801ae93f83fb9ed7a247305de8bd03a +Z 9ea20fed62648c22294e9e322338cabb diff --git a/manifest.uuid b/manifest.uuid index 5367fb5584..334a3ae4c0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8914530644f938a7a98e25ea1fb0bca1f9d79101 \ No newline at end of file +3eb084390382c108e9b0ff0b29dede58ebb149bc \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 56718b69d6..6da3715e30 100644 --- a/src/btree.c +++ b/src/btree.c @@ -629,16 +629,42 @@ static int saveCursorPosition(BtCursor *pCur){ return rc; } +/* Forward reference */ +static int SQLITE_NOINLINE saveCursorsOnList(BtCursor*,Pgno,BtCursor*); + /* ** Save the positions of all cursors (except pExcept) that are open on -** the table with root-page iRoot. Usually, this is called just before cursor -** pExcept is used to modify the table (BtreeDelete() or BtreeInsert()). +** the table with root-page iRoot. "Saving the cursor position" means that +** the location in the btree is remembered in such a way that it can be +** moved back to the same spot after the btree has been modified. This +** routine is called just before cursor pExcept is used to modify the +** table, for example in BtreeDelete() or BtreeInsert(). +** +** Implementation note: This routine merely checks to see if any cursors +** need to be saved. It calls out to saveCursorsOnList() in the (unusual) +** event that cursors are in need to being saved. */ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ - BtCursor *p; assert( sqlite3_mutex_held(pBt->mutex) ); assert( pExcept==0 || pExcept->pBt==pBt ); + BtCursor *p; for(p=pBt->pCursor; p; p=p->pNext){ + if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ) break; + } + return p ? saveCursorsOnList(p, iRoot, pExcept) : SQLITE_OK; +} + +/* This helper routine to saveAllCursors does the actual work of saving +** the cursors if and when a cursor is found that actually requires saving. +** The common case is that no cursors need to be saved, so this routine is +** broken out from its caller to avoid unnecessary stack pointer movement. +*/ +static int SQLITE_NOINLINE saveCursorsOnList( + BtCursor *p, /* The first cursor that needs saving */ + Pgno iRoot, /* Only save cursor with this iRoot. Save all if zero */ + BtCursor *pExcept /* Do not save this cursor */ +){ + do{ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){ if( p->eState==CURSOR_VALID ){ int rc = saveCursorPosition(p); @@ -650,7 +676,8 @@ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ btreeReleaseAllCursorPages(p); } } - } + p = p->pNext; + }while( p ); return SQLITE_OK; } From 6848dad89477be4146d535e7a2646300c472f429 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 22 Aug 2014 23:33:03 +0000 Subject: [PATCH 12/29] Another performance tweak: Split the sqlite3BtreeCursorHasMoved() routine into two with the second routine named sqlite3BtreeCursorRestore(). The first now only reports whether or not the cursor has moved and the second tries to restore the cursor. This allows the sqlite3VdbeCursorMoveto() routine to be refactored to avoid stack pointer movements, for a noticable performance gain. FossilOrigin-Name: ce123b5c592556a8cd38b01fcc91ba76231d3098 --- manifest | 16 ++++++------ manifest.uuid | 2 +- src/btree.c | 51 ++++++++++++++++++++++--------------- src/btree.h | 3 ++- src/vdbeaux.c | 69 ++++++++++++++++++++++++++++++++++----------------- 5 files changed, 88 insertions(+), 53 deletions(-) diff --git a/manifest b/manifest index a0fd1d8b2e..98cd57119e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Factor\sthe\ssaveAllCursors()\sroutine\sof\sbtree.c\sinto\stwo\sseparate\sroutines,\nfor\sa\snoticable\sperformance\simprovement. -D 2014-08-22T22:26:07.834 +C Another\sperformance\stweak:\sSplit\sthe\ssqlite3BtreeCursorHasMoved()\sroutine\s\ninto\stwo\swith\sthe\ssecond\sroutine\snamed\ssqlite3BtreeCursorRestore().\s\sThe\sfirst\nnow\sonly\sreports\swhether\sor\snot\sthe\scursor\shas\smoved\sand\sthe\ssecond\stries\sto\nrestore\sthe\scursor.\s\sThis\sallows\sthe\ssqlite3VdbeCursorMoveto()\sroutine\sto\sbe\nrefactored\sto\savoid\sstack\spointer\smovements,\sfor\sa\snoticable\sperformance\sgain. +D 2014-08-22T23:33:03.189 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -168,8 +168,8 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a31809c65623cc41849b94d368917f8bb66e6a7e F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c ec9d3f1295dafeb278c3830211cc5584132468f4 -F src/btree.c 776885dfef3033af7e8eabbf004481f219870a1d -F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a +F src/btree.c c4b4e1c9524ba7b7dab840e6f8b29e2379a3bdd2 +F src/btree.h a79aa6a71e7f1055f01052b7f821bd1c2dce95c8 F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3 F src/build.c 058e3aadb1376521ff291735237edf4c10f438fb F src/callback.c b97d0695ffcf6a8710ee445ffe56ee387d4d8a6f @@ -288,7 +288,7 @@ F src/vdbe.c f7f4066e4d6e3858878d76ce9288ea603e12ddf6 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 F src/vdbeInt.h f5513f2b5ac1e2c5128996c7ea23add256a301df F src/vdbeapi.c 49b8d2943d02d276b4efef114578251a3277f47d -F src/vdbeaux.c f7fdc59e2eefa6fc4ba7324b03ea6f8f66e98d62 +F src/vdbeaux.c dba006f67c9fd1b1d07ee7fb0fb38aa1905161d1 F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4 F src/vdbemem.c 4a64659ed8e4c3b18a9238e038145ab1bdcd146f F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 8914530644f938a7a98e25ea1fb0bca1f9d79101 -R 036983fb95199f1ba06f1397f389a453 +P 3eb084390382c108e9b0ff0b29dede58ebb149bc +R 356d2e894dc7576ad768e53fab77ee5b U drh -Z 9ea20fed62648c22294e9e322338cabb +Z 78a9bc2b7c59c5e05ea01f499ba8646b diff --git a/manifest.uuid b/manifest.uuid index 334a3ae4c0..af6d676ce0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3eb084390382c108e9b0ff0b29dede58ebb149bc \ No newline at end of file +ce123b5c592556a8cd38b01fcc91ba76231d3098 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 6da3715e30..23de31db07 100644 --- a/src/btree.c +++ b/src/btree.c @@ -762,37 +762,48 @@ static int btreeRestoreCursorPosition(BtCursor *pCur){ SQLITE_OK) /* -** Determine whether or not a cursor has moved from the position it -** was last placed at. Cursors can move when the row they are pointing -** at is deleted out from under them. +** Determine whether or not a cursor has moved from the position where +** it was last placed, or has been invalidated for any other reason. +** Cursors can move when the row they are pointing at is deleted out +** from under them, for example. Cursor might also move if a btree +** is rebalanced. ** -** This routine returns an error code if something goes wrong. The -** integer *pHasMoved is set as follows: +** Calling this routine with a NULL cursor pointer returns false. ** -** 0: The cursor is unchanged -** 1: The cursor is still pointing at the same row, but the pointers -** returned by sqlite3BtreeKeyFetch() or sqlite3BtreeDataFetch() -** might now be invalid because of a balance() or other change to the -** b-tree. -** 2: The cursor is no longer pointing to the row. The row might have -** been deleted out from under the cursor. +** Use the separate sqlite3BtreeCursorRestore() routine to restore a cursor +** back to where it ought to be if this routine returns true. */ -int sqlite3BtreeCursorHasMoved(BtCursor *pCur, int *pHasMoved){ +int sqlite3BtreeCursorHasMoved(BtCursor *pCur){ + return pCur && pCur->eState!=CURSOR_VALID; +} + +/* +** This routine restores a cursor back to its original position after it +** has been moved by some outside activity (such as a btree rebalance or +** a row having been deleted out from under the cursor). +** +** On success, the *pDifferentRow parameter is false if the cursor is left +** pointing at exactly the same row. *pDifferntRow is the row the cursor +** was pointing to has been deleted, forcing the cursor to point to some +** nearby row. +** +** This routine should only be called for a cursor that just returned +** TRUE from sqlite3BtreeCursorHasMoved(). +*/ +int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow){ int rc; - if( pCur->eState==CURSOR_VALID ){ - *pHasMoved = 0; - return SQLITE_OK; - } + assert( pCur!=0 ); + assert( pCur->eState!=CURSOR_VALID ); rc = restoreCursorPosition(pCur); if( rc ){ - *pHasMoved = 2; + *pDifferentRow = 1; return rc; } if( pCur->eState!=CURSOR_VALID || NEVER(pCur->skipNext!=0) ){ - *pHasMoved = 2; + *pDifferentRow = 1; }else{ - *pHasMoved = 1; + *pDifferentRow = 0; } return SQLITE_OK; } diff --git a/src/btree.h b/src/btree.h index 7118534f93..38abdca1a2 100644 --- a/src/btree.h +++ b/src/btree.h @@ -169,7 +169,8 @@ int sqlite3BtreeMovetoUnpacked( int bias, int *pRes ); -int sqlite3BtreeCursorHasMoved(BtCursor*, int*); +int sqlite3BtreeCursorHasMoved(BtCursor*); +int sqlite3BtreeCursorRestore(BtCursor*, int*); int sqlite3BtreeDelete(BtCursor*); int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, const void *pData, int nData, diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 58f39a48a8..2037121ddc 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2713,6 +2713,48 @@ void sqlite3VdbeDelete(Vdbe *p){ sqlite3DbFree(db, p); } +/* +** The cursor "p" has a pending seek operation that has not yet been +** carried out. Seek the cursor now. If an error occurs, return +** the appropriate error code. +*/ +static int SQLITE_NOINLINE handleDeferredMoveto(VdbeCursor *p){ + int res, rc; +#ifdef SQLITE_TEST + extern int sqlite3_search_count; +#endif + assert( p->deferredMoveto ); + assert( p->isTable ); + rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res); + if( rc ) return rc; + p->lastRowid = p->movetoTarget; + if( res!=0 ) return SQLITE_CORRUPT_BKPT; + p->rowidIsValid = 1; +#ifdef SQLITE_TEST + sqlite3_search_count++; +#endif + p->deferredMoveto = 0; + p->cacheStatus = CACHE_STALE; + return SQLITE_OK; +} + +/* +** Something has moved cursor "p" out of place. Maybe the row it was +** pointed to was deleted out from under it. Or maybe the btree was +** rebalanced. Whatever the cause, try to restore "p" to the place it +** is suppose to be pointing. If the row was deleted out from under the +** cursor, set the cursor to point to a NULL row. +*/ +static int SQLITE_NOINLINE handleMovedCursor(VdbeCursor *p){ + int isDifferentRow, rc; + assert( p->pCursor!=0 ); + assert( sqlite3BtreeCursorHasMoved(p->pCursor) ); + rc = sqlite3BtreeCursorRestore(p->pCursor, &isDifferentRow); + p->cacheStatus = CACHE_STALE; + if( isDifferentRow ) p->nullRow = 1; + return rc; +} + /* ** Make sure the cursor p is ready to read or write the row to which it ** was last positioned. Return an error code if an OOM fault or I/O error @@ -2728,29 +2770,10 @@ void sqlite3VdbeDelete(Vdbe *p){ */ int sqlite3VdbeCursorMoveto(VdbeCursor *p){ if( p->deferredMoveto ){ - int res, rc; -#ifdef SQLITE_TEST - extern int sqlite3_search_count; -#endif - assert( p->isTable ); - rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res); - if( rc ) return rc; - p->lastRowid = p->movetoTarget; - if( res!=0 ) return SQLITE_CORRUPT_BKPT; - p->rowidIsValid = 1; -#ifdef SQLITE_TEST - sqlite3_search_count++; -#endif - p->deferredMoveto = 0; - p->cacheStatus = CACHE_STALE; - }else if( p->pCursor ){ - int hasMoved; - int rc = sqlite3BtreeCursorHasMoved(p->pCursor, &hasMoved); - if( rc ) return rc; - if( hasMoved ){ - p->cacheStatus = CACHE_STALE; - if( hasMoved==2 ) p->nullRow = 1; - } + return handleDeferredMoveto(p); + } + if( sqlite3BtreeCursorHasMoved(p->pCursor) ){ + return handleMovedCursor(p); } return SQLITE_OK; } From bd9507c8daa292989b382628cb7fedba18dc2fb3 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Aug 2014 17:21:37 +0000 Subject: [PATCH 13/29] Performance optimization in the applyAffinity() logic inside the VDBE. FossilOrigin-Name: 25f2246be404f38b4f8dd70397cd1454d46358c4 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/vdbe.c | 34 +++++++++++++++++++++++----------- src/vdbeInt.h | 2 +- src/vdbemem.c | 13 +++++++------ 5 files changed, 40 insertions(+), 27 deletions(-) diff --git a/manifest b/manifest index 98cd57119e..8450ec16e4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Another\sperformance\stweak:\sSplit\sthe\ssqlite3BtreeCursorHasMoved()\sroutine\s\ninto\stwo\swith\sthe\ssecond\sroutine\snamed\ssqlite3BtreeCursorRestore().\s\sThe\sfirst\nnow\sonly\sreports\swhether\sor\snot\sthe\scursor\shas\smoved\sand\sthe\ssecond\stries\sto\nrestore\sthe\scursor.\s\sThis\sallows\sthe\ssqlite3VdbeCursorMoveto()\sroutine\sto\sbe\nrefactored\sto\savoid\sstack\spointer\smovements,\sfor\sa\snoticable\sperformance\sgain. -D 2014-08-22T23:33:03.189 +C Performance\soptimization\sin\sthe\sapplyAffinity()\slogic\sinside\sthe\sVDBE. +D 2014-08-23T17:21:37.343 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -284,13 +284,13 @@ F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059 F src/utf.c a0314e637768a030e6e84a957d0c4f6ba910cc05 F src/util.c 068dcd26354a3898ccc64ad5c4bdb95a7a15d33a F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c f7f4066e4d6e3858878d76ce9288ea603e12ddf6 +F src/vdbe.c 76f9fc30dc28751900e85f615e29cdf89c069a77 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 -F src/vdbeInt.h f5513f2b5ac1e2c5128996c7ea23add256a301df +F src/vdbeInt.h 764a055bc9a3e61a30ba37cd4c1826f62bcf8759 F src/vdbeapi.c 49b8d2943d02d276b4efef114578251a3277f47d F src/vdbeaux.c dba006f67c9fd1b1d07ee7fb0fb38aa1905161d1 F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4 -F src/vdbemem.c 4a64659ed8e4c3b18a9238e038145ab1bdcd146f +F src/vdbemem.c f2e162888521a9af35d608ac4c13db4991dfb417 F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 F src/vtab.c 019dbfd0406a7447c990e1f7bd1dfcdb8895697f @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 3eb084390382c108e9b0ff0b29dede58ebb149bc -R 356d2e894dc7576ad768e53fab77ee5b +P ce123b5c592556a8cd38b01fcc91ba76231d3098 +R f59cf04b4ec2e84886c139f6982d2702 U drh -Z 78a9bc2b7c59c5e05ea01f499ba8646b +Z 3f5bd9d4c135b090a54f8be497682e06 diff --git a/manifest.uuid b/manifest.uuid index af6d676ce0..4ee0b9c481 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ce123b5c592556a8cd38b01fcc91ba76231d3098 \ No newline at end of file +25f2246be404f38b4f8dd70397cd1454d46358c4 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 61adb9cccd..13a076cacb 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -146,7 +146,7 @@ int sqlite3_found_count = 0; ** already. Return non-zero if a malloc() fails. */ #define Stringify(P, enc) \ - if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc)) \ + if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc,0)) \ { goto no_mem; } /* @@ -228,8 +228,17 @@ static VdbeCursor *allocateCursor( ** do so without loss of information. In other words, if the string ** looks like a number, convert it into a number. If it does not ** look like a number, leave it alone. +** +** If the bTryForInt flag is true, then extra effort is made to give +** an integer representation. Strings that look like floating point +** values but which have no fractional component (example: '48.00') +** will have a MEM_Int representation when bTryForInt is true. +** +** If bTryForInt is false, then if the input string contains a decimal +** point or exponential notation, the result is only MEM_Real, even +** if there is an exact integer representation of the quantity. */ -static void applyNumericAffinity(Mem *pRec){ +static void applyNumericAffinity(Mem *pRec, int bTryForInt){ double rValue; i64 iValue; u8 enc = pRec->enc; @@ -241,10 +250,9 @@ static void applyNumericAffinity(Mem *pRec){ }else{ pRec->r = rValue; pRec->flags |= MEM_Real; + if( bTryForInt ) sqlite3VdbeIntegerAffinity(pRec); } } -#define ApplyNumericAffinity(X) \ - if(((X)->flags&(MEM_Real|MEM_Int))==0){applyNumericAffinity(X);} /* ** Processing is determine by the affinity parameter: @@ -275,15 +283,17 @@ static void applyAffinity( ** representation. */ if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){ - sqlite3VdbeMemStringify(pRec, enc); + sqlite3VdbeMemStringify(pRec, enc, 1); } - pRec->flags &= ~(MEM_Real|MEM_Int); }else if( affinity!=SQLITE_AFF_NONE ){ assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL || affinity==SQLITE_AFF_NUMERIC ); - ApplyNumericAffinity(pRec); - if( pRec->flags & MEM_Real ){ - sqlite3VdbeIntegerAffinity(pRec); + if( (pRec->flags & MEM_Int)==0 ){ + if( (pRec->flags & MEM_Real)==0 ){ + applyNumericAffinity(pRec,1); + }else{ + sqlite3VdbeIntegerAffinity(pRec); + } } } } @@ -298,7 +308,7 @@ int sqlite3_value_numeric_type(sqlite3_value *pVal){ int eType = sqlite3_value_type(pVal); if( eType==SQLITE_TEXT ){ Mem *pMem = (Mem*)pVal; - applyNumericAffinity(pMem); + applyNumericAffinity(pMem, 0); eType = sqlite3_value_type(pVal); } return eType; @@ -3603,7 +3613,9 @@ case OP_SeekGT: { /* jump, in3 */ ** blob, or NULL. But it needs to be an integer before we can do ** the seek, so covert it. */ pIn3 = &aMem[pOp->p3]; - ApplyNumericAffinity(pIn3); + if( (pIn3->flags & (MEM_Int|MEM_Real))==0 ){ + applyNumericAffinity(pIn3, 0); + } iKey = sqlite3VdbeIntValue(pIn3); pC->rowidIsValid = 0; diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 141573eef4..ba44b61e91 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -418,7 +418,7 @@ void sqlite3VdbeMemSetNull(Mem*); void sqlite3VdbeMemSetZeroBlob(Mem*,int); void sqlite3VdbeMemSetRowSet(Mem*); int sqlite3VdbeMemMakeWriteable(Mem*); -int sqlite3VdbeMemStringify(Mem*, int); +int sqlite3VdbeMemStringify(Mem*, u8, u8); i64 sqlite3VdbeIntValue(Mem*); int sqlite3VdbeMemIntegerify(Mem*); double sqlite3VdbeRealValue(Mem*); diff --git a/src/vdbemem.c b/src/vdbemem.c index 08cf40eaa8..572d486fc4 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -223,7 +223,8 @@ int sqlite3VdbeMemNulTerminate(Mem *pMem){ ** are converted using sqlite3_snprintf(). Converting a BLOB to a string ** is a no-op. ** -** Existing representations MEM_Int and MEM_Real are *not* invalidated. +** Existing representations MEM_Int and MEM_Real are invalidated if +** bForce is true but are retained if bForce is false. ** ** A MEM_Null value will never be passed to this function. This function is ** used for converting values to text for returning to the user (i.e. via @@ -231,8 +232,7 @@ int sqlite3VdbeMemNulTerminate(Mem *pMem){ ** keys are strings. In the former case a NULL pointer is returned the ** user and the later is an internal programming error. */ -int sqlite3VdbeMemStringify(Mem *pMem, int enc){ - int rc = SQLITE_OK; +int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){ int fg = pMem->flags; const int nByte = 32; @@ -248,7 +248,7 @@ int sqlite3VdbeMemStringify(Mem *pMem, int enc){ return SQLITE_NOMEM; } - /* For a Real or Integer, use sqlite3_mprintf() to produce the UTF-8 + /* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8 ** string representation of the value. Then, if the required encoding ** is UTF-16le or UTF-16be do a translation. ** @@ -263,8 +263,9 @@ int sqlite3VdbeMemStringify(Mem *pMem, int enc){ pMem->n = sqlite3Strlen30(pMem->z); pMem->enc = SQLITE_UTF8; pMem->flags |= MEM_Str|MEM_Term; + if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real); sqlite3VdbeChangeEncoding(pMem, enc); - return rc; + return SQLITE_OK; } /* @@ -877,7 +878,7 @@ const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ sqlite3VdbeMemNulTerminate(pVal); /* IMP: R-31275-44060 */ }else{ assert( (pVal->flags&MEM_Blob)==0 ); - sqlite3VdbeMemStringify(pVal, enc); + sqlite3VdbeMemStringify(pVal, enc, 0); assert( 0==(1&SQLITE_PTR_TO_INT(pVal->z)) ); } assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0 From f1a89ede4a392fec648f6a51f8aa0a3f5216cd4e Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Aug 2014 17:41:15 +0000 Subject: [PATCH 14/29] Improved performance in the type handling of arithmetic operators in the VDBE. FossilOrigin-Name: 0c0a603950c97837442d82886f947aab0acbd805 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbe.c | 26 +++++++++++++++++++------- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 8450ec16e4..a5fad99ba9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\soptimization\sin\sthe\sapplyAffinity()\slogic\sinside\sthe\sVDBE. -D 2014-08-23T17:21:37.343 +C Improved\sperformance\sin\sthe\stype\shandling\sof\sarithmetic\soperators\sin\sthe\sVDBE. +D 2014-08-23T17:41:15.456 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -284,7 +284,7 @@ F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059 F src/utf.c a0314e637768a030e6e84a957d0c4f6ba910cc05 F src/util.c 068dcd26354a3898ccc64ad5c4bdb95a7a15d33a F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c 76f9fc30dc28751900e85f615e29cdf89c069a77 +F src/vdbe.c 52ee5d589cbb171a8b096f210b69deb4a33c4369 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 F src/vdbeInt.h 764a055bc9a3e61a30ba37cd4c1826f62bcf8759 F src/vdbeapi.c 49b8d2943d02d276b4efef114578251a3277f47d @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P ce123b5c592556a8cd38b01fcc91ba76231d3098 -R f59cf04b4ec2e84886c139f6982d2702 +P 25f2246be404f38b4f8dd70397cd1454d46358c4 +R 2a69d28bf2271ac25d420aa80c42027b U drh -Z 3f5bd9d4c135b090a54f8be497682e06 +Z c64b6b94b93d1da5e9e0a75cc412b115 diff --git a/manifest.uuid b/manifest.uuid index 4ee0b9c481..53a34bdd8d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -25f2246be404f38b4f8dd70397cd1454d46358c4 \ No newline at end of file +0c0a603950c97837442d82886f947aab0acbd805 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 13a076cacb..2e797eeaf5 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -326,6 +326,24 @@ void sqlite3ValueApplyAffinity( applyAffinity((Mem *)pVal, affinity, enc); } +/* +** pMem currently only holds a string type (or maybe a BLOB that we can +** interpret as a string if we want to). Compute its corresponding +** numeric type, if has one. Set the pMem->r and pMem->u.i fields +** accordingly. +*/ +static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){ + assert( (pMem->flags & (MEM_Int|MEM_Real))==0 ); + assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ); + if( sqlite3AtoF(pMem->z, &pMem->r, pMem->n, pMem->enc)==0 ){ + return 0; + } + if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){ + return MEM_Int; + } + return MEM_Real; +} + /* ** Return the numeric type for pMem, either MEM_Int or MEM_Real or both or ** none. @@ -338,13 +356,7 @@ static u16 numericType(Mem *pMem){ return pMem->flags & (MEM_Int|MEM_Real); } if( pMem->flags & (MEM_Str|MEM_Blob) ){ - if( sqlite3AtoF(pMem->z, &pMem->r, pMem->n, pMem->enc)==0 ){ - return 0; - } - if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){ - return MEM_Int; - } - return MEM_Real; + return computeNumericType(pMem); } return 0; } From 9de4a17185a18927a72a7278fc70b600e46c653e Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Aug 2014 18:17:19 +0000 Subject: [PATCH 15/29] Make the implementation of the sqlite3_aggregate_context() interface faster for second an subsequent invocations. This helps all aggregate functions to perform better. FossilOrigin-Name: 802148f3110462eac939d53ce08eb9a2f6aac739 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbeapi.c | 42 ++++++++++++++++++++++++++---------------- 3 files changed, 33 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index a5fad99ba9..aa0c254b02 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\sperformance\sin\sthe\stype\shandling\sof\sarithmetic\soperators\sin\sthe\sVDBE. -D 2014-08-23T17:41:15.456 +C Make\sthe\simplementation\sof\sthe\ssqlite3_aggregate_context()\sinterface\sfaster\nfor\ssecond\san\ssubsequent\sinvocations.\s\sThis\shelps\sall\saggregate\sfunctions\sto\nperform\sbetter. +D 2014-08-23T18:17:19.059 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -287,7 +287,7 @@ F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 F src/vdbe.c 52ee5d589cbb171a8b096f210b69deb4a33c4369 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 F src/vdbeInt.h 764a055bc9a3e61a30ba37cd4c1826f62bcf8759 -F src/vdbeapi.c 49b8d2943d02d276b4efef114578251a3277f47d +F src/vdbeapi.c cda974083d7597f807640d344ffcf76d872201ce F src/vdbeaux.c dba006f67c9fd1b1d07ee7fb0fb38aa1905161d1 F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4 F src/vdbemem.c f2e162888521a9af35d608ac4c13db4991dfb417 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 25f2246be404f38b4f8dd70397cd1454d46358c4 -R 2a69d28bf2271ac25d420aa80c42027b +P 0c0a603950c97837442d82886f947aab0acbd805 +R d4bdc3de1168bf2d862dde32e02d949b U drh -Z c64b6b94b93d1da5e9e0a75cc412b115 +Z 5d66d6e81701eb9b183824f31680ac42 diff --git a/manifest.uuid b/manifest.uuid index 53a34bdd8d..5b8e019c7e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0c0a603950c97837442d82886f947aab0acbd805 \ No newline at end of file +802148f3110462eac939d53ce08eb9a2f6aac739 \ No newline at end of file diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 675361013a..b2d8059153 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -606,32 +606,42 @@ void sqlite3InvalidFunction( sqlite3_free(zErr); } +/* +** Create a new aggregate context for p and return a pointer to +** its pMem->z element. +*/ +static SQLITE_NOINLINE void *createAggContext(sqlite3_context *p, int nByte){ + Mem *pMem = p->pMem; + assert( (pMem->flags & MEM_Agg)==0 ); + if( nByte<=0 ){ + sqlite3VdbeMemReleaseExternal(pMem); + pMem->flags = MEM_Null; + pMem->z = 0; + }else{ + sqlite3VdbeMemGrow(pMem, nByte, 0); + pMem->flags = MEM_Agg; + pMem->u.pDef = p->pFunc; + if( pMem->z ){ + memset(pMem->z, 0, nByte); + } + } + return (void*)pMem->z; +} + /* ** Allocate or return the aggregate context for a user function. A new ** context is allocated on the first call. Subsequent calls return the ** same context that was returned on prior calls. */ void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ - Mem *pMem; assert( p && p->pFunc && p->pFunc->xStep ); assert( sqlite3_mutex_held(p->s.db->mutex) ); - pMem = p->pMem; testcase( nByte<0 ); - if( (pMem->flags & MEM_Agg)==0 ){ - if( nByte<=0 ){ - sqlite3VdbeMemReleaseExternal(pMem); - pMem->flags = MEM_Null; - pMem->z = 0; - }else{ - sqlite3VdbeMemGrow(pMem, nByte, 0); - pMem->flags = MEM_Agg; - pMem->u.pDef = p->pFunc; - if( pMem->z ){ - memset(pMem->z, 0, nByte); - } - } + if( (p->pMem->flags & MEM_Agg)==0 ){ + return createAggContext(p, nByte); + }else{ + return (void*)p->pMem->z; } - return (void*)pMem->z; } /* From 3ccd5bf89e57d67b1ee89e7cf9ad3bc5989b0339 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Aug 2014 19:04:55 +0000 Subject: [PATCH 16/29] Changes to sqlite3ScratchMalloc() that make the entire memory allocation interface a little faster and about 100 bytes smaller. FossilOrigin-Name: f83daa16f65ef35062412e88c214852a4aeb3da2 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/malloc.c | 14 ++++++-------- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index aa0c254b02..91d323beb8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\sthe\simplementation\sof\sthe\ssqlite3_aggregate_context()\sinterface\sfaster\nfor\ssecond\san\ssubsequent\sinvocations.\s\sThis\shelps\sall\saggregate\sfunctions\sto\nperform\sbetter. -D 2014-08-23T18:17:19.059 +C Changes\sto\ssqlite3ScratchMalloc()\sthat\smake\sthe\sentire\smemory\sallocation\ninterface\sa\slittle\sfaster\sand\sabout\s100\sbytes\ssmaller. +D 2014-08-23T19:04:55.170 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -191,7 +191,7 @@ F src/legacy.c 87c92f4a08e2f70220e3b22a9c3b2482d36a134a F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b F src/loadext.c 31c2122b7dd05a179049bbf163fd4839f181cbab F src/main.c 900dd06e41d22795cbb23ab0240397f1e2901bf7 -F src/malloc.c 0a88a97fc5ae621ca9659d38b080e0b9ddbb80ad +F src/malloc.c 7f26fcedc42b93bb49c4c12a77aa0d891182392e F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0c0a603950c97837442d82886f947aab0acbd805 -R d4bdc3de1168bf2d862dde32e02d949b +P 802148f3110462eac939d53ce08eb9a2f6aac739 +R f2effcc85284cd0fae163c222d4987e9 U drh -Z 5d66d6e81701eb9b183824f31680ac42 +Z d2f180c60ae7591aa14ffa4ab8835b4a diff --git a/manifest.uuid b/manifest.uuid index 5b8e019c7e..233ca94126 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -802148f3110462eac939d53ce08eb9a2f6aac739 \ No newline at end of file +f83daa16f65ef35062412e88c214852a4aeb3da2 \ No newline at end of file diff --git a/src/malloc.c b/src/malloc.c index 9fb4303979..f3b317da5f 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -352,22 +352,20 @@ void *sqlite3ScratchMalloc(int n){ assert( n>0 ); sqlite3_mutex_enter(mem0.mutex); + sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){ p = mem0.pScratchFree; mem0.pScratchFree = mem0.pScratchFree->pNext; mem0.nScratchFree--; sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1); - sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); sqlite3_mutex_leave(mem0.mutex); }else{ - if( sqlite3GlobalConfig.bMemstat ){ - sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); - n = mallocWithAlarm(n, &p); - if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n); + sqlite3_mutex_leave(mem0.mutex); + p = sqlite3Malloc(n); + if( sqlite3GlobalConfig.bMemstat && p ){ + sqlite3_mutex_enter(mem0.mutex); + sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p)); sqlite3_mutex_leave(mem0.mutex); - }else{ - sqlite3_mutex_leave(mem0.mutex); - p = sqlite3GlobalConfig.m.xMalloc(n); } sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH); } From 3bdffddc418b3b202d48eff685780eba2af24465 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Aug 2014 19:08:09 +0000 Subject: [PATCH 17/29] Fix a variable-declaration after code problem in btree.c. Harmless in GCC and CLANG but unacceptable for MSVC. FossilOrigin-Name: 45abd5c0bad2847861f3b26a7040490aa9bb1332 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 91d323beb8..f86063d01b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Changes\sto\ssqlite3ScratchMalloc()\sthat\smake\sthe\sentire\smemory\sallocation\ninterface\sa\slittle\sfaster\sand\sabout\s100\sbytes\ssmaller. -D 2014-08-23T19:04:55.170 +C Fix\sa\svariable-declaration\safter\scode\sproblem\sin\sbtree.c.\s\sHarmless\sin\nGCC\sand\sCLANG\sbut\sunacceptable\sfor\sMSVC. +D 2014-08-23T19:08:09.445 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -168,7 +168,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c a31809c65623cc41849b94d368917f8bb66e6a7e F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c ec9d3f1295dafeb278c3830211cc5584132468f4 -F src/btree.c c4b4e1c9524ba7b7dab840e6f8b29e2379a3bdd2 +F src/btree.c 4737cb5bdb2eb8989cb292f6ff921f7ff45f0c46 F src/btree.h a79aa6a71e7f1055f01052b7f821bd1c2dce95c8 F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3 F src/build.c 058e3aadb1376521ff291735237edf4c10f438fb @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 802148f3110462eac939d53ce08eb9a2f6aac739 -R f2effcc85284cd0fae163c222d4987e9 +P f83daa16f65ef35062412e88c214852a4aeb3da2 +R 964769625a1b08555f23e3f40e4e1b01 U drh -Z d2f180c60ae7591aa14ffa4ab8835b4a +Z 8bbf37cac5a7f4ae4955d0f942660ce9 diff --git a/manifest.uuid b/manifest.uuid index 233ca94126..948c00a194 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f83daa16f65ef35062412e88c214852a4aeb3da2 \ No newline at end of file +45abd5c0bad2847861f3b26a7040490aa9bb1332 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 23de31db07..384bab218c 100644 --- a/src/btree.c +++ b/src/btree.c @@ -645,9 +645,9 @@ static int SQLITE_NOINLINE saveCursorsOnList(BtCursor*,Pgno,BtCursor*); ** event that cursors are in need to being saved. */ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ + BtCursor *p; assert( sqlite3_mutex_held(pBt->mutex) ); assert( pExcept==0 || pExcept->pBt==pBt ); - BtCursor *p; for(p=pBt->pCursor; p; p=p->pNext){ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ) break; } From b4586f1254df07a7eccba2101ae4a95dfe2ca34b Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Aug 2014 19:42:06 +0000 Subject: [PATCH 18/29] Another memory allocator performance optimization. FossilOrigin-Name: 6da6f46d0c43e3b68c21f514ddf8ee663c20f249 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/malloc.c | 10 +++++++++- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index f86063d01b..0f001ae399 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\svariable-declaration\safter\scode\sproblem\sin\sbtree.c.\s\sHarmless\sin\nGCC\sand\sCLANG\sbut\sunacceptable\sfor\sMSVC. -D 2014-08-23T19:08:09.445 +C Another\smemory\sallocator\sperformance\soptimization. +D 2014-08-23T19:42:06.737 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -191,7 +191,7 @@ F src/legacy.c 87c92f4a08e2f70220e3b22a9c3b2482d36a134a F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b F src/loadext.c 31c2122b7dd05a179049bbf163fd4839f181cbab F src/main.c 900dd06e41d22795cbb23ab0240397f1e2901bf7 -F src/malloc.c 7f26fcedc42b93bb49c4c12a77aa0d891182392e +F src/malloc.c 06f8507831d04d2830237bf0c9f2fd04623f9868 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P f83daa16f65ef35062412e88c214852a4aeb3da2 -R 964769625a1b08555f23e3f40e4e1b01 +P 45abd5c0bad2847861f3b26a7040490aa9bb1332 +R 863f9a5c456ee79d86d610ec7db424be U drh -Z 8bbf37cac5a7f4ae4955d0f942660ce9 +Z 2076d0986bc3817907a655695f4a8b4e diff --git a/manifest.uuid b/manifest.uuid index 948c00a194..7e569bfcb7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -45abd5c0bad2847861f3b26a7040490aa9bb1332 \ No newline at end of file +6da6f46d0c43e3b68c21f514ddf8ee663c20f249 \ No newline at end of file diff --git a/src/malloc.c b/src/malloc.c index f3b317da5f..1b219604bc 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -477,6 +477,14 @@ void sqlite3_free(void *p){ } } +/* +** Add the size of memory allocation "p" to the count in +** *db->pnBytesFreed. +*/ +static SQLITE_NOINLINE void measureAllocationSize(sqlite3 *db, void *p){ + *db->pnBytesFreed += sqlite3DbMallocSize(db,p); +} + /* ** Free memory that might be associated with a particular database ** connection. @@ -486,7 +494,7 @@ void sqlite3DbFree(sqlite3 *db, void *p){ if( p==0 ) return; if( db ){ if( db->pnBytesFreed ){ - *db->pnBytesFreed += sqlite3DbMallocSize(db, p); + measureAllocationSize(db, p); return; } if( isLookaside(db, p) ){ From b50c65d561532c689a894112459be6e48f9ae366 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Aug 2014 20:25:53 +0000 Subject: [PATCH 19/29] Faster implementation of the sqlite3ApiExit() routine. FossilOrigin-Name: bd41d394d48516eb7d8ddc46abdcb427aa80173e --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/malloc.c | 17 ++++++++++++----- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 0f001ae399..1044726bb0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Another\smemory\sallocator\sperformance\soptimization. -D 2014-08-23T19:42:06.737 +C Faster\simplementation\sof\sthe\ssqlite3ApiExit()\sroutine. +D 2014-08-23T20:25:53.209 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -191,7 +191,7 @@ F src/legacy.c 87c92f4a08e2f70220e3b22a9c3b2482d36a134a F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b F src/loadext.c 31c2122b7dd05a179049bbf163fd4839f181cbab F src/main.c 900dd06e41d22795cbb23ab0240397f1e2901bf7 -F src/malloc.c 06f8507831d04d2830237bf0c9f2fd04623f9868 +F src/malloc.c 954de5f998c23237e04474a3f2159bf483bba65a F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 45abd5c0bad2847861f3b26a7040490aa9bb1332 -R 863f9a5c456ee79d86d610ec7db424be +P 6da6f46d0c43e3b68c21f514ddf8ee663c20f249 +R cfcb5b6ff857caed22b759c12472ea06 U drh -Z 2076d0986bc3817907a655695f4a8b4e +Z c1d7ee14996f329ac13456e7bf7bb3df diff --git a/manifest.uuid b/manifest.uuid index 7e569bfcb7..215297c16b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6da6f46d0c43e3b68c21f514ddf8ee663c20f249 \ No newline at end of file +bd41d394d48516eb7d8ddc46abdcb427aa80173e \ No newline at end of file diff --git a/src/malloc.c b/src/malloc.c index 1b219604bc..b4b70350f4 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -761,6 +761,14 @@ void sqlite3SetString(char **pz, sqlite3 *db, const char *zFormat, ...){ *pz = z; } +/* +** Take actions at the end of an API call to indicate an OOM error +*/ +static SQLITE_NOINLINE int apiOomError(sqlite3 *db){ + db->mallocFailed = 0; + sqlite3Error(db, SQLITE_NOMEM); + return SQLITE_NOMEM; +} /* ** This function must be called before exiting any API function (i.e. @@ -781,10 +789,9 @@ int sqlite3ApiExit(sqlite3* db, int rc){ ** is unsafe, as is the call to sqlite3Error(). */ assert( !db || sqlite3_mutex_held(db->mutex) ); - if( db && (db->mallocFailed || rc==SQLITE_IOERR_NOMEM) ){ - sqlite3Error(db, SQLITE_NOMEM); - db->mallocFailed = 0; - rc = SQLITE_NOMEM; + if( db==0 ) return rc & 0xff; + if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){ + return apiOomError(db); } - return rc & (db ? db->errMask : 0xff); + return rc & db->errMask; } From efbf04458341672c9200d51b1fd7d485ddd09ce3 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 23 Aug 2014 23:15:31 +0000 Subject: [PATCH 20/29] Faster implementation of pcache1Fetch() FossilOrigin-Name: 0371cc3bb07448bcd64fd671f3e71bb7f30deb4d --- manifest | 12 +-- manifest.uuid | 2 +- src/pcache1.c | 210 ++++++++++++++++++++++++++------------------------ 3 files changed, 116 insertions(+), 108 deletions(-) diff --git a/manifest b/manifest index 1044726bb0..6e1bca5a72 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Faster\simplementation\sof\sthe\ssqlite3ApiExit()\sroutine. -D 2014-08-23T20:25:53.209 +C Faster\simplementation\sof\spcache1Fetch() +D 2014-08-23T23:15:31.233 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -216,7 +216,7 @@ F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428 F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0 F src/pcache.c da602c5447051705cab41604bf3276815eb569d0 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 -F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c +F src/pcache1.c c5af6403a55178c9d1c09e4f77b0f9c88822762c F src/pragma.c d10ef67c4de79f78188b965b4b7988aff1d66f2e F src/prepare.c 3842c1dfc0b053458e3adcf9f6efc48e03e3fe3d F src/printf.c 00986c86ddfffefc2fd3c73667ff51b3b9709c74 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 6da6f46d0c43e3b68c21f514ddf8ee663c20f249 -R cfcb5b6ff857caed22b759c12472ea06 +P bd41d394d48516eb7d8ddc46abdcb427aa80173e +R d2491d65f44f8709d1d156c840c25703 U drh -Z c1d7ee14996f329ac13456e7bf7bb3df +Z 15bb2365f5f8da3e5de34ee820ad0674 diff --git a/manifest.uuid b/manifest.uuid index 215297c16b..bd2aebab20 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bd41d394d48516eb7d8ddc46abdcb427aa80173e \ No newline at end of file +0371cc3bb07448bcd64fd671f3e71bb7f30deb4d \ No newline at end of file diff --git a/src/pcache1.c b/src/pcache1.c index 1644b0693c..82015befce 100644 --- a/src/pcache1.c +++ b/src/pcache1.c @@ -383,7 +383,7 @@ static int pcache1UnderMemoryPressure(PCache1 *pCache){ ** ** The PCache mutex must be held when this function is called. */ -static int pcache1ResizeHash(PCache1 *p){ +static void pcache1ResizeHash(PCache1 *p){ PgHdr1 **apNew; unsigned int nNew; unsigned int i; @@ -415,8 +415,6 @@ static int pcache1ResizeHash(PCache1 *p){ p->apHash = apNew; p->nHash = nNew; } - - return (p->apHash ? SQLITE_OK : SQLITE_NOMEM); } /* @@ -551,6 +549,9 @@ static void pcache1Shutdown(void *NotUsed){ memset(&pcache1, 0, sizeof(pcache1)); } +/* forward declaration */ +static void pcache1Destroy(sqlite3_pcache *p); + /* ** Implementation of the sqlite3_pcache.xCreate method. ** @@ -595,12 +596,17 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){ pCache->szPage = szPage; pCache->szExtra = szExtra; pCache->bPurgeable = (bPurgeable ? 1 : 0); + pcache1EnterMutex(pGroup); + pcache1ResizeHash(pCache); if( bPurgeable ){ pCache->nMin = 10; - pcache1EnterMutex(pGroup); pGroup->nMinPage += pCache->nMin; pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; - pcache1LeaveMutex(pGroup); + } + pcache1LeaveMutex(pGroup); + if( pCache->nHash==0 ){ + pcache1Destroy((sqlite3_pcache*)pCache); + pCache = 0; } } return (sqlite3_pcache *)pCache; @@ -656,6 +662,95 @@ static int pcache1Pagecount(sqlite3_pcache *p){ return n; } + +/* +** Implement steps 3, 4, and 5 of the pcache1Fetch() algorithm described +** in the header of the pcache1Fetch() procedure. +** +** This steps are broken out into a separate procedure because they are +** usually not needed, and by avoiding the stack initialization required +** for these steps, the main pcache1Fetch() procedure can run faster. +*/ +static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2( + PCache1 *pCache, + unsigned int iKey, + int createFlag +){ + unsigned int nPinned; + PGroup *pGroup = pCache->pGroup; + PgHdr1 *pPage = 0; + + /* Step 3: Abort if createFlag is 1 but the cache is nearly full */ + assert( pCache->nPage >= pCache->nRecyclable ); + nPinned = pCache->nPage - pCache->nRecyclable; + assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage ); + assert( pCache->n90pct == pCache->nMax*9/10 ); + if( createFlag==1 && ( + nPinned>=pGroup->mxPinned + || nPinned>=pCache->n90pct + || pcache1UnderMemoryPressure(pCache) + )){ + return 0; + } + + if( pCache->nPage>=pCache->nHash ) pcache1ResizeHash(pCache); + assert( pCache->nHash>0 && pCache->apHash ); + + /* Step 4. Try to recycle a page. */ + if( pCache->bPurgeable && pGroup->pLruTail && ( + (pCache->nPage+1>=pCache->nMax) + || pGroup->nCurrentPage>=pGroup->nMaxPage + || pcache1UnderMemoryPressure(pCache) + )){ + PCache1 *pOther; + pPage = pGroup->pLruTail; + assert( pPage->isPinned==0 ); + pcache1RemoveFromHash(pPage); + pcache1PinPage(pPage); + pOther = pPage->pCache; + + /* We want to verify that szPage and szExtra are the same for pOther + ** and pCache. Assert that we can verify this by comparing sums. */ + assert( (pCache->szPage & (pCache->szPage-1))==0 && pCache->szPage>=512 ); + assert( pCache->szExtra<512 ); + assert( (pOther->szPage & (pOther->szPage-1))==0 && pOther->szPage>=512 ); + assert( pOther->szExtra<512 ); + + if( pOther->szPage+pOther->szExtra != pCache->szPage+pCache->szExtra ){ + pcache1FreePage(pPage); + pPage = 0; + }else{ + pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable); + } + } + + /* Step 5. If a usable page buffer has still not been found, + ** attempt to allocate a new one. + */ + if( !pPage ){ + if( createFlag==1 ) sqlite3BeginBenignMalloc(); + pPage = pcache1AllocPage(pCache); + if( createFlag==1 ) sqlite3EndBenignMalloc(); + } + + if( pPage ){ + unsigned int h = iKey % pCache->nHash; + pCache->nPage++; + pPage->iKey = iKey; + pPage->pNext = pCache->apHash[h]; + pPage->pCache = pCache; + pPage->pLruPrev = 0; + pPage->pLruNext = 0; + pPage->isPinned = 1; + *(void **)pPage->page.pExtra = 0; + pCache->apHash[h] = pPage; + if( iKey>pCache->iMaxKey ){ + pCache->iMaxKey = iKey; + } + } + return pPage; +} + /* ** Implementation of the sqlite3_pcache.xFetch method. ** @@ -715,9 +810,7 @@ static sqlite3_pcache_page *pcache1Fetch( unsigned int iKey, int createFlag ){ - unsigned int nPinned; PCache1 *pCache = (PCache1 *)p; - PGroup *pGroup; PgHdr1 *pPage = 0; assert( offsetof(PgHdr1,page)==0 ); @@ -725,107 +818,22 @@ static sqlite3_pcache_page *pcache1Fetch( assert( pCache->bPurgeable || pCache->nMin==0 ); assert( pCache->bPurgeable==0 || pCache->nMin==10 ); assert( pCache->nMin==0 || pCache->bPurgeable ); - pcache1EnterMutex(pGroup = pCache->pGroup); + assert( pCache->nHash>0 ); + pcache1EnterMutex(pCache->pGroup); /* Step 1: Search the hash table for an existing entry. */ - if( pCache->nHash>0 ){ - unsigned int h = iKey % pCache->nHash; - for(pPage=pCache->apHash[h]; pPage&&pPage->iKey!=iKey; pPage=pPage->pNext); - } + pPage = pCache->apHash[iKey % pCache->nHash]; + while( pPage && pPage->iKey!=iKey ){ pPage = pPage->pNext; } /* Step 2: Abort if no existing page is found and createFlag is 0 */ if( pPage ){ if( !pPage->isPinned ) pcache1PinPage(pPage); - goto fetch_out; + }else if( createFlag ){ + /* Steps 3, 4, and 5 implemented by this subroutine */ + pPage = pcache1FetchStage2(pCache, iKey, createFlag); } - if( createFlag==0 ){ - goto fetch_out; - } - - /* The pGroup local variable will normally be initialized by the - ** pcache1EnterMutex() macro above. But if SQLITE_MUTEX_OMIT is defined, - ** then pcache1EnterMutex() is a no-op, so we have to initialize the - ** local variable here. Delaying the initialization of pGroup is an - ** optimization: The common case is to exit the module before reaching - ** this point. - */ -#ifdef SQLITE_MUTEX_OMIT - pGroup = pCache->pGroup; -#endif - - /* Step 3: Abort if createFlag is 1 but the cache is nearly full */ - assert( pCache->nPage >= pCache->nRecyclable ); - nPinned = pCache->nPage - pCache->nRecyclable; - assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage ); - assert( pCache->n90pct == pCache->nMax*9/10 ); - if( createFlag==1 && ( - nPinned>=pGroup->mxPinned - || nPinned>=pCache->n90pct - || pcache1UnderMemoryPressure(pCache) - )){ - goto fetch_out; - } - - if( pCache->nPage>=pCache->nHash && pcache1ResizeHash(pCache) ){ - goto fetch_out; - } - assert( pCache->nHash>0 && pCache->apHash ); - - /* Step 4. Try to recycle a page. */ - if( pCache->bPurgeable && pGroup->pLruTail && ( - (pCache->nPage+1>=pCache->nMax) - || pGroup->nCurrentPage>=pGroup->nMaxPage - || pcache1UnderMemoryPressure(pCache) - )){ - PCache1 *pOther; - pPage = pGroup->pLruTail; - assert( pPage->isPinned==0 ); - pcache1RemoveFromHash(pPage); - pcache1PinPage(pPage); - pOther = pPage->pCache; - - /* We want to verify that szPage and szExtra are the same for pOther - ** and pCache. Assert that we can verify this by comparing sums. */ - assert( (pCache->szPage & (pCache->szPage-1))==0 && pCache->szPage>=512 ); - assert( pCache->szExtra<512 ); - assert( (pOther->szPage & (pOther->szPage-1))==0 && pOther->szPage>=512 ); - assert( pOther->szExtra<512 ); - - if( pOther->szPage+pOther->szExtra != pCache->szPage+pCache->szExtra ){ - pcache1FreePage(pPage); - pPage = 0; - }else{ - pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable); - } - } - - /* Step 5. If a usable page buffer has still not been found, - ** attempt to allocate a new one. - */ - if( !pPage ){ - if( createFlag==1 ) sqlite3BeginBenignMalloc(); - pPage = pcache1AllocPage(pCache); - if( createFlag==1 ) sqlite3EndBenignMalloc(); - } - - if( pPage ){ - unsigned int h = iKey % pCache->nHash; - pCache->nPage++; - pPage->iKey = iKey; - pPage->pNext = pCache->apHash[h]; - pPage->pCache = pCache; - pPage->pLruPrev = 0; - pPage->pLruNext = 0; - pPage->isPinned = 1; - *(void **)pPage->page.pExtra = 0; - pCache->apHash[h] = pPage; - } - -fetch_out: - if( pPage && iKey>pCache->iMaxKey ){ - pCache->iMaxKey = iKey; - } - pcache1LeaveMutex(pGroup); + assert( pPage==0 || pCache->iMaxKey>=iKey ); + pcache1LeaveMutex(pCache->pGroup); return (sqlite3_pcache_page*)pPage; } From f063e08fd93c4f00cb44c03bad01e811d76ddb6e Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 24 Aug 2014 01:32:43 +0000 Subject: [PATCH 21/29] Patch the sqlite3PagerWrite() method in the Pager to run a bit faster. FossilOrigin-Name: c63311e2f3344363a5ed99838fb5850004eaee30 --- manifest | 12 ++-- manifest.uuid | 2 +- src/pager.c | 185 ++++++++++++++++++++++++++------------------------ 3 files changed, 105 insertions(+), 94 deletions(-) diff --git a/manifest b/manifest index 6e1bca5a72..a21c0da13e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Faster\simplementation\sof\spcache1Fetch() -D 2014-08-23T23:15:31.233 +C Patch\sthe\ssqlite3PagerWrite()\smethod\sin\sthe\sPager\sto\srun\sa\sbit\sfaster. +D 2014-08-24T01:32:43.379 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -211,7 +211,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c bd7df3094a60915c148517504c76df4fca24e542 F src/os_win.c d067fce558a5032e6e6afe62899e5397bf63cf3e F src/os_win.h 09e751b20bbc107ffbd46e13555dc73576d88e21 -F src/pager.c f6bb1fa6cdf2062f2d8aec3e64db302bca519ab8 +F src/pager.c c831b0df879114915c08dc5a0188f9f22c48403b F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428 F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0 F src/pcache.c da602c5447051705cab41604bf3276815eb569d0 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P bd41d394d48516eb7d8ddc46abdcb427aa80173e -R d2491d65f44f8709d1d156c840c25703 +P 0371cc3bb07448bcd64fd671f3e71bb7f30deb4d +R 2fe545d9c9446b3adf94c91625adc119 U drh -Z 15bb2365f5f8da3e5de34ee820ad0674 +Z 79e99766e8b4bdebd57118e507ef67dc diff --git a/manifest.uuid b/manifest.uuid index bd2aebab20..308d8ad8ef 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0371cc3bb07448bcd64fd671f3e71bb7f30deb4d \ No newline at end of file +c63311e2f3344363a5ed99838fb5850004eaee30 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index a77dcecc4c..4a178a2985 100644 --- a/src/pager.c +++ b/src/pager.c @@ -5772,6 +5772,97 @@ static int pager_write(PgHdr *pPg){ return rc; } +/* +** This is a variant of sqlite3PagerWrite() that runs when the sector size +** is larger than the page size. SQLite makes the (reasonable) assumption that +** all bytes of a sector are written together by hardware. Hence, all bytes of +** a sector need to be journalled in case of a power loss in the middle of +** a write. +** +** Usually, the sector size is less than or equal to the page size, in which +** case pages can be individually written. This routine only runs in the exceptional +** case where the page size is smaller than the sector size. +*/ +static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){ + int rc = SQLITE_OK; /* Return code */ + Pgno nPageCount; /* Total number of pages in database file */ + Pgno pg1; /* First page of the sector pPg is located on. */ + int nPage = 0; /* Number of pages starting at pg1 to journal */ + int ii; /* Loop counter */ + int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */ + Pager *pPager = pPg->pPager; /* The pager that owns pPg */ + Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); + + /* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow + ** a journal header to be written between the pages journaled by + ** this function. + */ + assert( !MEMDB ); + assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 ); + pPager->doNotSpill |= SPILLFLAG_NOSYNC; + + /* This trick assumes that both the page-size and sector-size are + ** an integer power of 2. It sets variable pg1 to the identifier + ** of the first page of the sector pPg is located on. + */ + pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1; + + nPageCount = pPager->dbSize; + if( pPg->pgno>nPageCount ){ + nPage = (pPg->pgno - pg1)+1; + }else if( (pg1+nPagePerSector-1)>nPageCount ){ + nPage = nPageCount+1-pg1; + }else{ + nPage = nPagePerSector; + } + assert(nPage>0); + assert(pg1<=pPg->pgno); + assert((pg1+nPage)>pPg->pgno); + + for(ii=0; iipgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){ + if( pg!=PAGER_MJ_PGNO(pPager) ){ + rc = sqlite3PagerGet(pPager, pg, &pPage); + if( rc==SQLITE_OK ){ + rc = pager_write(pPage); + if( pPage->flags&PGHDR_NEED_SYNC ){ + needSync = 1; + } + sqlite3PagerUnrefNotNull(pPage); + } + } + }else if( (pPage = pager_lookup(pPager, pg))!=0 ){ + if( pPage->flags&PGHDR_NEED_SYNC ){ + needSync = 1; + } + sqlite3PagerUnrefNotNull(pPage); + } + } + + /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages + ** starting at pg1, then it needs to be set for all of them. Because + ** writing to any of these nPage pages may damage the others, the + ** journal file must contain sync()ed copies of all of them + ** before any of them can be written out to the database file. + */ + if( rc==SQLITE_OK && needSync ){ + assert( !MEMDB ); + for(ii=0; iiflags |= PGHDR_NEED_SYNC; + sqlite3PagerUnrefNotNull(pPage); + } + } + } + + assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 ); + pPager->doNotSpill &= ~SPILLFLAG_NOSYNC; + return rc; +} + /* ** Mark a data page as writeable. This routine must be called before ** making changes to a page. The caller must check the return value @@ -5786,96 +5877,16 @@ static int pager_write(PgHdr *pPg){ ** If an error occurs, SQLITE_NOMEM or an IO error code is returned ** as appropriate. Otherwise, SQLITE_OK. */ -int sqlite3PagerWrite(DbPage *pDbPage){ - int rc = SQLITE_OK; - - PgHdr *pPg = pDbPage; - Pager *pPager = pPg->pPager; - +int sqlite3PagerWrite(PgHdr *pPg){ assert( (pPg->flags & PGHDR_MMAP)==0 ); - assert( pPager->eState>=PAGER_WRITER_LOCKED ); - assert( pPager->eState!=PAGER_ERROR ); - assert( assert_pager_state(pPager) ); - - if( pPager->sectorSize > (u32)pPager->pageSize ){ - Pgno nPageCount; /* Total number of pages in database file */ - Pgno pg1; /* First page of the sector pPg is located on. */ - int nPage = 0; /* Number of pages starting at pg1 to journal */ - int ii; /* Loop counter */ - int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */ - Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); - - /* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow - ** a journal header to be written between the pages journaled by - ** this function. - */ - assert( !MEMDB ); - assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 ); - pPager->doNotSpill |= SPILLFLAG_NOSYNC; - - /* This trick assumes that both the page-size and sector-size are - ** an integer power of 2. It sets variable pg1 to the identifier - ** of the first page of the sector pPg is located on. - */ - pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1; - - nPageCount = pPager->dbSize; - if( pPg->pgno>nPageCount ){ - nPage = (pPg->pgno - pg1)+1; - }else if( (pg1+nPagePerSector-1)>nPageCount ){ - nPage = nPageCount+1-pg1; - }else{ - nPage = nPagePerSector; - } - assert(nPage>0); - assert(pg1<=pPg->pgno); - assert((pg1+nPage)>pPg->pgno); - - for(ii=0; iipgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){ - if( pg!=PAGER_MJ_PGNO(pPager) ){ - rc = sqlite3PagerGet(pPager, pg, &pPage); - if( rc==SQLITE_OK ){ - rc = pager_write(pPage); - if( pPage->flags&PGHDR_NEED_SYNC ){ - needSync = 1; - } - sqlite3PagerUnrefNotNull(pPage); - } - } - }else if( (pPage = pager_lookup(pPager, pg))!=0 ){ - if( pPage->flags&PGHDR_NEED_SYNC ){ - needSync = 1; - } - sqlite3PagerUnrefNotNull(pPage); - } - } - - /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages - ** starting at pg1, then it needs to be set for all of them. Because - ** writing to any of these nPage pages may damage the others, the - ** journal file must contain sync()ed copies of all of them - ** before any of them can be written out to the database file. - */ - if( rc==SQLITE_OK && needSync ){ - assert( !MEMDB ); - for(ii=0; iiflags |= PGHDR_NEED_SYNC; - sqlite3PagerUnrefNotNull(pPage); - } - } - } - - assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 ); - pPager->doNotSpill &= ~SPILLFLAG_NOSYNC; + assert( pPg->pPager->eState>=PAGER_WRITER_LOCKED ); + assert( pPg->pPager->eState!=PAGER_ERROR ); + assert( assert_pager_state(pPg->pPager) ); + if( pPg->pPager->sectorSize > (u32)pPg->pPager->pageSize ){ + return pagerWriteLargeSector(pPg); }else{ - rc = pager_write(pDbPage); + return pager_write(pPg); } - return rc; } /* From 4274dae9e9971ce49bda44989be0e3aff4e1b865 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 24 Aug 2014 02:53:23 +0000 Subject: [PATCH 22/29] The sqlite3VdbeChangeEncoding() routine goes about 3x faster if the sqlite3VdbeMemTranslate() subroutine is not inlined. FossilOrigin-Name: 0c7e1b875a14ff9d71af7bb125a0272a23d57353 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/utf.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index a21c0da13e..bb740b999a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Patch\sthe\ssqlite3PagerWrite()\smethod\sin\sthe\sPager\sto\srun\sa\sbit\sfaster. -D 2014-08-24T01:32:43.379 +C The\ssqlite3VdbeChangeEncoding()\sroutine\sgoes\sabout\s3x\sfaster\sif\sthe\nsqlite3VdbeMemTranslate()\ssubroutine\sis\snot\sinlined. +D 2014-08-24T02:53:23.646 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -281,7 +281,7 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c ae45399d6252b4d736af43bee1576ce7bff86aec F src/trigger.c 4bddd12803275aa98f1c7ce0118fceb02b2167f6 F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059 -F src/utf.c a0314e637768a030e6e84a957d0c4f6ba910cc05 +F src/utf.c 77abb5e6d27f3d236e50f7c8fff1d00e15262359 F src/util.c 068dcd26354a3898ccc64ad5c4bdb95a7a15d33a F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 F src/vdbe.c 52ee5d589cbb171a8b096f210b69deb4a33c4369 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0371cc3bb07448bcd64fd671f3e71bb7f30deb4d -R 2fe545d9c9446b3adf94c91625adc119 +P c63311e2f3344363a5ed99838fb5850004eaee30 +R 195c0a9c31ce9f43b0d460b5ca896167 U drh -Z 79e99766e8b4bdebd57118e507ef67dc +Z 7685d4da1bf506f63008f6a3d5e2d0bd diff --git a/manifest.uuid b/manifest.uuid index 308d8ad8ef..de00fe8cee 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c63311e2f3344363a5ed99838fb5850004eaee30 \ No newline at end of file +0c7e1b875a14ff9d71af7bb125a0272a23d57353 \ No newline at end of file diff --git a/src/utf.c b/src/utf.c index 97898746a2..557f3a95e4 100644 --- a/src/utf.c +++ b/src/utf.c @@ -199,7 +199,7 @@ u32 sqlite3Utf8Read( ** desiredEnc. It is an error if the string is already of the desired ** encoding, or if *pMem does not contain a string value. */ -int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){ +SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){ int len; /* Maximum length of output string in bytes */ unsigned char *zOut; /* Output buffer */ unsigned char *zIn; /* Input iterator */ From 12b7c7d8c397ff07626d720d9c2b68701b53fe0b Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 25 Aug 2014 11:20:27 +0000 Subject: [PATCH 23/29] Change the name of the VdbeMemRelease() macro to VdbeMemReleaseExtern() to more accurately reflect what it does. Performance enhancement to the sqlite3VdbeMemRelease() function. FossilOrigin-Name: 3ca5846da7da5e08192a4c96288197be3b7ab6f7 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/vdbe.c | 8 ++++---- src/vdbeInt.h | 2 +- src/vdbemem.c | 39 ++++++++++++++++++++++++++++++--------- 5 files changed, 44 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index bb740b999a..bfef72eb6a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\ssqlite3VdbeChangeEncoding()\sroutine\sgoes\sabout\s3x\sfaster\sif\sthe\nsqlite3VdbeMemTranslate()\ssubroutine\sis\snot\sinlined. -D 2014-08-24T02:53:23.646 +C Change\sthe\sname\sof\sthe\sVdbeMemRelease()\smacro\sto\sVdbeMemReleaseExtern()\sto\nmore\saccurately\sreflect\swhat\sit\sdoes.\s\sPerformance\senhancement\sto\sthe\nsqlite3VdbeMemRelease()\sfunction. +D 2014-08-25T11:20:27.189 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -284,13 +284,13 @@ F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059 F src/utf.c 77abb5e6d27f3d236e50f7c8fff1d00e15262359 F src/util.c 068dcd26354a3898ccc64ad5c4bdb95a7a15d33a F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c 52ee5d589cbb171a8b096f210b69deb4a33c4369 +F src/vdbe.c 0fe4b47668b36a50bd9f7fd7b15cbeeb69d54b37 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 -F src/vdbeInt.h 764a055bc9a3e61a30ba37cd4c1826f62bcf8759 +F src/vdbeInt.h 20056cd59ff93ef9eb91009ece726d65dd7ed322 F src/vdbeapi.c cda974083d7597f807640d344ffcf76d872201ce F src/vdbeaux.c dba006f67c9fd1b1d07ee7fb0fb38aa1905161d1 F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4 -F src/vdbemem.c f2e162888521a9af35d608ac4c13db4991dfb417 +F src/vdbemem.c 4c9d686da474957d2e78834f13cc5f141fe6b87f F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 F src/vtab.c 019dbfd0406a7447c990e1f7bd1dfcdb8895697f @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c63311e2f3344363a5ed99838fb5850004eaee30 -R 195c0a9c31ce9f43b0d460b5ca896167 +P 0c7e1b875a14ff9d71af7bb125a0272a23d57353 +R 3449942ddb4a22bfe8e7f1684bd27e8b U drh -Z 7685d4da1bf506f63008f6a3d5e2d0bd +Z c7041d8c52f909d88b499b4a5f3227aa diff --git a/manifest.uuid b/manifest.uuid index de00fe8cee..725161693a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0c7e1b875a14ff9d71af7bb125a0272a23d57353 \ No newline at end of file +3ca5846da7da5e08192a4c96288197be3b7ab6f7 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 2e797eeaf5..72a1552ce1 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -640,7 +640,7 @@ int sqlite3VdbeExec( assert( pOp->p2<=(p->nMem-p->nCursor) ); pOut = &aMem[pOp->p2]; memAboutToChange(p, pOut); - VdbeMemRelease(pOut); + VdbeMemReleaseExtern(pOut); pOut->flags = MEM_Int; } @@ -1079,7 +1079,7 @@ case OP_Null: { /* out2-prerelease */ while( cnt>0 ){ pOut++; memAboutToChange(p, pOut); - VdbeMemRelease(pOut); + VdbeMemReleaseExtern(pOut); pOut->flags = nullFlag; cnt--; } @@ -1165,7 +1165,7 @@ case OP_Move: { assert( pIn1<=&aMem[(p->nMem-p->nCursor)] ); assert( memIsValid(pIn1) ); memAboutToChange(p, pOut); - VdbeMemRelease(pOut); + VdbeMemReleaseExtern(pOut); zMalloc = pOut->zMalloc; memcpy(pOut, pIn1, sizeof(Mem)); #ifdef SQLITE_DEBUG @@ -2538,7 +2538,7 @@ case OP_Column: { if( pC->szRow>=aOffset[p2+1] ){ /* This is the common case where the desired content fits on the original ** page - where the content is not on an overflow page */ - VdbeMemRelease(pDest); + VdbeMemReleaseExtern(pDest); sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], aType[p2], pDest); }else{ /* This branch happens only when content is on overflow pages */ diff --git a/src/vdbeInt.h b/src/vdbeInt.h index ba44b61e91..384c5eb37b 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -430,7 +430,7 @@ void sqlite3VdbeMemRelease(Mem *p); void sqlite3VdbeMemReleaseExternal(Mem *p); #define VdbeMemDynamic(X) \ (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0) -#define VdbeMemRelease(X) \ +#define VdbeMemReleaseExtern(X) \ if( VdbeMemDynamic(X) ) sqlite3VdbeMemReleaseExternal(X); int sqlite3VdbeMemFinalize(Mem*, FuncDef*); const char *sqlite3OpcodeName(int); diff --git a/src/vdbemem.c b/src/vdbemem.c index 572d486fc4..55e212d8ca 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -121,7 +121,7 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n); } if( pMem->zMalloc==0 ){ - VdbeMemRelease(pMem); + VdbeMemReleaseExtern(pMem); pMem->z = 0; pMem->flags = MEM_Null; return SQLITE_NOMEM; @@ -300,6 +300,9 @@ int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){ ** If the memory cell contains a string value that must be freed by ** invoking an external callback, free it now. Calling this function ** does not free any Mem.zMalloc buffer. +** +** The VdbeMemReleaseExtern() macro invokes this routine if only if there +** is work for this routine to do. */ void sqlite3VdbeMemReleaseExternal(Mem *p){ assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) ); @@ -319,6 +322,25 @@ void sqlite3VdbeMemReleaseExternal(Mem *p){ } } +/* +** Release memory held by the Mem p, both external memory cleared +** by p->xDel and memory in p->zMalloc. +** +** This is a helper routine invoked by sqlite3VdbeMemRelease() in +** the uncommon case when there really is memory in p that is +** need of freeing. +*/ +static SQLITE_NOINLINE void vdbeMemRelease(Mem *p){ + if( VdbeMemDynamic(p) ){ + sqlite3VdbeMemReleaseExternal(p); + } + if( p->zMalloc ){ + sqlite3DbFree(p->db, p->zMalloc); + p->zMalloc = 0; + } + p->z = 0; +} + /* ** Release any memory held by the Mem. This may leave the Mem in an ** inconsistent state, for example with (Mem.z==0) and @@ -326,13 +348,12 @@ void sqlite3VdbeMemReleaseExternal(Mem *p){ */ void sqlite3VdbeMemRelease(Mem *p){ assert( sqlite3VdbeCheckMemInvariants(p) ); - VdbeMemRelease(p); - if( p->zMalloc ){ - sqlite3DbFree(p->db, p->zMalloc); - p->zMalloc = 0; + if( VdbeMemDynamic(p) || p->zMalloc ){ + vdbeMemRelease(p); + }else{ + p->z = 0; } - p->z = 0; - assert( p->xDel==0 ); /* Zeroed by VdbeMemRelease() above */ + assert( p->xDel==0 ); } /* @@ -638,7 +659,7 @@ void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){ */ void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ assert( (pFrom->flags & MEM_RowSet)==0 ); - VdbeMemRelease(pTo); + VdbeMemReleaseExtern(pTo); memcpy(pTo, pFrom, MEMCELLSIZE); pTo->xDel = 0; if( (pFrom->flags&MEM_Static)==0 ){ @@ -656,7 +677,7 @@ int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ int rc = SQLITE_OK; assert( (pFrom->flags & MEM_RowSet)==0 ); - VdbeMemRelease(pTo); + VdbeMemReleaseExtern(pTo); memcpy(pTo, pFrom, MEMCELLSIZE); pTo->flags &= ~MEM_Dyn; pTo->xDel = 0; From c137807a87d4754885c83dc7660026ca6c0bb8af Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 25 Aug 2014 11:33:41 +0000 Subject: [PATCH 24/29] Remove the pager_lookup() function since it is redundant with sqlite3PagerLookup(). FossilOrigin-Name: 54164ce47cfc3ad5dd8797114e4ba78811f23bef --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/pager.c | 26 +++++--------------------- 3 files changed, 12 insertions(+), 28 deletions(-) diff --git a/manifest b/manifest index bfef72eb6a..3c6bec475e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sname\sof\sthe\sVdbeMemRelease()\smacro\sto\sVdbeMemReleaseExtern()\sto\nmore\saccurately\sreflect\swhat\sit\sdoes.\s\sPerformance\senhancement\sto\sthe\nsqlite3VdbeMemRelease()\sfunction. -D 2014-08-25T11:20:27.189 +C Remove\sthe\spager_lookup()\sfunction\ssince\sit\sis\sredundant\swith\s\nsqlite3PagerLookup(). +D 2014-08-25T11:33:41.726 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -211,7 +211,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c bd7df3094a60915c148517504c76df4fca24e542 F src/os_win.c d067fce558a5032e6e6afe62899e5397bf63cf3e F src/os_win.h 09e751b20bbc107ffbd46e13555dc73576d88e21 -F src/pager.c c831b0df879114915c08dc5a0188f9f22c48403b +F src/pager.c 53cc5e9d73afb74add79f49755c8ee240fbdbef7 F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428 F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0 F src/pcache.c da602c5447051705cab41604bf3276815eb569d0 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0c7e1b875a14ff9d71af7bb125a0272a23d57353 -R 3449942ddb4a22bfe8e7f1684bd27e8b +P 3ca5846da7da5e08192a4c96288197be3b7ab6f7 +R e183e353a27fb2d0c63a06eeb0b66e97 U drh -Z c7041d8c52f909d88b499b4a5f3227aa +Z 12acde8fd951a315f106f1112e06c5c6 diff --git a/manifest.uuid b/manifest.uuid index 725161693a..698dca573d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3ca5846da7da5e08192a4c96288197be3b7ab6f7 \ No newline at end of file +54164ce47cfc3ad5dd8797114e4ba78811f23bef \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 4a178a2985..8930ce862c 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1677,21 +1677,6 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){ return rc; } -/* -** Find a page in the hash table given its page number. Return -** a pointer to the page or NULL if the requested page is not -** already in memory. -*/ -static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){ - PgHdr *p = 0; /* Return value */ - - /* It is not possible for a call to PcacheFetch() with createFlag==0 to - ** fail, since no attempt to allocate dynamic memory will be made. - */ - (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p); - return p; -} - /* ** Discard the entire contents of the in-memory page-cache. */ @@ -1984,7 +1969,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ #ifdef SQLITE_CHECK_PAGES sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash); if( pPager->dbSize==0 && sqlite3PcacheRefCount(pPager->pPCache)>0 ){ - PgHdr *p = pager_lookup(pPager, 1); + PgHdr *p = sqlite3PagerLookup(pPager, 1); if( p ){ p->pageHash = 0; sqlite3PagerUnrefNotNull(p); @@ -2263,7 +2248,7 @@ static int pager_playback_one_page( if( pagerUseWal(pPager) ){ pPg = 0; }else{ - pPg = pager_lookup(pPager, pgno); + pPg = sqlite3PagerLookup(pPager, pgno); } assert( pPg || !MEMDB ); assert( pPager->eState!=PAGER_OPEN || pPg==0 ); @@ -5434,7 +5419,6 @@ DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ assert( pPager!=0 ); assert( pgno!=0 ); assert( pPager->pPCache!=0 ); - assert( pPager->eState>=PAGER_READER && pPager->eState!=PAGER_ERROR ); sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg); return pPg; } @@ -5833,7 +5817,7 @@ static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){ sqlite3PagerUnrefNotNull(pPage); } } - }else if( (pPage = pager_lookup(pPager, pg))!=0 ){ + }else if( (pPage = sqlite3PagerLookup(pPager, pg))!=0 ){ if( pPage->flags&PGHDR_NEED_SYNC ){ needSync = 1; } @@ -5850,7 +5834,7 @@ static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){ if( rc==SQLITE_OK && needSync ){ assert( !MEMDB ); for(ii=0; iiflags |= PGHDR_NEED_SYNC; sqlite3PagerUnrefNotNull(pPage); @@ -6782,7 +6766,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){ ** for the page moved there. */ pPg->flags &= ~PGHDR_NEED_SYNC; - pPgOld = pager_lookup(pPager, pgno); + pPgOld = sqlite3PagerLookup(pPager, pgno); assert( !pPgOld || pPgOld->nRef==1 ); if( pPgOld ){ pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC); From f741e0491e0a1ac499983f5d709c08c334c18783 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 25 Aug 2014 18:29:38 +0000 Subject: [PATCH 25/29] In cases where stat4 data is available but cannot be used because the rhs of a range constraint is too complex a expression, fall back to using the default estimates for number of rows scanned. FossilOrigin-Name: e06dc6f0c35f87c44292c71677111b74f073a5c4 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/where.c | 6 +++--- test/analyze9.test | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 3c6bec475e..1e3b094e1d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sthe\spager_lookup()\sfunction\ssince\sit\sis\sredundant\swith\s\nsqlite3PagerLookup(). -D 2014-08-25T11:33:41.726 +C In\scases\swhere\sstat4\sdata\sis\savailable\sbut\scannot\sbe\sused\sbecause\sthe\srhs\sof\sa\srange\sconstraint\sis\stoo\scomplex\sa\sexpression,\sfall\sback\sto\susing\sthe\sdefault\sestimates\sfor\snumber\sof\srows\sscanned. +D 2014-08-25T18:29:38.998 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -297,7 +297,7 @@ F src/vtab.c 019dbfd0406a7447c990e1f7bd1dfcdb8895697f F src/wal.c 264df50a1b33124130b23180ded2e2c5663c652a F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 -F src/where.c 4c499d185827a492643cf017ae5e3aa0523f9f18 +F src/where.c 4e2770a1914b8ce30f3e44ad954b720eca3b5efd F src/whereInt.h 923820bee9726033a501a08d2fc69b9c1ee4feb3 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -317,7 +317,7 @@ F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4 F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88 -F test/analyze9.test 3ef1b471247308e710a794b6e50a6ab536c5604b +F test/analyze9.test 72795c8113604b5dcd47a1498a61d6d7fb5d041a F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944 F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 3ca5846da7da5e08192a4c96288197be3b7ab6f7 -R e183e353a27fb2d0c63a06eeb0b66e97 -U drh -Z 12acde8fd951a315f106f1112e06c5c6 +P 54164ce47cfc3ad5dd8797114e4ba78811f23bef +R 2f8cc3122e94f945065c591b14dad548 +U dan +Z ef14939a1b480c479e36ded151638132 diff --git a/manifest.uuid b/manifest.uuid index 698dca573d..0ea03bbedf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -54164ce47cfc3ad5dd8797114e4ba78811f23bef \ No newline at end of file +e06dc6f0c35f87c44292c71677111b74f073a5c4 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 6a4299cc9a..4ba8de6e41 100644 --- a/src/where.c +++ b/src/where.c @@ -2220,6 +2220,7 @@ static int whereRangeScanEst( iNew = a[0] + ((pLower->eOperator & WO_GT) ? a[1] : 0); if( iNew>iLower ) iLower = iNew; nOut--; + pLower = 0; } } @@ -2235,6 +2236,7 @@ static int whereRangeScanEst( iNew = a[0] + ((pUpper->eOperator & WO_LE) ? a[1] : 0); if( iNewnOut = (LogEst)nOut; WHERETRACE(0x10, ("range scan regions: %u..%u est=%d\n", (u32)iLower, (u32)iUpper, nOut)); - return SQLITE_OK; } }else{ int bDone = 0; @@ -2262,8 +2262,8 @@ static int whereRangeScanEst( #else UNUSED_PARAMETER(pParse); UNUSED_PARAMETER(pBuilder); -#endif assert( pLower || pUpper ); +#endif assert( pUpper==0 || (pUpper->wtFlags & TERM_VNULL)==0 ); nNew = whereRangeAdjust(pLower, nOut); nNew = whereRangeAdjust(pUpper, nNew); diff --git a/test/analyze9.test b/test/analyze9.test index 0d72658df6..8572cbea00 100644 --- a/test/analyze9.test +++ b/test/analyze9.test @@ -1088,4 +1088,50 @@ foreach {tn where eqp} { do_eqp_test 24.$tn "SeLeCt * FROM t5 WHERE $where" $eqp } +#------------------------------------------------------------------------- +# Test that if stat4 data is available but cannot be used because the +# rhs of a range constraint is a complex expression, the default estimates +# are used instead. +ifcapable stat4&&cte { + do_execsql_test 25.1 { + CREATE TABLE t6(a, b); + WITH ints(i,j) AS ( + SELECT 1,1 UNION ALL SELECT i+1,j+1 FROM ints WHERE i<100 + ) INSERT INTO t6 SELECT * FROM ints; + CREATE INDEX aa ON t6(a); + CREATE INDEX bb ON t6(b); + ANALYZE; + } + + # Term (b? AND b=? term. Better than + # (a<20) but not as good as (a<10). + do_eqp_test 25.4.1 { + SELECT * FROM t6 WHERE a < 10 AND (b BETWEEN ? AND 60) + } { + 0 0 0 {SEARCH TABLE t6 USING INDEX aa (a? AND b Date: Mon, 25 Aug 2014 20:11:52 +0000 Subject: [PATCH 26/29] Allow CAST expressions and unary "+" operators to be used in the DEFAULT argument of an ALTER TABLE ADD COLUMN and to be understand on the RHS of range constraints interpreted by STAT3/4. This involves a rewrite of the implementation of the CAST operator. FossilOrigin-Name: 91d8a8d0b792ea5c4fe68fd9caaf3345eddea486 --- manifest | 22 +++++------ manifest.uuid | 2 +- src/expr.c | 17 +------- src/vdbe.c | 100 ++++++----------------------------------------- src/vdbeInt.h | 1 + src/vdbemem.c | 57 ++++++++++++++++++++++++++- test/alter4.test | 2 +- 7 files changed, 84 insertions(+), 117 deletions(-) diff --git a/manifest b/manifest index 1e3b094e1d..f27497a3eb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\scases\swhere\sstat4\sdata\sis\savailable\sbut\scannot\sbe\sused\sbecause\sthe\srhs\sof\sa\srange\sconstraint\sis\stoo\scomplex\sa\sexpression,\sfall\sback\sto\susing\sthe\sdefault\sestimates\sfor\snumber\sof\srows\sscanned. -D 2014-08-25T18:29:38.998 +C Allow\sCAST\sexpressions\sand\sunary\s"+"\soperators\sto\sbe\sused\sin\sthe\sDEFAULT\nargument\sof\san\sALTER\sTABLE\sADD\sCOLUMN\sand\sto\sbe\sunderstand\son\sthe\sRHS\sof\nrange\sconstraints\sinterpreted\sby\sSTAT3/4.\s\sThis\sinvolves\sa\srewrite\sof\sthe\nimplementation\sof\sthe\sCAST\soperator. +D 2014-08-25T20:11:52.974 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -177,7 +177,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 F src/delete.c 5adcd322c6b08fc25d215d780ca62cebce66304d -F src/expr.c f749009cf4a8534efb5e0d5cd7c9fb1fb0f2836c +F src/expr.c 358634f4ddeeb4e69643cb6db5819104a7834c60 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 8d81a780ad78d16ec9082585758a8f1d6bf02ca3 F src/func.c bbb724b74ed96ca42675a7274646a71dd52bcda7 @@ -284,13 +284,13 @@ F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059 F src/utf.c 77abb5e6d27f3d236e50f7c8fff1d00e15262359 F src/util.c 068dcd26354a3898ccc64ad5c4bdb95a7a15d33a F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c 0fe4b47668b36a50bd9f7fd7b15cbeeb69d54b37 +F src/vdbe.c 2b3420d22410089b95a1555872dbc35183927a25 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 -F src/vdbeInt.h 20056cd59ff93ef9eb91009ece726d65dd7ed322 +F src/vdbeInt.h df58400454823954cfb241e5858f07f37fc1fd78 F src/vdbeapi.c cda974083d7597f807640d344ffcf76d872201ce F src/vdbeaux.c dba006f67c9fd1b1d07ee7fb0fb38aa1905161d1 F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4 -F src/vdbemem.c 4c9d686da474957d2e78834f13cc5f141fe6b87f +F src/vdbemem.c 5b5e296ac25f7458b6496fbee2756a087e8d569d F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 F src/vtab.c 019dbfd0406a7447c990e1f7bd1dfcdb8895697f @@ -307,7 +307,7 @@ F test/all.test 6ff7b43c2b4b905c74dc4a813d201d0fa64c5783 F test/alter.test 547dc2d292644301ac9a7dda22b319b74f9c08d2 F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060 F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d -F test/alter4.test d6c011fa0d6227abba762498cafbb607c9609e93 +F test/alter4.test c461150723ac957f3b2214aa0b11552cd72023ec F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f F test/analyze.test 1772936d66471c65221e437b6d1999c3a03166c4 @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 54164ce47cfc3ad5dd8797114e4ba78811f23bef -R 2f8cc3122e94f945065c591b14dad548 -U dan -Z ef14939a1b480c479e36ded151638132 +P e06dc6f0c35f87c44292c71677111b74f073a5c4 +R 9f2d5499974a5fb7517d1c1150241c64 +U drh +Z 9fb020703498fe8e63fa568755e6ee4e diff --git a/manifest.uuid b/manifest.uuid index 0ea03bbedf..c3a49f3b80 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e06dc6f0c35f87c44292c71677111b74f073a5c4 \ No newline at end of file +91d8a8d0b792ea5c4fe68fd9caaf3345eddea486 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 0d2292e943..fabdae2fcf 100644 --- a/src/expr.c +++ b/src/expr.c @@ -2595,26 +2595,13 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ #ifndef SQLITE_OMIT_CAST case TK_CAST: { /* Expressions of the form: CAST(pLeft AS token) */ - int aff, to_op; inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - aff = sqlite3AffinityType(pExpr->u.zToken, 0); - to_op = aff - SQLITE_AFF_TEXT + OP_ToText; - assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT ); - assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE ); - assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC ); - assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER ); - assert( to_op==OP_ToReal || aff!=SQLITE_AFF_REAL ); - testcase( to_op==OP_ToText ); - testcase( to_op==OP_ToBlob ); - testcase( to_op==OP_ToNumeric ); - testcase( to_op==OP_ToInt ); - testcase( to_op==OP_ToReal ); if( inReg!=target ){ sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target); inReg = target; } - sqlite3VdbeAddOp1(v, to_op, inReg); + sqlite3VdbeAddOp2(v, OP_Cast, target, + sqlite3AffinityType(pExpr->u.zToken, 0)); testcase( usedAsColumnCache(pParse, inReg, inReg) ); sqlite3ExprCacheAffinityChange(pParse, inReg, 1); break; diff --git a/src/vdbe.c b/src/vdbe.c index 72a1552ce1..ec2b64f770 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -1768,106 +1768,30 @@ case OP_RealAffinity: { /* in1 */ #endif #ifndef SQLITE_OMIT_CAST -/* Opcode: ToText P1 * * * * +/* Opcode: Cast P1 P2 * * * ** -** Force the value in register P1 to be text. -** If the value is numeric, convert it to a string using the -** equivalent of sprintf(). Blob values are unchanged and -** are afterwards simply interpreted as text. +** Force the value in register P1 to be the type defined by P2. +** +**
    +**
  • TEXT +**
  • BLOB +**
  • NUMERIC +**
  • INTEGER +**
  • REAL +**
** ** A NULL value is not changed by this routine. It remains NULL. */ -case OP_ToText: { /* same as TK_TO_TEXT, in1 */ +case OP_Cast: { /* in1 */ pIn1 = &aMem[pOp->p1]; memAboutToChange(p, pIn1); - if( pIn1->flags & MEM_Null ) break; - assert( MEM_Str==(MEM_Blob>>3) ); - pIn1->flags |= (pIn1->flags&MEM_Blob)>>3; - applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding); rc = ExpandBlob(pIn1); - assert( pIn1->flags & MEM_Str || db->mallocFailed ); - pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Blob|MEM_Zero); + sqlite3VdbeMemCast(pIn1, pOp->p2, encoding); UPDATE_MAX_BLOBSIZE(pIn1); break; } - -/* Opcode: ToBlob P1 * * * * -** -** Force the value in register P1 to be a BLOB. -** If the value is numeric, convert it to a string first. -** Strings are simply reinterpreted as blobs with no change -** to the underlying data. -** -** A NULL value is not changed by this routine. It remains NULL. -*/ -case OP_ToBlob: { /* same as TK_TO_BLOB, in1 */ - pIn1 = &aMem[pOp->p1]; - if( pIn1->flags & MEM_Null ) break; - if( (pIn1->flags & MEM_Blob)==0 ){ - applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding); - assert( pIn1->flags & MEM_Str || db->mallocFailed ); - MemSetTypeFlag(pIn1, MEM_Blob); - }else{ - pIn1->flags &= ~(MEM_TypeMask&~MEM_Blob); - } - UPDATE_MAX_BLOBSIZE(pIn1); - break; -} - -/* Opcode: ToNumeric P1 * * * * -** -** Force the value in register P1 to be numeric (either an -** integer or a floating-point number.) -** If the value is text or blob, try to convert it to an using the -** equivalent of atoi() or atof() and store 0 if no such conversion -** is possible. -** -** A NULL value is not changed by this routine. It remains NULL. -*/ -case OP_ToNumeric: { /* same as TK_TO_NUMERIC, in1 */ - pIn1 = &aMem[pOp->p1]; - sqlite3VdbeMemNumerify(pIn1); - break; -} #endif /* SQLITE_OMIT_CAST */ -/* Opcode: ToInt P1 * * * * -** -** Force the value in register P1 to be an integer. If -** The value is currently a real number, drop its fractional part. -** If the value is text or blob, try to convert it to an integer using the -** equivalent of atoi() and store 0 if no such conversion is possible. -** -** A NULL value is not changed by this routine. It remains NULL. -*/ -case OP_ToInt: { /* same as TK_TO_INT, in1 */ - pIn1 = &aMem[pOp->p1]; - if( (pIn1->flags & MEM_Null)==0 ){ - sqlite3VdbeMemIntegerify(pIn1); - } - break; -} - -#if !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) -/* Opcode: ToReal P1 * * * * -** -** Force the value in register P1 to be a floating point number. -** If The value is currently an integer, convert it. -** If the value is text or blob, try to convert it to an integer using the -** equivalent of atoi() and store 0.0 if no such conversion is possible. -** -** A NULL value is not changed by this routine. It remains NULL. -*/ -case OP_ToReal: { /* same as TK_TO_REAL, in1 */ - pIn1 = &aMem[pOp->p1]; - memAboutToChange(p, pIn1); - if( (pIn1->flags & MEM_Null)==0 ){ - sqlite3VdbeMemRealify(pIn1); - } - break; -} -#endif /* !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) */ - /* Opcode: Lt P1 P2 P3 P4 P5 ** Synopsis: if r[P1]flags & MEM_Null ) return; + switch( aff ){ + case SQLITE_AFF_NONE: { /* Really a cast to BLOB */ + if( (pMem->flags & MEM_Blob)==0 ){ + sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); + assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); + MemSetTypeFlag(pMem, MEM_Blob); + }else{ + pMem->flags &= ~(MEM_TypeMask&~MEM_Blob); + } + break; + } + case SQLITE_AFF_NUMERIC: { + sqlite3VdbeMemNumerify(pMem); + break; + } + case SQLITE_AFF_INTEGER: { + sqlite3VdbeMemIntegerify(pMem); + break; + } + case SQLITE_AFF_REAL: { + sqlite3VdbeMemRealify(pMem); + break; + } + default: { + assert( aff==SQLITE_AFF_TEXT ); + assert( MEM_Str==(MEM_Blob>>3) ); + pMem->flags |= (pMem->flags&MEM_Blob)>>3; + sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); + assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); + pMem->flags &= ~(MEM_Int|MEM_Real|MEM_Blob|MEM_Zero); + break; + } + } +} + + /* ** Delete any previous value and set the value stored in *pMem to NULL. */ @@ -1015,9 +1060,19 @@ static int valueFromExpr( *ppVal = 0; return SQLITE_OK; } - op = pExpr->op; + while( (op = pExpr->op)==TK_UPLUS ) pExpr = pExpr->pLeft; if( NEVER(op==TK_REGISTER) ) op = pExpr->op2; + if( op==TK_CAST ){ + u8 aff = sqlite3AffinityType(pExpr->u.zToken,0); + rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx); + if( rc==SQLITE_OK && *ppVal ){ + sqlite3VdbeMemCast(*ppVal, aff, SQLITE_UTF8); + sqlite3ValueApplyAffinity(*ppVal, affinity, SQLITE_UTF8); + } + return rc; + } + /* Handle negative integers in a single step. This is needed in the ** case when the value is -9223372036854775808. */ diff --git a/test/alter4.test b/test/alter4.test index eaad37e001..ac39d614a5 100644 --- a/test/alter4.test +++ b/test/alter4.test @@ -145,7 +145,7 @@ do_test alter4-2.6 { } {1 {Cannot add a column with non-constant default}} do_test alter4-2.7 { catchsql { - alter table t1 add column d default (-+1); + alter table t1 add column d default (-5+1); } } {1 {Cannot add a column with non-constant default}} do_test alter4-2.99 { From 21b0e733540b21b64fd90312f3a8741da8060793 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 25 Aug 2014 20:21:07 +0000 Subject: [PATCH 27/29] Test cases added for using unary "+" and CAST operators on the RHS of range constraints and verifying that STAT3/4 can use those constraints. FossilOrigin-Name: 42505e5a810832442699ca54a46637c50e7f9e71 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/analyzeA.test | 23 +++++++++++++++++++++-- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index f27497a3eb..761ead9728 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Allow\sCAST\sexpressions\sand\sunary\s"+"\soperators\sto\sbe\sused\sin\sthe\sDEFAULT\nargument\sof\san\sALTER\sTABLE\sADD\sCOLUMN\sand\sto\sbe\sunderstand\son\sthe\sRHS\sof\nrange\sconstraints\sinterpreted\sby\sSTAT3/4.\s\sThis\sinvolves\sa\srewrite\sof\sthe\nimplementation\sof\sthe\sCAST\soperator. -D 2014-08-25T20:11:52.974 +C Test\scases\sadded\sfor\susing\sunary\s"+"\sand\sCAST\soperators\son\sthe\sRHS\sof\srange\nconstraints\sand\sverifying\sthat\sSTAT3/4\scan\suse\sthose\sconstraints. +D 2014-08-25T20:21:07.683 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -318,7 +318,7 @@ F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88 F test/analyze9.test 72795c8113604b5dcd47a1498a61d6d7fb5d041a -F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944 +F test/analyzeA.test 3335697f6700c7052295cfd0067fc5b2aacddf9a F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93 F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P e06dc6f0c35f87c44292c71677111b74f073a5c4 -R 9f2d5499974a5fb7517d1c1150241c64 +P 91d8a8d0b792ea5c4fe68fd9caaf3345eddea486 +R 12fb957b1fcac5280a480acdbd82e25d U drh -Z 9fb020703498fe8e63fa568755e6ee4e +Z dc13f49ba965d3549e28167f01462351 diff --git a/manifest.uuid b/manifest.uuid index c3a49f3b80..edf7f89be2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -91d8a8d0b792ea5c4fe68fd9caaf3345eddea486 \ No newline at end of file +42505e5a810832442699ca54a46637c50e7f9e71 \ No newline at end of file diff --git a/test/analyzeA.test b/test/analyzeA.test index d9ca2c0f3b..a2da10edff 100644 --- a/test/analyzeA.test +++ b/test/analyzeA.test @@ -117,7 +117,7 @@ foreach {tn analyze_cmd} { } { reset_db do_test 1.$tn.1 { - execsql { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c) } + execsql { CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT, c INT) } for {set i 0} {$i < 100} {incr i} { set c [expr int(pow(1.1,$i)/100)] set b [expr 125 - int(pow(1.1,99-$i))/100] @@ -161,7 +161,26 @@ foreach {tn analyze_cmd} { do_eqp_test 1.$tn.3.6 { SELECT * FROM t1 WHERE b BETWEEN 75 AND 125 AND c BETWEEN 75 AND 125 } {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c? AND b? AND b? AND c? AND c Date: Mon, 25 Aug 2014 21:11:01 +0000 Subject: [PATCH 28/29] Minor changes to the CAST logic to make it more testable. FossilOrigin-Name: 1ad70ec550c004160d9c0c57e6c416812cdead5e --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbemem.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 761ead9728..192b84c230 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Test\scases\sadded\sfor\susing\sunary\s"+"\sand\sCAST\soperators\son\sthe\sRHS\sof\srange\nconstraints\sand\sverifying\sthat\sSTAT3/4\scan\suse\sthose\sconstraints. -D 2014-08-25T20:21:07.683 +C Minor\schanges\sto\sthe\sCAST\slogic\sto\smake\sit\smore\stestable. +D 2014-08-25T21:11:01.892 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -290,7 +290,7 @@ F src/vdbeInt.h df58400454823954cfb241e5858f07f37fc1fd78 F src/vdbeapi.c cda974083d7597f807640d344ffcf76d872201ce F src/vdbeaux.c dba006f67c9fd1b1d07ee7fb0fb38aa1905161d1 F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4 -F src/vdbemem.c 5b5e296ac25f7458b6496fbee2756a087e8d569d +F src/vdbemem.c 4e08ea087aea367dae7c45129b75487e0056e819 F src/vdbesort.c f7f5563bf7d4695ca8f3203f3bf9de96d04ed0b3 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767 F src/vtab.c 019dbfd0406a7447c990e1f7bd1dfcdb8895697f @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 91d8a8d0b792ea5c4fe68fd9caaf3345eddea486 -R 12fb957b1fcac5280a480acdbd82e25d +P 42505e5a810832442699ca54a46637c50e7f9e71 +R 64d7800c0b3c56b546428f1dfa98a8bd U drh -Z dc13f49ba965d3549e28167f01462351 +Z 2062d1773620f0a49c6fdbe873cdd5f6 diff --git a/manifest.uuid b/manifest.uuid index edf7f89be2..e6aa85bdb1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -42505e5a810832442699ca54a46637c50e7f9e71 \ No newline at end of file +1ad70ec550c004160d9c0c57e6c416812cdead5e \ No newline at end of file diff --git a/src/vdbemem.c b/src/vdbemem.c index 22e213898a..e4012593da 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -409,7 +409,6 @@ i64 sqlite3VdbeIntValue(Mem *pMem){ }else if( flags & (MEM_Str|MEM_Blob) ){ i64 value = 0; assert( pMem->z || pMem->n==0 ); - testcase( pMem->z==0 ); sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc); return value; }else{ @@ -1066,7 +1065,8 @@ static int valueFromExpr( if( op==TK_CAST ){ u8 aff = sqlite3AffinityType(pExpr->u.zToken,0); rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx); - if( rc==SQLITE_OK && *ppVal ){ + testcase( rc!=SQLITE_OK ); + if( *ppVal ){ sqlite3VdbeMemCast(*ppVal, aff, SQLITE_UTF8); sqlite3ValueApplyAffinity(*ppVal, affinity, SQLITE_UTF8); } From 05bbb2e824df2af559aaf301a4a44f16c080ffc8 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 25 Aug 2014 22:37:19 +0000 Subject: [PATCH 29/29] Add an assert() and five testcase() macros to the OP_Cast opcode implementation to help verify that it is fully tested. FossilOrigin-Name: af364cce9da0961593ef876b646197f82df08ad5 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbe.c | 6 ++++++ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 192b84c230..a75c4cd6f7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\schanges\sto\sthe\sCAST\slogic\sto\smake\sit\smore\stestable. -D 2014-08-25T21:11:01.892 +C Add\san\sassert()\sand\sfive\stestcase()\smacros\sto\sthe\sOP_Cast\sopcode\simplementation\nto\shelp\sverify\sthat\sit\sis\sfully\stested. +D 2014-08-25T22:37:19.150 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -284,7 +284,7 @@ F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059 F src/utf.c 77abb5e6d27f3d236e50f7c8fff1d00e15262359 F src/util.c 068dcd26354a3898ccc64ad5c4bdb95a7a15d33a F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c 2b3420d22410089b95a1555872dbc35183927a25 +F src/vdbe.c 2f8fbc520cac2f5bacc43de2aeed6a4880c9cb57 F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8 F src/vdbeInt.h df58400454823954cfb241e5858f07f37fc1fd78 F src/vdbeapi.c cda974083d7597f807640d344ffcf76d872201ce @@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 42505e5a810832442699ca54a46637c50e7f9e71 -R 64d7800c0b3c56b546428f1dfa98a8bd +P 1ad70ec550c004160d9c0c57e6c416812cdead5e +R b751a4133861a7b502aa405ba96eea49 U drh -Z 2062d1773620f0a49c6fdbe873cdd5f6 +Z 0bd8a75e39f468a6e4b9b4599a579487 diff --git a/manifest.uuid b/manifest.uuid index e6aa85bdb1..c36f309914 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1ad70ec550c004160d9c0c57e6c416812cdead5e \ No newline at end of file +af364cce9da0961593ef876b646197f82df08ad5 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index ec2b64f770..5d440d825b 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -1783,6 +1783,12 @@ case OP_RealAffinity: { /* in1 */ ** A NULL value is not changed by this routine. It remains NULL. */ case OP_Cast: { /* in1 */ + assert( pOp->p2>=SQLITE_AFF_TEXT && pOp->p2<=SQLITE_AFF_REAL ); + testcase( pOp->p2==SQLITE_AFF_TEXT ); + testcase( pOp->p2==SQLITE_AFF_NONE ); + testcase( pOp->p2==SQLITE_AFF_NUMERIC ); + testcase( pOp->p2==SQLITE_AFF_INTEGER ); + testcase( pOp->p2==SQLITE_AFF_REAL ); pIn1 = &aMem[pOp->p1]; memAboutToChange(p, pIn1); rc = ExpandBlob(pIn1);