From 57a140946f6f7508e64d91b5ae8671f3cab073a0 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 26 Mar 2015 11:55:03 +0000 Subject: [PATCH 01/26] Optimize cases where all the sorter is sorting a set of records that all begin with integer values, or that all begin with text values to be compared using BINARY. FossilOrigin-Name: ce5ad17c25cf2f8274ce304c51e4421faae0b32b --- manifest | 17 ++++++++++------- manifest.uuid | 2 +- src/vdbesort.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 6fdfb0ad40..65ccebc2d0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\san\sunreachable\sbranch\sinto\san\sassert(). -D 2015-03-25T18:29:10.982 +C Optimize\scases\swhere\sall\sthe\ssorter\sis\ssorting\sa\sset\sof\srecords\sthat\sall\sbegin\swith\sinteger\svalues,\sor\sthat\sall\sbegin\swith\stext\svalues\sto\sbe\scompared\susing\sBINARY. +D 2015-03-26T11:55:03.488 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 88a3e6261286db378fdffa1124cad11b3c05f5bb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -300,7 +300,7 @@ F src/vdbeapi.c 583d56b129dd27f12bed518270de9ebe521e6a75 F src/vdbeaux.c 413dc496248ac18eb0c19e35e86bb1ffd47b8907 F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90 F src/vdbemem.c c0dc81285b7571b0a31c40f17846fe2397ec1cd9 -F src/vdbesort.c 919717d7599fa31d343ec28bffd0f9e91a4ff5f6 +F src/vdbesort.c a8d82ed4b09f3b1f5390c7546a9bcad72d483abf F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010 F src/vtab.c 62d49237bd8f3be4863815a39387b0f9897fa5e1 F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb @@ -1247,7 +1247,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 37866b4d483296ab9b7fcb9f5486695d4c2b8ddd -R 6f3611ab9d4988693f727ae20dc9c9e5 -U drh -Z 3f028f44e21ab0b1619e9687cba7cf7a +P fb076b28c36975ff2e41440f22fe5de115c195da +R 1e1c6c1ab8dfb515d00c85e16ae436f0 +T *branch * sorter-opt +T *sym-sorter-opt * +T -sym-trunk * +U dan +Z 9752268c90db4ae1847219cb63314e99 diff --git a/manifest.uuid b/manifest.uuid index 849f782137..dfa9f94353 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fb076b28c36975ff2e41440f22fe5de115c195da \ No newline at end of file +ce5ad17c25cf2f8274ce304c51e4421faae0b32b \ No newline at end of file diff --git a/src/vdbesort.c b/src/vdbesort.c index bbdafa8230..4faeebf963 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -298,6 +298,7 @@ struct SortSubtask { UnpackedRecord *pUnpacked; /* Space to unpack a record */ SorterList list; /* List for thread to write to a PMA */ int nPMA; /* Number of PMAs currently in file */ + RecordCompare xCompare; /* Compare function to use */ SorterFile file; /* Temp file for level-0 PMAs */ SorterFile file2; /* Space for other PMAs */ }; @@ -328,9 +329,13 @@ struct VdbeSorter { u8 bUseThreads; /* True to use background threads */ u8 iPrev; /* Previous thread used to flush PMA */ u8 nTask; /* Size of aTask[] array */ + u8 typeMask; SortSubtask aTask[1]; /* One or more subtasks */ }; +#define SORTER_TYPE_INTEGER 0x01 +#define SORTER_TYPE_TEXT 0x02 + /* ** An instance of the following object is used to read records out of a ** PMA, in sorted order. The next key to be read is cached in nKey/aKey. @@ -765,7 +770,7 @@ static int vdbeSorterCompare( if( pKey2 ){ sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2); } - return sqlite3VdbeRecordCompare(nKey1, pKey1, r2); + return pTask->xCompare(nKey1, pKey1, r2); } /* @@ -835,9 +840,13 @@ int sqlite3VdbeSorterInit( pSorter->pKeyInfo = pKeyInfo = (KeyInfo*)((u8*)pSorter + sz); memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo); pKeyInfo->db = 0; - if( nField && nWorker==0 ) pKeyInfo->nField = nField; + if( nField && nWorker==0 ){ + pKeyInfo->nXField += (pKeyInfo->nField - nField); + pKeyInfo->nField = nField; + } pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt); pSorter->nTask = nWorker + 1; + pSorter->iPrev = nWorker-1; pSorter->bUseThreads = (pSorter->nTask>1); pSorter->db = db; for(i=0; inTask; i++){ @@ -863,6 +872,10 @@ int sqlite3VdbeSorterInit( if( !pSorter->list.aMemory ) rc = SQLITE_NOMEM; } } + + if( (pKeyInfo->nField+pKeyInfo->nXField)<13 && pKeyInfo->aColl[0]==0 ){ + pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT; + } } return rc; @@ -1182,6 +1195,13 @@ static int vdbeSortAllocUnpacked(SortSubtask *pTask){ if( pFree==0 ) return SQLITE_NOMEM; pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nField; pTask->pUnpacked->errCode = 0; + if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ + pTask->pUnpacked->r1 = 1; + pTask->pUnpacked->r2 = -1; + }else{ + pTask->pUnpacked->r1 = -1; + pTask->pUnpacked->r2 = 1; + } } return SQLITE_OK; } @@ -1235,12 +1255,20 @@ static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){ rc = vdbeSortAllocUnpacked(pTask); if( rc!=SQLITE_OK ) return rc; + p = pList->pList; + if( pTask->pSorter->typeMask==0 ){ + pTask->xCompare = sqlite3VdbeRecordCompare; + }else{ + UnpackedRecord *pRec = pTask->pUnpacked; + sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, p->nVal, SRVAL(p), pRec); + pTask->xCompare = sqlite3VdbeFindCompare(pRec); + } + aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *)); if( !aSlot ){ return SQLITE_NOMEM; } - p = pList->pList; while( p ){ SorterRecord *pNext; if( pList->aMemory ){ @@ -1602,6 +1630,16 @@ int sqlite3VdbeSorterWrite( int bFlush; /* True to flush contents of memory to PMA */ int nReq; /* Bytes of memory required */ int nPMA; /* Bytes of PMA space required */ + int t; /* serial type of first record field */ + + getVarint32((const u8*)&pVal->z[1], t); + if( t>0 && t<10 && t!=7 ){ + pSorter->typeMask &= SORTER_TYPE_INTEGER; + }else if( t & 0x01 ){ + pSorter->typeMask &= SORTER_TYPE_TEXT; + }else{ + pSorter->typeMask = 0; + } assert( pSorter ); @@ -2288,6 +2326,13 @@ static int vdbeSorterSetupMerge(VdbeSorter *pSorter){ MergeEngine *pMain = 0; #if SQLITE_MAX_WORKER_THREADS sqlite3 *db = pTask0->pSorter->db; + RecordCompare xCompare = (pSorter->typeMask==0 ? + sqlite3VdbeRecordCompare : pSorter->aTask[0].xCompare + ); + int i; + for(i=0; inTask; i++){ + pSorter->aTask[i].xCompare = xCompare; + } #endif rc = vdbeSorterMergeTreeBuild(pSorter, &pMain); From a9d9111c4aa590e197878515c7a9de526ef6feb9 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 28 Mar 2015 19:56:41 +0000 Subject: [PATCH 02/26] Further optimizations for sorting records that begin with integer or text values. FossilOrigin-Name: 24fe9f25d64ee516633fed1ae7ebc21554aa69ca --- manifest | 15 ++-- manifest.uuid | 2 +- src/vdbesort.c | 187 ++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 159 insertions(+), 45 deletions(-) diff --git a/manifest b/manifest index 65ccebc2d0..aba8fb17d1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Optimize\scases\swhere\sall\sthe\ssorter\sis\ssorting\sa\sset\sof\srecords\sthat\sall\sbegin\swith\sinteger\svalues,\sor\sthat\sall\sbegin\swith\stext\svalues\sto\sbe\scompared\susing\sBINARY. -D 2015-03-26T11:55:03.488 +C Further\soptimizations\sfor\ssorting\srecords\sthat\sbegin\swith\sinteger\sor\stext\svalues. +D 2015-03-28T19:56:41.373 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 88a3e6261286db378fdffa1124cad11b3c05f5bb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -300,7 +300,7 @@ F src/vdbeapi.c 583d56b129dd27f12bed518270de9ebe521e6a75 F src/vdbeaux.c 413dc496248ac18eb0c19e35e86bb1ffd47b8907 F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90 F src/vdbemem.c c0dc81285b7571b0a31c40f17846fe2397ec1cd9 -F src/vdbesort.c a8d82ed4b09f3b1f5390c7546a9bcad72d483abf +F src/vdbesort.c b3d16bbd66ff8d26b42670a8aa5dfda0e0d2e45e F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010 F src/vtab.c 62d49237bd8f3be4863815a39387b0f9897fa5e1 F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb @@ -1247,10 +1247,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 fb076b28c36975ff2e41440f22fe5de115c195da -R 1e1c6c1ab8dfb515d00c85e16ae436f0 -T *branch * sorter-opt -T *sym-sorter-opt * -T -sym-trunk * +P ce5ad17c25cf2f8274ce304c51e4421faae0b32b +R 5a4cff4b803c75214d0e7f89bc9331f1 U dan -Z 9752268c90db4ae1847219cb63314e99 +Z 8e7d5cc07144236ce8ed9e6cb6b634d0 diff --git a/manifest.uuid b/manifest.uuid index dfa9f94353..1d45093594 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ce5ad17c25cf2f8274ce304c51e4421faae0b32b \ No newline at end of file +24fe9f25d64ee516633fed1ae7ebc21554aa69ca \ No newline at end of file diff --git a/src/vdbesort.c b/src/vdbesort.c index 4faeebf963..b8ef783a06 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -291,6 +291,7 @@ struct MergeEngine { ** after the thread has finished are not dire. So we don't worry about ** memory barriers and such here. */ +typedef int (*SorterCompare)(SortSubtask*,int*,const void*,int,const void*,int); struct SortSubtask { SQLiteThread *pThread; /* Background thread, if any */ int bDone; /* Set if thread is finished but not joined */ @@ -298,11 +299,12 @@ struct SortSubtask { UnpackedRecord *pUnpacked; /* Space to unpack a record */ SorterList list; /* List for thread to write to a PMA */ int nPMA; /* Number of PMAs currently in file */ - RecordCompare xCompare; /* Compare function to use */ + SorterCompare xCompare; /* Compare function to use */ SorterFile file; /* Temp file for level-0 PMAs */ SorterFile file2; /* Space for other PMAs */ }; + /* ** Main sorter structure. A single instance of this is allocated for each ** sorter cursor created by the VDBE. @@ -747,30 +749,136 @@ static int vdbePmaReaderInit( return rc; } - /* ** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2, ** size nKey2 bytes). Use (pTask->pKeyInfo) for the collation sequences ** used by the comparison. Return the result of the comparison. ** -** Before returning, object (pTask->pUnpacked) is populated with the -** unpacked version of key2. Or, if pKey2 is passed a NULL pointer, then it -** is assumed that the (pTask->pUnpacked) structure already contains the -** unpacked key to use as key2. +** If IN/OUT parameter *pbKey2Cached is true when this function is called, +** it is assumed that (pTask->pUnpacked) contains the unpacked version +** of key2. If it is false, (pTask->pUnpacked) is populated with the unpacked +** version of key2 and *pbKey2Cached set to true before returning. ** ** If an OOM error is encountered, (pTask->pUnpacked->error_rc) is set ** to SQLITE_NOMEM. */ static int vdbeSorterCompare( SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ const void *pKey1, int nKey1, /* Left side of comparison */ const void *pKey2, int nKey2 /* Right side of comparison */ ){ UnpackedRecord *r2 = pTask->pUnpacked; - if( pKey2 ){ + if( !*pbKey2Cached ){ sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2); + *pbKey2Cached = 1; } - return pTask->xCompare(nKey1, pKey1, r2); + return sqlite3VdbeRecordCompare(nKey1, pKey1, r2); +} + +/* +** A specially optimized version of vdbeSorterCompare() that assumes that +** the first field of each key is a TEXT value and that the collation +** sequence to compare them with is BINARY. +*/ +static int vdbeSorterCompareText( + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ + const void *pKey1, int nKey1, /* Left side of comparison */ + const void *pKey2, int nKey2 /* Right side of comparison */ +){ + const u8 * const p1 = (const u8 * const)pKey1; + const u8 * const p2 = (const u8 * const)pKey2; + const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */ + const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */ + + int n1; + int n2; + int res; + + getVarint32(&p1[1], n1); n1 = (n1 - 13) / 2; + getVarint32(&p2[1], n2); n2 = (n2 - 13) / 2; + res = memcmp(v1, v2, MIN(n1, n2)); + if( res==0 ){ + res = n1 - n2; + } + + if( res==0 ){ + if( pTask->pSorter->pKeyInfo->nField>1 ){ + res = vdbeSorterCompare(pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2); + } + }else{ + if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ + res = res * -1; + } + } + + return res; +} + +/* +** A specially optimized version of vdbeSorterCompare() that assumes that +** the first field of each key is an INTEGER value. +*/ +static int vdbeSorterCompareInt( + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ + const void *pKey1, int nKey1, /* Left side of comparison */ + const void *pKey2, int nKey2 /* Right side of comparison */ +){ + const u8 * const p1 = (const u8 * const)pKey1; + const u8 * const p2 = (const u8 * const)pKey2; + const int s1 = p1[1]; /* Left hand serial type */ + const int s2 = p2[1]; /* Right hand serial type */ + const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */ + const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */ + int res; /* Return value */ + + assert( (s1>0 && s1<7) || s1==8 || s1==9 ); + assert( (s2>0 && s2<7) || s2==8 || s2==9 ); + + if( s1>7 && s2>7 ){ + res = s1 - s2; + }else{ + if( s1==s2 ){ + if( (*v1 ^ *v2) & 0x80 ){ + /* The two values have different signs */ + res = (*v1 & 0x80) ? -1 : +1; + }else{ + /* The two values have the same sign. Compare using memcmp(). */ + static const u8 aLen[] = {0, 1, 2, 3, 4, 6, 8 }; + int i; + res = 0; + for(i=0; i7 ){ + res = +1; + }else if( s1>7 ){ + res = -1; + }else{ + res = s1 - s2; + } + + if( res>0 ){ + if( *v1 & 0x80 ) res = -1; + }else if( res<0 ){ + if( *v2 & 0x80 ) res = +1; + } + } + } + + if( res==0 ){ + if( pTask->pSorter->pKeyInfo->nField>1 ){ + res = vdbeSorterCompare(pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2); + } + }else if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ + res = res * -1; + } + + return res; } /* @@ -873,7 +981,9 @@ int sqlite3VdbeSorterInit( } } - if( (pKeyInfo->nField+pKeyInfo->nXField)<13 && pKeyInfo->aColl[0]==0 ){ + if( (pKeyInfo->nField+pKeyInfo->nXField)<13 + && (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl) + ){ pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT; } } @@ -1219,28 +1329,42 @@ static void vdbeSorterMerge( ){ SorterRecord *pFinal = 0; SorterRecord **pp = &pFinal; - void *pVal2 = p2 ? SRVAL(p2) : 0; + int bCached = 0; while( p1 && p2 ){ int res; - res = vdbeSorterCompare(pTask, SRVAL(p1), p1->nVal, pVal2, p2->nVal); + res = pTask->xCompare( + pTask, &bCached, SRVAL(p1), p1->nVal, SRVAL(p2), p2->nVal + ); + if( res<=0 ){ *pp = p1; pp = &p1->u.pNext; p1 = p1->u.pNext; - pVal2 = 0; }else{ *pp = p2; - pp = &p2->u.pNext; + pp = &p2->u.pNext; p2 = p2->u.pNext; - if( p2==0 ) break; - pVal2 = SRVAL(p2); + bCached = 0; } } *pp = p1 ? p1 : p2; *ppOut = pFinal; } +/* +** Return the SorterCompare function to compare values collected by the +** sorter object passed as the only argument. +*/ +static SorterCompare vdbeSorterGetCompare(VdbeSorter *p){ + if( p->typeMask==SORTER_TYPE_INTEGER ){ + return vdbeSorterCompareInt; + }else if( p->typeMask==SORTER_TYPE_TEXT ){ + return vdbeSorterCompareText; + } + return vdbeSorterCompare; +} + /* ** Sort the linked list of records headed at pTask->pList. Return ** SQLITE_OK if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if @@ -1256,13 +1380,7 @@ static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){ if( rc!=SQLITE_OK ) return rc; p = pList->pList; - if( pTask->pSorter->typeMask==0 ){ - pTask->xCompare = sqlite3VdbeRecordCompare; - }else{ - UnpackedRecord *pRec = pTask->pUnpacked; - sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, p->nVal, SRVAL(p), pRec); - pTask->xCompare = sqlite3VdbeFindCompare(pRec); - } + pTask->xCompare = vdbeSorterGetCompare(pTask->pSorter); aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *)); if( !aSlot ){ @@ -1482,13 +1600,12 @@ static int vdbeMergeEngineStep( int i; /* Index of aTree[] to recalculate */ PmaReader *pReadr1; /* First PmaReader to compare */ PmaReader *pReadr2; /* Second PmaReader to compare */ - u8 *pKey2; /* To pReadr2->aKey, or 0 if record cached */ + int bCached = 0; /* Find the first two PmaReaders to compare. The one that was just ** advanced (iPrev) and the one next to it in the array. */ pReadr1 = &pMerger->aReadr[(iPrev & 0xFFFE)]; pReadr2 = &pMerger->aReadr[(iPrev | 0x0001)]; - pKey2 = pReadr2->aKey; for(i=(pMerger->nTree+iPrev)/2; i>0; i=i/2){ /* Compare pReadr1 and pReadr2. Store the result in variable iRes. */ @@ -1498,8 +1615,8 @@ static int vdbeMergeEngineStep( }else if( pReadr2->pFd==0 ){ iRes = -1; }else{ - iRes = vdbeSorterCompare(pTask, - pReadr1->aKey, pReadr1->nKey, pKey2, pReadr2->nKey + iRes = pTask->xCompare(pTask, &bCached, + pReadr1->aKey, pReadr1->nKey, pReadr2->aKey, pReadr2->nKey ); } @@ -1521,9 +1638,9 @@ static int vdbeMergeEngineStep( if( iRes<0 || (iRes==0 && pReadr1aTree[i] = (int)(pReadr1 - pMerger->aReadr); pReadr2 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ]; - pKey2 = pReadr2->aKey; + bCached = 0; }else{ - if( pReadr1->pFd ) pKey2 = 0; + bCached = (pReadr1->pFd!=0); pMerger->aTree[i] = (int)(pReadr2 - pMerger->aReadr); pReadr1 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ]; } @@ -1635,7 +1752,7 @@ int sqlite3VdbeSorterWrite( getVarint32((const u8*)&pVal->z[1], t); if( t>0 && t<10 && t!=7 ){ pSorter->typeMask &= SORTER_TYPE_INTEGER; - }else if( t & 0x01 ){ + }else if( t>10 && (t & 0x01) ){ pSorter->typeMask &= SORTER_TYPE_TEXT; }else{ pSorter->typeMask = 0; @@ -1905,10 +2022,12 @@ static void vdbeMergeEngineCompare( }else if( p2->pFd==0 ){ iRes = i1; }else{ + SortSubtask *pTask = pMerger->pTask; + int bCached = 0; int res; - assert( pMerger->pTask->pUnpacked!=0 ); /* from vdbeSortSubtaskMain() */ - res = vdbeSorterCompare( - pMerger->pTask, p1->aKey, p1->nKey, p2->aKey, p2->nKey + assert( pTask->pUnpacked!=0 ); /* from vdbeSortSubtaskMain() */ + res = pTask->xCompare( + pTask, &bCached, p1->aKey, p1->nKey, p2->aKey, p2->nKey ); if( res<=0 ){ iRes = i1; @@ -2326,10 +2445,8 @@ static int vdbeSorterSetupMerge(VdbeSorter *pSorter){ MergeEngine *pMain = 0; #if SQLITE_MAX_WORKER_THREADS sqlite3 *db = pTask0->pSorter->db; - RecordCompare xCompare = (pSorter->typeMask==0 ? - sqlite3VdbeRecordCompare : pSorter->aTask[0].xCompare - ); int i; + SorterCompare xCompare = vdbeSorterGetCompare(pSorter); for(i=0; inTask; i++){ pSorter->aTask[i].xCompare = xCompare; } From d2e1191929c9cdceebfcf46bcaf18d03ea4d47be Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 30 Mar 2015 09:58:38 +0000 Subject: [PATCH 03/26] Remove some unnecessary code from vdbesort.c. FossilOrigin-Name: b58191e91736b1d978db4127f22867dfe2302f7c --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbesort.c | 7 ------- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index aba8fb17d1..a3ffa9b4e0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Further\soptimizations\sfor\ssorting\srecords\sthat\sbegin\swith\sinteger\sor\stext\svalues. -D 2015-03-28T19:56:41.373 +C Remove\ssome\sunnecessary\scode\sfrom\svdbesort.c. +D 2015-03-30T09:58:38.613 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 88a3e6261286db378fdffa1124cad11b3c05f5bb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -300,7 +300,7 @@ F src/vdbeapi.c 583d56b129dd27f12bed518270de9ebe521e6a75 F src/vdbeaux.c 413dc496248ac18eb0c19e35e86bb1ffd47b8907 F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90 F src/vdbemem.c c0dc81285b7571b0a31c40f17846fe2397ec1cd9 -F src/vdbesort.c b3d16bbd66ff8d26b42670a8aa5dfda0e0d2e45e +F src/vdbesort.c f283b28d9d1bbaf9c4467c1275ab2146ed868ec9 F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010 F src/vtab.c 62d49237bd8f3be4863815a39387b0f9897fa5e1 F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb @@ -1247,7 +1247,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 ce5ad17c25cf2f8274ce304c51e4421faae0b32b -R 5a4cff4b803c75214d0e7f89bc9331f1 +P 24fe9f25d64ee516633fed1ae7ebc21554aa69ca +R 7cd5cef35d63d5a82a586382f49d8e50 U dan -Z 8e7d5cc07144236ce8ed9e6cb6b634d0 +Z 51fc974a93f39baea754c6fb429251e1 diff --git a/manifest.uuid b/manifest.uuid index 1d45093594..698dbf4147 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -24fe9f25d64ee516633fed1ae7ebc21554aa69ca \ No newline at end of file +b58191e91736b1d978db4127f22867dfe2302f7c \ No newline at end of file diff --git a/src/vdbesort.c b/src/vdbesort.c index b8ef783a06..b6483b9ee7 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -1305,13 +1305,6 @@ static int vdbeSortAllocUnpacked(SortSubtask *pTask){ if( pFree==0 ) return SQLITE_NOMEM; pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nField; pTask->pUnpacked->errCode = 0; - if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ - pTask->pUnpacked->r1 = 1; - pTask->pUnpacked->r2 = -1; - }else{ - pTask->pUnpacked->r1 = -1; - pTask->pUnpacked->r2 = 1; - } } return SQLITE_OK; } From 7004f3f6a311398f00d856b359d7389b72f802de Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 30 Mar 2015 12:06:26 +0000 Subject: [PATCH 04/26] Improve performance of multi-field sorts where the first field has a low cardinality. FossilOrigin-Name: 601e7b6b8e6bfabda03b70f75094c9014e3a3c49 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/vdbe.h | 1 + src/vdbeaux.c | 8 ++++---- src/vdbesort.c | 27 +++++++++++++++++++++++++-- 5 files changed, 39 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index a3ffa9b4e0..a7a78bf354 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\ssome\sunnecessary\scode\sfrom\svdbesort.c. -D 2015-03-30T09:58:38.613 +C Improve\sperformance\sof\smulti-field\ssorts\swhere\sthe\sfirst\sfield\shas\sa\slow\scardinality. +D 2015-03-30T12:06:26.995 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 88a3e6261286db378fdffa1124cad11b3c05f5bb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -294,13 +294,13 @@ F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c F src/util.c 98a7627ca48ad3265b6940915a1d08355eb3fc7e F src/vacuum.c 9460b9de7b2d4e34b0d374894aa6c8a0632be8ec F src/vdbe.c bbfede5a8a6908b3ddcd55fdb0b2301288dd4754 -F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3 +F src/vdbe.h 7e538ecf47dccb307ea2d087c3ddc2dd8d70e79d F src/vdbeInt.h 9cbaa84f53ddd2d09a0cf61a94337a3a035d08a0 F src/vdbeapi.c 583d56b129dd27f12bed518270de9ebe521e6a75 -F src/vdbeaux.c 413dc496248ac18eb0c19e35e86bb1ffd47b8907 +F src/vdbeaux.c a20504ae52392459fa08402fda3f195f19d7c79d F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90 F src/vdbemem.c c0dc81285b7571b0a31c40f17846fe2397ec1cd9 -F src/vdbesort.c f283b28d9d1bbaf9c4467c1275ab2146ed868ec9 +F src/vdbesort.c 7b3684665ea51d642b0e664fa4d0b0d08d61d80c F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010 F src/vtab.c 62d49237bd8f3be4863815a39387b0f9897fa5e1 F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb @@ -1247,7 +1247,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 24fe9f25d64ee516633fed1ae7ebc21554aa69ca -R 7cd5cef35d63d5a82a586382f49d8e50 +P b58191e91736b1d978db4127f22867dfe2302f7c +R ce44a3d54ad53a02b61fed80311cecef U dan -Z 51fc974a93f39baea754c6fb429251e1 +Z 8753c6822202b0898d8492105ecdb751 diff --git a/manifest.uuid b/manifest.uuid index 698dbf4147..2a8f64fa3a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b58191e91736b1d978db4127f22867dfe2302f7c \ No newline at end of file +601e7b6b8e6bfabda03b70f75094c9014e3a3c49 \ No newline at end of file diff --git a/src/vdbe.h b/src/vdbe.h index b715241b41..bb597b68d7 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -213,6 +213,7 @@ int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); +int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int); UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); typedef int (*RecordCompare)(int,const void*,UnpackedRecord*); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 9c5d9acca9..1c10bab0b8 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3585,7 +3585,7 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){ ** pPKey2->errCode is set to SQLITE_NOMEM and, if it is not NULL, the ** malloc-failed flag set on database handle (pPKey2->pKeyInfo->db). */ -static int vdbeRecordCompareWithSkip( +int sqlite3VdbeRecordCompareWithSkip( int nKey1, const void *pKey1, /* Left key */ UnpackedRecord *pPKey2, /* Right key */ int bSkip /* If true, skip the first field */ @@ -3771,7 +3771,7 @@ int sqlite3VdbeRecordCompare( int nKey1, const void *pKey1, /* Left key */ UnpackedRecord *pPKey2 /* Right key */ ){ - return vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0); + return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0); } @@ -3859,7 +3859,7 @@ static int vdbeRecordCompareInt( }else if( pPKey2->nField>1 ){ /* The first fields of the two keys are equal. Compare the trailing ** fields. */ - res = vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); + res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); }else{ /* The first fields of the two keys are equal and there are no trailing ** fields. Return pPKey2->default_rc in this case. */ @@ -3907,7 +3907,7 @@ static int vdbeRecordCompareString( res = nStr - pPKey2->aMem[0].n; if( res==0 ){ if( pPKey2->nField>1 ){ - res = vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); + res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); }else{ res = pPKey2->default_rc; } diff --git a/src/vdbesort.c b/src/vdbesort.c index b6483b9ee7..547dce2e65 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -749,6 +749,25 @@ static int vdbePmaReaderInit( return rc; } +/* +** A version of vdbeSorterCompare() that assumes that it has already been +** determined that the first field of key1 is equal to the first field of +** key2. +*/ +static int vdbeSorterCompareTail( + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ + const void *pKey1, int nKey1, /* Left side of comparison */ + const void *pKey2, int nKey2 /* Right side of comparison */ +){ + UnpackedRecord *r2 = pTask->pUnpacked; + if( *pbKey2Cached==0 ){ + sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2); + *pbKey2Cached = 1; + } + return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, r2, 1); +} + /* ** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2, ** size nKey2 bytes). Use (pTask->pKeyInfo) for the collation sequences @@ -805,7 +824,9 @@ static int vdbeSorterCompareText( if( res==0 ){ if( pTask->pSorter->pKeyInfo->nField>1 ){ - res = vdbeSorterCompare(pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2); + res = vdbeSorterCompareTail( + pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 + ); } }else{ if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ @@ -872,7 +893,9 @@ static int vdbeSorterCompareInt( if( res==0 ){ if( pTask->pSorter->pKeyInfo->nField>1 ){ - res = vdbeSorterCompare(pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2); + res = vdbeSorterCompareTail( + pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 + ); } }else if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ res = res * -1; From b18e60b3e43270773c163d7b6424b904fb9ffb9a Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 1 Apr 2015 16:18:00 +0000 Subject: [PATCH 05/26] Reduce the CPU used by CREATE INDEX statements by taking better advantage of the fact that keys are inserted in sorted order. FossilOrigin-Name: 592cdc5d7254be7032aa9c0b03405a74ca060b51 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/build.c | 3 ++- src/vdbe.c | 3 ++- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index a7a78bf354..be112fc01e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\sperformance\sof\smulti-field\ssorts\swhere\sthe\sfirst\sfield\shas\sa\slow\scardinality. -D 2015-03-30T12:06:26.995 +C Reduce\sthe\sCPU\sused\sby\sCREATE\sINDEX\sstatements\sby\staking\sbetter\sadvantage\sof\sthe\sfact\sthat\skeys\sare\sinserted\sin\ssorted\sorder. +D 2015-04-01T16:18:00.779 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 88a3e6261286db378fdffa1124cad11b3c05f5bb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -176,7 +176,7 @@ F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 F src/btree.c 4f305e554d7d207375c3e29ab0335bd5a473a125 F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1 F src/btreeInt.h 2bfefc01875d8da066504c233ec259fcb3b2ef72 -F src/build.c 0419bba592c22f6d00e6d57a2ca7136720d02c1a +F src/build.c 9103f5cd8f4071dc0c44a3312956e53f5b7f52c8 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/complete.c 198a0066ba60ab06fc00fba1998d870a4d575463 F src/ctime.c 98f89724adc891a1a4c655bee04e33e716e05887 @@ -293,7 +293,7 @@ F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c F src/util.c 98a7627ca48ad3265b6940915a1d08355eb3fc7e F src/vacuum.c 9460b9de7b2d4e34b0d374894aa6c8a0632be8ec -F src/vdbe.c bbfede5a8a6908b3ddcd55fdb0b2301288dd4754 +F src/vdbe.c a9d916abb1e22355a81b0e72040917ba33c87ed7 F src/vdbe.h 7e538ecf47dccb307ea2d087c3ddc2dd8d70e79d F src/vdbeInt.h 9cbaa84f53ddd2d09a0cf61a94337a3a035d08a0 F src/vdbeapi.c 583d56b129dd27f12bed518270de9ebe521e6a75 @@ -1247,7 +1247,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 b58191e91736b1d978db4127f22867dfe2302f7c -R ce44a3d54ad53a02b61fed80311cecef +P 601e7b6b8e6bfabda03b70f75094c9014e3a3c49 +R 151febe3c42a1563a662898adadb6b2d U dan -Z 8753c6822202b0898d8492105ecdb751 +Z 37e9d6c37bda7e19a2c8ebf1573e150d diff --git a/manifest.uuid b/manifest.uuid index 2a8f64fa3a..6bc7a444cf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -601e7b6b8e6bfabda03b70f75094c9014e3a3c49 \ No newline at end of file +592cdc5d7254be7032aa9c0b03405a74ca060b51 \ No newline at end of file diff --git a/src/build.c b/src/build.c index fcf96bd42c..11c790d311 100644 --- a/src/build.c +++ b/src/build.c @@ -2763,7 +2763,8 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ addr2 = sqlite3VdbeCurrentAddr(v); } sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx); - sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1); + sqlite3VdbeAddOp3(v, OP_Last, iIdx, 0, -1); + sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v); diff --git a/src/vdbe.c b/src/vdbe.c index ec5e6d7442..150b2c150f 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -4480,7 +4480,7 @@ case OP_NullRow: { break; } -/* Opcode: Last P1 P2 * * * +/* Opcode: Last P1 P2 P3 * * ** ** The next use of the Rowid or Column or Prev instruction for P1 ** will refer to the last entry in the database table or index. @@ -4507,6 +4507,7 @@ case OP_Last: { /* jump */ pC->nullRow = (u8)res; pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; + pC->seekResult = pOp->p3; #ifdef SQLITE_DEBUG pC->seekOp = OP_Last; #endif From e34162b14f24aae2b478b917ceb6f516289ac39a Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 1 Apr 2015 18:20:25 +0000 Subject: [PATCH 06/26] When vacuuming an index that uses no collations other than BINARY, assume that the order of index entries will not be changed by the VACUUM. FossilOrigin-Name: e403460b96814ac8cb976d58b27939b3bd3c61f9 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/insert.c | 48 ++++++++++++++++++++++++++++++++++++++++-------- src/sqliteInt.h | 1 + src/vacuum.c | 4 ++++ 5 files changed, 54 insertions(+), 17 deletions(-) diff --git a/manifest b/manifest index be112fc01e..16584352e7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Reduce\sthe\sCPU\sused\sby\sCREATE\sINDEX\sstatements\sby\staking\sbetter\sadvantage\sof\sthe\sfact\sthat\skeys\sare\sinserted\sin\ssorted\sorder. -D 2015-04-01T16:18:00.779 +C When\svacuuming\san\sindex\sthat\suses\sno\scollations\sother\sthan\sBINARY,\sassume\sthat\sthe\sorder\sof\sindex\sentries\swill\snot\sbe\schanged\sby\sthe\sVACUUM. +D 2015-04-01T18:20:25.537 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 88a3e6261286db378fdffa1124cad11b3c05f5bb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -190,7 +190,7 @@ F src/global.c 4f77cadbc5427d00139ba43d0f3979804cbb700e F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 5b9243a33726008cc4132897d2be371db12a13be +F src/insert.c 1cc9dc4e939b5dd4a74ac4a3222b89e66b074210 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770 @@ -235,7 +235,7 @@ F src/shell.c 3ae1e53878d2804fe77b8c8f1f6ca287a0e5d80e F src/sqlite.h.in 278602140d49575e8708e643161f4263e428a02a F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d -F src/sqliteInt.h bedf15914c09bfb5fe3ec4e3f211a4a6fc42cd33 +F src/sqliteInt.h df0ee3545220b8687d8640d433d1417b31e1675a F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179 F src/table.c e7a09215315a978057fb42c640f890160dbcc45e @@ -292,7 +292,7 @@ F src/trigger.c 25571661fdeae8c7f975ff40ffec205520a3f92f F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c F src/util.c 98a7627ca48ad3265b6940915a1d08355eb3fc7e -F src/vacuum.c 9460b9de7b2d4e34b0d374894aa6c8a0632be8ec +F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 F src/vdbe.c a9d916abb1e22355a81b0e72040917ba33c87ed7 F src/vdbe.h 7e538ecf47dccb307ea2d087c3ddc2dd8d70e79d F src/vdbeInt.h 9cbaa84f53ddd2d09a0cf61a94337a3a035d08a0 @@ -1247,7 +1247,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 601e7b6b8e6bfabda03b70f75094c9014e3a3c49 -R 151febe3c42a1563a662898adadb6b2d +P 592cdc5d7254be7032aa9c0b03405a74ca060b51 +R d93391642538d3e00eae6a1c718cf53f U dan -Z 37e9d6c37bda7e19a2c8ebf1573e150d +Z 6ea2b15ffbb091b1ac11e4173c1e9ec7 diff --git a/manifest.uuid b/manifest.uuid index 6bc7a444cf..180597c5c9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -592cdc5d7254be7032aa9c0b03405a74ca060b51 \ No newline at end of file +e403460b96814ac8cb976d58b27939b3bd3c61f9 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index a5c3f3e92d..f8ae4d7d3c 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1765,6 +1765,7 @@ static int xferOptimization( int onError, /* How to handle constraint errors */ int iDbDest /* The database of pDest */ ){ + sqlite3 *db = pParse->db; ExprList *pEList; /* The result set of the SELECT */ Table *pSrc; /* The table in the FROM clause of SELECT */ Index *pSrcIdx, *pDestIdx; /* Source and destination indices */ @@ -1912,11 +1913,11 @@ static int xferOptimization( ** the extra complication to make this rule less restrictive is probably ** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e] */ - if( (pParse->db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){ + if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){ return 0; } #endif - if( (pParse->db->flags & SQLITE_CountRows)!=0 ){ + if( (db->flags & SQLITE_CountRows)!=0 ){ return 0; /* xfer opt does not play well with PRAGMA count_changes */ } @@ -1927,7 +1928,7 @@ static int xferOptimization( #ifdef SQLITE_TEST sqlite3_xferopt_count++; #endif - iDbSrc = sqlite3SchemaToIndex(pParse->db, pSrc->pSchema); + iDbSrc = sqlite3SchemaToIndex(db, pSrc->pSchema); v = sqlite3GetVdbe(pParse); sqlite3CodeVerifySchema(pParse, iDbSrc); iSrc = pParse->nTab++; @@ -1937,14 +1938,18 @@ static int xferOptimization( regRowid = sqlite3GetTempReg(pParse); sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite); assert( HasRowid(pDest) || destHasUniqueIdx ); - if( (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */ + if( (db->flags & SQLITE_Vacuum)==0 && ( + (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */ || destHasUniqueIdx /* (2) */ || (onError!=OE_Abort && onError!=OE_Rollback) /* (3) */ - ){ + )){ /* In some circumstances, we are able to run the xfer optimization - ** only if the destination table is initially empty. This code makes - ** that determination. Conditions under which the destination must - ** be empty: + ** only if the destination table is initially empty. Unless the + ** SQLITE_Vacuum flag is set, this block generates code to make + ** that determination. If SQLITE_Vacuum is set, then the destination + ** table is always empty. + ** + ** Conditions under which the destination must be empty: ** ** (1) There is no INTEGER PRIMARY KEY but there are indices. ** (If the destination is not initially empty, the rowid fields @@ -1987,6 +1992,7 @@ static int xferOptimization( sqlite3TableLock(pParse, iDbSrc, pSrc->tnum, 0, pSrc->zName); } for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ + u8 useSeekResult = 0; for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){ if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; } @@ -2000,7 +2006,33 @@ static int xferOptimization( VdbeComment((v, "%s", pDestIdx->zName)); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData); + if( db->flags & SQLITE_Vacuum ){ + /* This INSERT command is part of a VACUUM operation, which guarantees + ** that the destination table is empty. If all indexed columns use + ** collation sequence BINARY, then it can also be assumed that the + ** index will be populated by inserting keys in strictly sorted + ** order. In this case, instead of seeking within the b-tree as part + ** of every OP_IdxInsert opcode, an OP_Last is added before the + ** OP_IdxInsert to seek to the point within the b-tree where each key + ** should be inserted. This is faster. + ** + ** If any of the indexed columns use a collation sequence other than + ** BINARY, this optimization is disabled. This is because the user + ** might change the definition of a collation sequence and then run + ** a VACUUM command. In that case keys may not be written in strictly + ** sorted order. */ + int i; + for(i=0; inColumn; i++){ + char *zColl = pSrcIdx->azColl[i]; + if( zColl && sqlite3_stricmp("BINARY", zColl) ) break; + } + if( i==pSrcIdx->nColumn ){ + useSeekResult = OPFLAG_USESEEKRESULT; + sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); + } + } sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1); + sqlite3VdbeChangeP5(v, useSeekResult); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 9df6d1bc4e..5e49bf58ff 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1226,6 +1226,7 @@ struct sqlite3 { #define SQLITE_DeferFKs 0x01000000 /* Defer all FK constraints */ #define SQLITE_QueryOnly 0x02000000 /* Disable database changes */ #define SQLITE_VdbeEQP 0x04000000 /* Debug EXPLAIN QUERY PLAN */ +#define SQLITE_Vacuum 0x08000000 /* Currently in a VACUUM */ /* diff --git a/src/vacuum.c b/src/vacuum.c index dca43e217e..adc802e60b 100644 --- a/src/vacuum.c +++ b/src/vacuum.c @@ -250,6 +250,8 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy ** the contents to the temporary database. */ + assert( (db->flags & SQLITE_Vacuum)==0 ); + db->flags |= SQLITE_Vacuum; rc = execExecSql(db, pzErrMsg, "SELECT 'INSERT INTO vacuum_db.' || quote(name) " "|| ' SELECT * FROM main.' || quote(name) || ';'" @@ -257,6 +259,8 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ "WHERE type = 'table' AND name!='sqlite_sequence' " " AND coalesce(rootpage,1)>0" ); + assert( (db->flags & SQLITE_Vacuum)!=0 ); + db->flags &= ~SQLITE_Vacuum; if( rc!=SQLITE_OK ) goto end_of_vacuum; /* Copy over the sequence table From 29f1a19cd96e8d7f72366492986cce2053df0deb Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 2 Apr 2015 09:06:21 +0000 Subject: [PATCH 07/26] Fix a problem in vdbesort.c to do with caching unpacked records. FossilOrigin-Name: 80a00539506c95443165a781d1d869205057ca6c --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbesort.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 8108693bf7..f9ce3a510d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\slatest\strunk\schanges\swith\sthis\sbranch. -D 2015-04-01T18:22:26.384 +C Fix\sa\sproblem\sin\svdbesort.c\sto\sdo\swith\scaching\sunpacked\srecords. +D 2015-04-02T09:06:21.116 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 00d12636df7a5b08af09116bcd6c7bfd49b8b3b4 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -300,7 +300,7 @@ F src/vdbeapi.c 583d56b129dd27f12bed518270de9ebe521e6a75 F src/vdbeaux.c a20504ae52392459fa08402fda3f195f19d7c79d F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90 F src/vdbemem.c c0dc81285b7571b0a31c40f17846fe2397ec1cd9 -F src/vdbesort.c 7b3684665ea51d642b0e664fa4d0b0d08d61d80c +F src/vdbesort.c 74a41fcd3adc22bc47ede68443d0b3e26ae13bb8 F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010 F src/vtab.c 62d49237bd8f3be4863815a39387b0f9897fa5e1 F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb @@ -1248,7 +1248,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 e403460b96814ac8cb976d58b27939b3bd3c61f9 30011ad2f55cfcacaf23a58ebcc17b17a7b9355e -R 768d1278a2c7aae9e472dc5791f2f6a1 +P 4621b2eef8be6d944f87de097bd11c649fe43333 +R 0796456518338cd116674974cfde4890 U dan -Z 2045741c9810a18232145862154fc073 +Z 0cef8df18e8711c69cda8f5613bc4995 diff --git a/manifest.uuid b/manifest.uuid index a5a195f19f..0941cff2b9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4621b2eef8be6d944f87de097bd11c649fe43333 \ No newline at end of file +80a00539506c95443165a781d1d869205057ca6c \ No newline at end of file diff --git a/src/vdbesort.c b/src/vdbesort.c index 547dce2e65..f4b995c88a 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -1656,7 +1656,7 @@ static int vdbeMergeEngineStep( pReadr2 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ]; bCached = 0; }else{ - bCached = (pReadr1->pFd!=0); + if( pReadr1->pFd ) bCached = 0; pMerger->aTree[i] = (int)(pReadr2 - pMerger->aReadr); pReadr1 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ]; } From 5efbd06ab31aa0853d79b5361142b44c211a33b6 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 8 Apr 2015 12:16:33 +0000 Subject: [PATCH 08/26] Version 3.8.9 FossilOrigin-Name: 8a8ffc862e96f57aa698f93de10dee28e69f6e09 --- manifest | 11 +++++++---- manifest.uuid | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/manifest b/manifest index aa53c43007..e3dc7c37f3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\ssigned\sinteger\soverflow\swhen\sconverting\soversized\sin-line\sinteger\nwidths\sand\sprecisions\sin\sprintf(). -D 2015-04-07T15:39:29.937 +C Version\s3.8.9 +D 2015-04-08T12:16:33.323 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 00d12636df7a5b08af09116bcd6c7bfd49b8b3b4 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -1249,7 +1249,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 95625ef3adc3c408d67e70f877f390445fbb8292 +P 8e4ac2ce24415926247961b00a62425ae85d6ffb R 5875861747bb686954783d9ce4259b86 +T +bgcolor * #d0c0ff +T +sym-release * +T +sym-version-3.8.9 * U drh -Z e5281cee406ead55e17262e5bdbb2163 +Z 05045ab8d5dbbaefca88cc23b8dca09c diff --git a/manifest.uuid b/manifest.uuid index 786af92027..a38b33773e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8e4ac2ce24415926247961b00a62425ae85d6ffb \ No newline at end of file +8a8ffc862e96f57aa698f93de10dee28e69f6e09 \ No newline at end of file From 50c7bb67f0e23c0b9618c7d488e234fb789505c3 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 9 Apr 2015 11:24:03 +0000 Subject: [PATCH 09/26] Remove a variable initializion to silence a harmless compiler warning. FossilOrigin-Name: 79861adbef8998c0f23e160543af8212d5546cd0 --- manifest | 15 ++++++--------- manifest.uuid | 2 +- src/complete.c | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index e3dc7c37f3..2af0d5f0d6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Version\s3.8.9 -D 2015-04-08T12:16:33.323 +C Remove\sa\svariable\sinitializion\sto\ssilence\sa\sharmless\scompiler\swarning. +D 2015-04-09T11:24:03.589 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 00d12636df7a5b08af09116bcd6c7bfd49b8b3b4 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -178,7 +178,7 @@ F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1 F src/btreeInt.h 973a22a6fd61350b454ad614832b1f0a5e25a1e4 F src/build.c 0419bba592c22f6d00e6d57a2ca7136720d02c1a F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 -F src/complete.c 198a0066ba60ab06fc00fba1998d870a4d575463 +F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575 F src/ctime.c 98f89724adc891a1a4c655bee04e33e716e05887 F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac F src/delete.c 37964e6c1d73ff49cbea9ff690c9605fb15f600e @@ -1249,10 +1249,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 8e4ac2ce24415926247961b00a62425ae85d6ffb -R 5875861747bb686954783d9ce4259b86 -T +bgcolor * #d0c0ff -T +sym-release * -T +sym-version-3.8.9 * +P 8a8ffc862e96f57aa698f93de10dee28e69f6e09 +R 94d9923532f03d2c01923395a653f609 U drh -Z 05045ab8d5dbbaefca88cc23b8dca09c +Z 1ec7205940b0e152091a81dfbeda06fb diff --git a/manifest.uuid b/manifest.uuid index a38b33773e..acb9c7faab 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8a8ffc862e96f57aa698f93de10dee28e69f6e09 \ No newline at end of file +79861adbef8998c0f23e160543af8212d5546cd0 \ No newline at end of file diff --git a/src/complete.c b/src/complete.c index f7a35cc6f3..a12184e64d 100644 --- a/src/complete.c +++ b/src/complete.c @@ -269,7 +269,7 @@ int sqlite3_complete(const char *zSql){ int sqlite3_complete16(const void *zSql){ sqlite3_value *pVal; char const *zSql8; - int rc = SQLITE_NOMEM; + int rc; #ifndef SQLITE_OMIT_AUTOINIT rc = sqlite3_initialize(); From d62c0f4c2daa03886116576b65866bfedb2e6ed6 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 9 Apr 2015 13:34:29 +0000 Subject: [PATCH 10/26] Add the "sqldiff" utility program. FossilOrigin-Name: 88da5bf5d2c4f848dbd4b5ffb1539abfbbdaff18 --- Makefile.in | 3 + Makefile.msc | 3 + main.mk | 4 + manifest | 17 +- manifest.uuid | 2 +- tool/sqldiff.c | 783 +++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 803 insertions(+), 9 deletions(-) create mode 100644 tool/sqldiff.c diff --git a/Makefile.in b/Makefile.in index 2177488f9b..295a6bc9c1 100644 --- a/Makefile.in +++ b/Makefile.in @@ -536,6 +536,9 @@ sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h -o $@ $(TOP)/src/shell.c libsqlite3.la \ $(LIBREADLINE) $(TLIBS) -rpath "$(libdir)" +sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h + $(LTLINK) -o $@ $(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) + mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c $(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \ $(TLIBS) -rpath "$(libdir)" diff --git a/Makefile.msc b/Makefile.msc index 5330f8962f..b49a3eb0e1 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1154,6 +1154,9 @@ sqlite3.exe: $(TOP)\src\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\src\shell.c \ /link /pdb:sqlite3sh.pdb $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS) +sqldiff.exe: $(TOP)\tool\sqldiff.c sqlite3.c sqlite3.h + $(LTLINK) $(TOP)\tool\sqldiff.c sqlite3.c + mptester.exe: $(TOP)\mptest\mptest.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h $(LTLINK) $(SHELL_COMPILE_OPTS) $(TOP)\mptest\mptest.c \ /link $(LTLINKOPTS) $(LTLIBPATHS) $(SHELL_LINK_OPTS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS) diff --git a/main.mk b/main.mk index 57bb35c486..c5328dc6c7 100644 --- a/main.mk +++ b/main.mk @@ -404,6 +404,10 @@ sqlite3$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h $(TOP)/src/shell.c \ libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB) +sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h + $(TCCX) -o sqldiff$(EXE) -DSQLITE_THREADSAFE=0 \ + $(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) $(THREADLIB) + mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c $(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \ $(TLIBS) $(THREADLIB) diff --git a/manifest b/manifest index 2af0d5f0d6..bcddd8c661 100644 --- a/manifest +++ b/manifest @@ -1,9 +1,9 @@ -C Remove\sa\svariable\sinitializion\sto\ssilence\sa\sharmless\scompiler\swarning. -D 2015-04-09T11:24:03.589 +C Add\sthe\s"sqldiff"\sutility\sprogram. +D 2015-04-09T13:34:29.580 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f -F Makefile.in 00d12636df7a5b08af09116bcd6c7bfd49b8b3b4 +F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 -F Makefile.msc a8d817fa486d8c88dfbd19ae6a6567d9d350de39 +F Makefile.msc fa6a6de11af800d89f86e8a4266fd40a46008347 F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858 F README.md d58e3bebc0a4145e0f2a87994015fdb575a8e866 F VERSION 319eb1ced4b4d17a67730f2b7b85f15c1346cb60 @@ -152,7 +152,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 997eee18387a3e69394f2f948c9c6ccf079655a4 +F main.mk ddffac494a82d42772df9fe30d3a78acf4f7cb41 F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 @@ -1239,6 +1239,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c +F tool/sqldiff.c 9c1c1e0aef974f1ad52aa720440a8a105d24d6f0 F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43 F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f @@ -1249,7 +1250,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 8a8ffc862e96f57aa698f93de10dee28e69f6e09 -R 94d9923532f03d2c01923395a653f609 +P 79861adbef8998c0f23e160543af8212d5546cd0 +R 55392413d804c3fa91206c94bb3d11f7 U drh -Z 1ec7205940b0e152091a81dfbeda06fb +Z a808bd48a859f116c92ef95210be5fe3 diff --git a/manifest.uuid b/manifest.uuid index acb9c7faab..32da2f232b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -79861adbef8998c0f23e160543af8212d5546cd0 \ No newline at end of file +88da5bf5d2c4f848dbd4b5ffb1539abfbbdaff18 \ No newline at end of file diff --git a/tool/sqldiff.c b/tool/sqldiff.c new file mode 100644 index 0000000000..9aa68caaa9 --- /dev/null +++ b/tool/sqldiff.c @@ -0,0 +1,783 @@ +/* +** 2015-04-06 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This is a utility problem that computes the differences in content +** between two SQLite databases. +*/ +#include +#include +#include +#include +#include +#include "sqlite3.h" + +/* +** All global variables are gathered into the "g" singleton. +*/ +struct GlobalVars { + const char *zArgv0; /* Name of program */ + int bSchemaOnly; /* Only show schema differences */ + unsigned fDebug; /* Debug flags */ + sqlite3 *db; /* The database connection */ +} g; + +/* +** Allowed values for g.fDebug +*/ +#define DEBUG_COLUMN_NAMES 0x000001 +#define DEBUG_DIFF_SQL 0x000002 + +/* +** Dynamic string object +*/ +typedef struct Str Str; +struct Str { + char *z; /* Text of the string */ + int nAlloc; /* Bytes allocated in z[] */ + int nUsed; /* Bytes actually used in z[] */ +}; + +/* +** Initialize a Str object +*/ +static void strInit(Str *p){ + p->z = 0; + p->nAlloc = 0; + p->nUsed = 0; +} + +/* +** Print an error resulting from faulting command-line arguments and +** abort the program. +*/ +static void cmdlineError(const char *zFormat, ...){ + va_list ap; + fprintf(stderr, "%s: ", g.zArgv0); + va_start(ap, zFormat); + vfprintf(stderr, zFormat, ap); + va_end(ap); + fprintf(stderr, "\n\"%s --help\" for more help\n", g.zArgv0); + exit(1); +} + +/* +** Print an error message for an error that occurs at runtime, then +** abort the program. +*/ +static void runtimeError(const char *zFormat, ...){ + va_list ap; + fprintf(stderr, "%s: ", g.zArgv0); + va_start(ap, zFormat); + vfprintf(stderr, zFormat, ap); + va_end(ap); + fprintf(stderr, "\n"); + exit(1); +} + +/* +** Free all memory held by a Str object +*/ +static void strFree(Str *p){ + sqlite3_free(p->z); + strInit(p); +} + +/* +** Add formatted text to the end of a Str object +*/ +static void strPrintf(Str *p, const char *zFormat, ...){ + int nNew; + for(;;){ + if( p->z ){ + va_list ap; + va_start(ap, zFormat); + sqlite3_vsnprintf(p->nAlloc-p->nUsed, p->z+p->nUsed, zFormat, ap); + va_end(ap); + nNew = (int)strlen(p->z + p->nUsed); + }else{ + nNew = p->nAlloc; + } + if( p->nUsed+nNew < p->nAlloc-1 ){ + p->nUsed += nNew; + break; + } + p->nAlloc = p->nAlloc*2 + 1000; + p->z = sqlite3_realloc(p->z, p->nAlloc); + if( p->z==0 ) runtimeError("out of memory"); + } +} + + + +/* Safely quote an SQL identifier. Use the minimum amount of transformation +** necessary to allow the string to be used with %s. +** +** Space to hold the returned string is obtained from sqlite3_malloc(). The +** caller is responsible for ensuring this space is freed when no longer +** needed. +*/ +static char *safeId(const char *zId){ + /* All SQLite keywords, in alphabetical order */ + static const char *azKeywords[] = { + "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS", + "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY", + "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT", + "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE", + "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE", + "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH", + "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN", + "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF", + "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", + "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", + "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL", + "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA", + "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP", + "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT", + "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP", + "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE", + "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE", + "WITH", "WITHOUT", + }; + int lwr, upr, mid, c, i, x; + for(i=x=0; (c = zId[i])!=0; i++){ + if( !isalpha(c) && c!='_' ){ + if( i>0 && isdigit(c) ){ + x++; + }else{ + return sqlite3_mprintf("\"%w\"", zId); + } + } + } + if( x ) return sqlite3_mprintf("%s", zId); + lwr = 0; + upr = sizeof(azKeywords)/sizeof(azKeywords[0]) - 1; + while( lwr<=upr ){ + mid = (lwr+upr)/2; + c = sqlite3_stricmp(azKeywords[mid], zId); + if( c==0 ) return sqlite3_mprintf("\"%w\"", zId); + if( c<0 ){ + lwr = mid+1; + }else{ + upr = mid-1; + } + } + return sqlite3_mprintf("%s", zId); +} + +/* +** Prepare a new SQL statement. Print an error and abort if anything +** goes wrong. +*/ +static sqlite3_stmt *db_vprepare(const char *zFormat, va_list ap){ + char *zSql; + int rc; + sqlite3_stmt *pStmt; + + zSql = sqlite3_vmprintf(zFormat, ap); + if( zSql==0 ) runtimeError("out of memory"); + rc = sqlite3_prepare_v2(g.db, zSql, -1, &pStmt, 0); + if( rc ){ + runtimeError("SQL statement error: %s\n\"%s\"", sqlite3_errmsg(g.db), + zSql); + } + sqlite3_free(zSql); + return pStmt; +} +static sqlite3_stmt *db_prepare(const char *zFormat, ...){ + va_list ap; + sqlite3_stmt *pStmt; + va_start(ap, zFormat); + pStmt = db_vprepare(zFormat, ap); + va_end(ap); + return pStmt; +} + +/* +** Free a list of strings +*/ +static void namelistFree(char **az){ + if( az ){ + int i; + for(i=0; az[i]; i++) sqlite3_free(az[i]); + sqlite3_free(az); + } +} + +/* +** Return a list of column names for the table zDb.zTab. Space to +** old the list is obtained from malloc() and should released by calling +** namelistFree() when no longer needed. +** +** Primary key columns are listed first, followed by data columns. The +** "primary key" in the previous sentence is the true primary key - the +** rowid or INTEGER PRIMARY KEY for ordinary tables or the declared +** PRIMARY KEY for WITHOUT ROWID tables. The number of columns in the +** primary key is returned in *pNPkey. +** +** If the table is a rowid table for which the rowid is inaccessible, +** then this routine returns a NULL pointer. +** +** Examples: +** CREATE TABLE t1(a INT UNIQUE, b INTEGER, c TEXT, PRIMARY KEY(c)); +** *pnPKey = 1; +** az = { "rowid", "a", "b", "c", 0 } +** +** CREATE TABLE t2(a INT UNIQUE, b INTEGER, c TEXT, PRIMARY KEY(b)); +** *pnPKey = 1; +** az = { "b", "a", "c", 0 } +** +** CREATE TABLE t3(x,y,z,PRIMARY KEY(y,z)); +** *pnPKey = 1 +** az = { "rowid", "x", "y", "z", 0 } +** +** CREATE TABLE t4(x,y,z,PRIMARY KEY(y,z)) WITHOUT ROWID; +** *pnPKey = 2 +** az = { "y", "z", "x", 0 } +** +** CREATE TABLE t5(rowid,_rowid_,oid); +** az = 0 // The rowid is not accessible +*/ +static char **columnNames(const char *zDb, const char *zTab, int *pnPKey){ + char **az = 0; + int naz = 0; + sqlite3_stmt *pStmt; + char *zPkIdxName = 0; /* Name of the PRIMARY KEY index */ + int truePk = 0; /* PRAGMA table_info indentifies the true PK */ + int nPK = 0; /* Number of PRIMARY KEY columns */ + int i, j; + + pStmt = db_prepare("PRAGMA %s.index_list=%Q", zDb, zTab); + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + if( sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,3),"pk")==0 ){ + zPkIdxName = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1)); + break; + } + } + sqlite3_finalize(pStmt); + if( zPkIdxName ){ + int nKey = 0; + int nCol = 0; + truePk = 0; + pStmt = db_prepare("PRAGMA %s.index_xinfo=%Q", zDb, zPkIdxName); + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + nCol++; + if( sqlite3_column_int(pStmt,5) ){ nKey++; continue; } + if( sqlite3_column_int(pStmt,1)>=0 ) truePk = 1; + } + if( nCol==nKey ) truePk = 1; + if( truePk ){ + nPK = nKey; + }else{ + nPK = 1; + } + sqlite3_finalize(pStmt); + sqlite3_free(zPkIdxName); + }else{ + truePk = 1; + nPK = 1; + } + *pnPKey = nPK; + naz = nPK; + az = sqlite3_malloc( sizeof(char*)*(nPK+1) ); + if( az==0 ) runtimeError("out of memory"); + memset(az, 0, sizeof(char*)*(nPK+1)); + pStmt = db_prepare("PRAGMA %s.table_info=%Q", zDb, zTab); + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + int iPKey; + if( truePk && (iPKey = sqlite3_column_int(pStmt,5))>0 ){ + az[iPKey-1] = safeId((char*)sqlite3_column_text(pStmt,1)); + }else{ + az = sqlite3_realloc(az, sizeof(char*)*(naz+2) ); + if( az==0 ) runtimeError("out of memory"); + az[naz++] = safeId((char*)sqlite3_column_text(pStmt,1)); + } + } + sqlite3_finalize(pStmt); + if( az ) az[naz] = 0; + if( az[0]==0 ){ + const char *azRowid[] = { "rowid", "_rowid_", "oid" }; + for(i=0; i=naz ){ + az[0] = sqlite3_mprintf("%s", azRowid[i]); + break; + } + } + if( az[0]==0 ){ + for(i=1; inPk2 ){ + zSep = "SELECT "; + for(i=0; i Date: Thu, 9 Apr 2015 13:40:18 +0000 Subject: [PATCH 11/26] Fix comment typos in the sqldiff.c utility program. FossilOrigin-Name: 32ab2bb990746a84f5944e3cf428fb2dff3628da --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/sqldiff.c | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index bcddd8c661..f4f4fa2b88 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\s"sqldiff"\sutility\sprogram. -D 2015-04-09T13:34:29.580 +C Fix\scomment\stypos\sin\sthe\ssqldiff.c\sutility\sprogram. +D 2015-04-09T13:40:18.767 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -1239,7 +1239,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c -F tool/sqldiff.c 9c1c1e0aef974f1ad52aa720440a8a105d24d6f0 +F tool/sqldiff.c a28d17d824bc80940c2d67b2cf85a387c461dc97 F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43 F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f @@ -1250,7 +1250,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 79861adbef8998c0f23e160543af8212d5546cd0 -R 55392413d804c3fa91206c94bb3d11f7 +P 88da5bf5d2c4f848dbd4b5ffb1539abfbbdaff18 +R df929ff4fd13763291be7acc0214ee00 U drh -Z a808bd48a859f116c92ef95210be5fe3 +Z 41493ba4ef878730b46175333abd9329 diff --git a/manifest.uuid b/manifest.uuid index 32da2f232b..91e566d270 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -88da5bf5d2c4f848dbd4b5ffb1539abfbbdaff18 \ No newline at end of file +32ab2bb990746a84f5944e3cf428fb2dff3628da \ No newline at end of file diff --git a/tool/sqldiff.c b/tool/sqldiff.c index 9aa68caaa9..2b982e914a 100644 --- a/tool/sqldiff.c +++ b/tool/sqldiff.c @@ -214,14 +214,14 @@ static void namelistFree(char **az){ /* ** Return a list of column names for the table zDb.zTab. Space to -** old the list is obtained from malloc() and should released by calling -** namelistFree() when no longer needed. +** hold the list is obtained from sqlite3_malloc() and should released +** using namelistFree() when no longer needed. ** ** Primary key columns are listed first, followed by data columns. The ** "primary key" in the previous sentence is the true primary key - the ** rowid or INTEGER PRIMARY KEY for ordinary tables or the declared ** PRIMARY KEY for WITHOUT ROWID tables. The number of columns in the -** primary key is returned in *pNPkey. +** primary key is returned in *pnPkey. ** ** If the table is a rowid table for which the rowid is inaccessible, ** then this routine returns a NULL pointer. From 3875becf3559a1129da2eca84491f11ab7b308d8 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 9 Apr 2015 16:30:56 +0000 Subject: [PATCH 12/26] Remove two pointless assert() statements. This should silence harmless compiler warnings reported at [https://bugzilla.mozilla.org/show_bug.cgi?id=1152845] FossilOrigin-Name: 83b342a44ffc9ea07dc4d59f2866cefc68ee4f13 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/build.c | 1 - src/trigger.c | 1 - 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index f4f4fa2b88..a4817bdb6c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\scomment\stypos\sin\sthe\ssqldiff.c\sutility\sprogram. -D 2015-04-09T13:40:18.767 +C Remove\stwo\spointless\sassert()\sstatements.\s\sThis\sshould\ssilence\sharmless\ncompiler\swarnings\sreported\sat\s\n[https://bugzilla.mozilla.org/show_bug.cgi?id=1152845] +D 2015-04-09T16:30:56.502 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -176,7 +176,7 @@ F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 F src/btree.c 2caf598165f3608fde8abac2b243826616ce54b7 F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1 F src/btreeInt.h 973a22a6fd61350b454ad614832b1f0a5e25a1e4 -F src/build.c 0419bba592c22f6d00e6d57a2ca7136720d02c1a +F src/build.c 4a6d573cd5f77812f32d343134b429046946d560 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575 F src/ctime.c 98f89724adc891a1a4c655bee04e33e716e05887 @@ -288,7 +288,7 @@ F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481 F src/tokenize.c a8d270b06e5f709930f7b67cf70a847969cb5bf3 -F src/trigger.c 25571661fdeae8c7f975ff40ffec205520a3f92f +F src/trigger.c 69a91bed7c94e46223e37ffccfeeb35e34b999ac F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c F src/util.c 98a7627ca48ad3265b6940915a1d08355eb3fc7e @@ -1250,7 +1250,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 88da5bf5d2c4f848dbd4b5ffb1539abfbbdaff18 -R df929ff4fd13763291be7acc0214ee00 +P 32ab2bb990746a84f5944e3cf428fb2dff3628da +R 37f01a89c55b4805b0a5cf101a377c7c U drh -Z 41493ba4ef878730b46175333abd9329 +Z 80169060600c5dd4d547a3dab7f7d969 diff --git a/manifest.uuid b/manifest.uuid index 91e566d270..341851e55f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -32ab2bb990746a84f5944e3cf428fb2dff3628da \ No newline at end of file +83b342a44ffc9ea07dc4d59f2866cefc68ee4f13 \ No newline at end of file diff --git a/src/build.c b/src/build.c index fcf96bd42c..e01e2427f1 100644 --- a/src/build.c +++ b/src/build.c @@ -3776,7 +3776,6 @@ void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){ void sqlite3SrcListShiftJoinType(SrcList *p){ if( p ){ int i; - assert( p->a || p->nSrc==0 ); for(i=p->nSrc-1; i>0; i--){ p->a[i].jointype = p->a[i-1].jointype; } diff --git a/src/trigger.c b/src/trigger.c index d2e7b5a1e6..ed152d2a8a 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -680,7 +680,6 @@ static SrcList *targetSrcList( pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0); if( pSrc ){ assert( pSrc->nSrc>0 ); - assert( pSrc->a!=0 ); iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema); if( iDb==0 || iDb>=2 ){ sqlite3 *db = pParse->db; From a37591cdd10ead51ed87a43aeeb9f83312636fd1 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 9 Apr 2015 18:14:03 +0000 Subject: [PATCH 13/26] Add the --primarykey option to the sqldiff tool, which causes it to use the schema-defined PRIMARY KEY. FossilOrigin-Name: 5063f9070afde9374ea0f2bc338fee840d8b3dd4 --- manifest | 12 +++--- manifest.uuid | 2 +- tool/sqldiff.c | 112 ++++++++++++++++++++++++++++++++----------------- 3 files changed, 80 insertions(+), 46 deletions(-) diff --git a/manifest b/manifest index a4817bdb6c..d6f8442010 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\stwo\spointless\sassert()\sstatements.\s\sThis\sshould\ssilence\sharmless\ncompiler\swarnings\sreported\sat\s\n[https://bugzilla.mozilla.org/show_bug.cgi?id=1152845] -D 2015-04-09T16:30:56.502 +C Add\sthe\s--primarykey\soption\sto\sthe\ssqldiff\stool,\swhich\scauses\sit\sto\suse\sthe\nschema-defined\sPRIMARY\sKEY. +D 2015-04-09T18:14:03.130 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -1239,7 +1239,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c -F tool/sqldiff.c a28d17d824bc80940c2d67b2cf85a387c461dc97 +F tool/sqldiff.c 9334ebc767dda9e02b904d4cbbd31cf8aaba3ca5 F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43 F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f @@ -1250,7 +1250,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 32ab2bb990746a84f5944e3cf428fb2dff3628da -R 37f01a89c55b4805b0a5cf101a377c7c +P 83b342a44ffc9ea07dc4d59f2866cefc68ee4f13 +R 80b4d61d5d12e62d07bcaa502c23a21f U drh -Z 80169060600c5dd4d547a3dab7f7d969 +Z 965913d93d231505652de01e91883fad diff --git a/manifest.uuid b/manifest.uuid index 341851e55f..fda938f72a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -83b342a44ffc9ea07dc4d59f2866cefc68ee4f13 \ No newline at end of file +5063f9070afde9374ea0f2bc338fee840d8b3dd4 \ No newline at end of file diff --git a/tool/sqldiff.c b/tool/sqldiff.c index 2b982e914a..28b66b2c37 100644 --- a/tool/sqldiff.c +++ b/tool/sqldiff.c @@ -26,6 +26,7 @@ struct GlobalVars { const char *zArgv0; /* Name of program */ int bSchemaOnly; /* Only show schema differences */ + int bSchemaPK; /* Use the schema-defined PK, not the true PK */ unsigned fDebug; /* Debug flags */ sqlite3 *db; /* The database connection */ } g; @@ -217,27 +218,34 @@ static void namelistFree(char **az){ ** hold the list is obtained from sqlite3_malloc() and should released ** using namelistFree() when no longer needed. ** -** Primary key columns are listed first, followed by data columns. The -** "primary key" in the previous sentence is the true primary key - the -** rowid or INTEGER PRIMARY KEY for ordinary tables or the declared -** PRIMARY KEY for WITHOUT ROWID tables. The number of columns in the -** primary key is returned in *pnPkey. +** Primary key columns are listed first, followed by data columns. +** The number of columns in the primary key is returned in *pnPkey. ** -** If the table is a rowid table for which the rowid is inaccessible, +** Normally, the "primary key" in the previous sentence is the true +** primary key - the rowid or INTEGER PRIMARY KEY for ordinary tables +** or the declared PRIMARY KEY for WITHOUT ROWID tables. However, if +** the g.bSchemaPK flag is set, then the schema-defined PRIMARY KEY is +** used in all cases. In that case, entries that have NULL values in +** any of their primary key fields will be excluded from the analysis. +** +** If the primary key for a table is the rowid but rowid is inaccessible, ** then this routine returns a NULL pointer. ** ** Examples: ** CREATE TABLE t1(a INT UNIQUE, b INTEGER, c TEXT, PRIMARY KEY(c)); ** *pnPKey = 1; -** az = { "rowid", "a", "b", "c", 0 } +** az = { "rowid", "a", "b", "c", 0 } // Normal case +** az = { "c", "a", "b", 0 } // g.bSchemaPK==1 ** ** CREATE TABLE t2(a INT UNIQUE, b INTEGER, c TEXT, PRIMARY KEY(b)); ** *pnPKey = 1; ** az = { "b", "a", "c", 0 } ** ** CREATE TABLE t3(x,y,z,PRIMARY KEY(y,z)); -** *pnPKey = 1 -** az = { "rowid", "x", "y", "z", 0 } +** *pnPKey = 1 // Normal case +** az = { "rowid", "x", "y", "z", 0 } // Normal case +** *pnPKey = 2 // g.bSchemaPK==1 +** az = { "y", "x", "z", 0 } // g.bSchemaPK==1 ** ** CREATE TABLE t4(x,y,z,PRIMARY KEY(y,z)) WITHOUT ROWID; ** *pnPKey = 2 @@ -247,50 +255,72 @@ static void namelistFree(char **az){ ** az = 0 // The rowid is not accessible */ static char **columnNames(const char *zDb, const char *zTab, int *pnPKey){ - char **az = 0; - int naz = 0; - sqlite3_stmt *pStmt; + char **az = 0; /* List of column names to be returned */ + int naz = 0; /* Number of entries in az[] */ + sqlite3_stmt *pStmt; /* SQL statement being run */ char *zPkIdxName = 0; /* Name of the PRIMARY KEY index */ - int truePk = 0; /* PRAGMA table_info indentifies the true PK */ + int truePk = 0; /* PRAGMA table_info indentifies the PK to use */ int nPK = 0; /* Number of PRIMARY KEY columns */ - int i, j; + int i, j; /* Loop counters */ - pStmt = db_prepare("PRAGMA %s.index_list=%Q", zDb, zTab); - while( SQLITE_ROW==sqlite3_step(pStmt) ){ - if( sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,3),"pk")==0 ){ - zPkIdxName = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1)); - break; - } - } - sqlite3_finalize(pStmt); - if( zPkIdxName ){ - int nKey = 0; - int nCol = 0; - truePk = 0; - pStmt = db_prepare("PRAGMA %s.index_xinfo=%Q", zDb, zPkIdxName); + if( g.bSchemaPK==0 ){ + /* Normal case: Figure out what the true primary key is for the table. + ** * For WITHOUT ROWID tables, the true primary key is the same as + ** the schema PRIMARY KEY, which is guaranteed to be present. + ** * For rowid tables with an INTEGER PRIMARY KEY, the true primary + ** key is the INTEGER PRIMARY KEY. + ** * For all other rowid tables, the rowid is the true primary key. + */ + pStmt = db_prepare("PRAGMA %s.index_list=%Q", zDb, zTab); while( SQLITE_ROW==sqlite3_step(pStmt) ){ - nCol++; - if( sqlite3_column_int(pStmt,5) ){ nKey++; continue; } - if( sqlite3_column_int(pStmt,1)>=0 ) truePk = 1; - } - if( nCol==nKey ) truePk = 1; - if( truePk ){ - nPK = nKey; - }else{ - nPK = 1; + if( sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,3),"pk")==0 ){ + zPkIdxName = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1)); + break; + } } sqlite3_finalize(pStmt); - sqlite3_free(zPkIdxName); + if( zPkIdxName ){ + int nKey = 0; + int nCol = 0; + truePk = 0; + pStmt = db_prepare("PRAGMA %s.index_xinfo=%Q", zDb, zPkIdxName); + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + nCol++; + if( sqlite3_column_int(pStmt,5) ){ nKey++; continue; } + if( sqlite3_column_int(pStmt,1)>=0 ) truePk = 1; + } + if( nCol==nKey ) truePk = 1; + if( truePk ){ + nPK = nKey; + }else{ + nPK = 1; + } + sqlite3_finalize(pStmt); + sqlite3_free(zPkIdxName); + }else{ + truePk = 1; + nPK = 1; + } + pStmt = db_prepare("PRAGMA %s.table_info=%Q", zDb, zTab); }else{ + /* The g.bSchemaPK==1 case: Use whatever primary key is declared + ** in the schema. The "rowid" will still be used as the primary key + ** if the table definition does not contain a PRIMARY KEY. + */ + nPK = 0; + pStmt = db_prepare("PRAGMA %s.table_info=%Q", zDb, zTab); + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + if( sqlite3_column_int(pStmt,5)>0 ) nPK++; + } + sqlite3_reset(pStmt); + if( nPK==0 ) nPK = 1; truePk = 1; - nPK = 1; } *pnPKey = nPK; naz = nPK; az = sqlite3_malloc( sizeof(char*)*(nPK+1) ); if( az==0 ) runtimeError("out of memory"); memset(az, 0, sizeof(char*)*(nPK+1)); - pStmt = db_prepare("PRAGMA %s.table_info=%Q", zDb, zTab); while( SQLITE_ROW==sqlite3_step(pStmt) ){ int iPKey; if( truePk && (iPKey = sqlite3_column_int(pStmt,5))>0 ){ @@ -692,6 +722,7 @@ static void showHelp(void){ printf( "Output SQL text that would transform DB1 into DB2.\n" "Options:\n" +" --primarykey Use schema-defined PRIMARY KEYs\n" " --schema Show only differences in the schema\n" " --table TAB Show only differences in table TAB\n" ); @@ -720,6 +751,9 @@ int main(int argc, char **argv){ showHelp(); return 0; }else + if( strcmp(z,"primarykey")==0 ){ + g.bSchemaPK = 1; + }else if( strcmp(z,"schema")==0 ){ g.bSchemaOnly = 1; }else From 2139d252ddcaeb2e162b04694b912cb0b2148d4f Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 9 Apr 2015 19:39:54 +0000 Subject: [PATCH 14/26] Fix incorrect column names in UPDATE statements generated by the sqldiff utility. FossilOrigin-Name: ee53b46011852e27db23708387fe1e918cc8284c --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/sqldiff.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index d6f8442010..5b339e5c39 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\s--primarykey\soption\sto\sthe\ssqldiff\stool,\swhich\scauses\sit\sto\suse\sthe\nschema-defined\sPRIMARY\sKEY. -D 2015-04-09T18:14:03.130 +C Fix\sincorrect\scolumn\snames\sin\sUPDATE\sstatements\sgenerated\sby\sthe\ssqldiff\nutility. +D 2015-04-09T19:39:54.853 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -1239,7 +1239,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c -F tool/sqldiff.c 9334ebc767dda9e02b904d4cbbd31cf8aaba3ca5 +F tool/sqldiff.c 050763654cb28d23c4d9516deb348c8632e432cd F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43 F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f @@ -1250,7 +1250,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 83b342a44ffc9ea07dc4d59f2866cefc68ee4f13 -R 80b4d61d5d12e62d07bcaa502c23a21f +P 5063f9070afde9374ea0f2bc338fee840d8b3dd4 +R b81a13af06affec3f4deb7b3b6092ef8 U drh -Z 965913d93d231505652de01e91883fad +Z 7a24354f8d3816810c976cc3a62d01ee diff --git a/manifest.uuid b/manifest.uuid index fda938f72a..56fcea9bbf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5063f9070afde9374ea0f2bc338fee840d8b3dd4 \ No newline at end of file +ee53b46011852e27db23708387fe1e918cc8284c \ No newline at end of file diff --git a/tool/sqldiff.c b/tool/sqldiff.c index 28b66b2c37..53c5977ed4 100644 --- a/tool/sqldiff.c +++ b/tool/sqldiff.c @@ -658,7 +658,7 @@ static void diff_one_table(const char *zTab){ zSep = " SET"; for(i=nPk+1; i Date: Fri, 10 Apr 2015 07:55:07 +0000 Subject: [PATCH 15/26] Do not allow virtual table constructors to be called recursively. FossilOrigin-Name: 0a72726da21581ab16cb3e964bd825b8f2e931e4 --- ext/fts3/fts3.c | 8 ++++++-- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/vtab.c | 33 +++++++++++++++++++++++++-------- test/fts4content.test | 18 ++++++++++++++++-- 5 files changed, 57 insertions(+), 22 deletions(-) diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index 7a15379b83..42b9663a1b 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -1019,7 +1019,8 @@ static int fts3ContentColumns( const char *zTbl, /* Name of content table */ const char ***pazCol, /* OUT: Malloc'd array of column names */ int *pnCol, /* OUT: Size of array *pazCol */ - int *pnStr /* OUT: Bytes of string content */ + int *pnStr, /* OUT: Bytes of string content */ + char **pzErr /* OUT: error message */ ){ int rc = SQLITE_OK; /* Return code */ char *zSql; /* "SELECT *" statement on zTbl */ @@ -1030,6 +1031,9 @@ static int fts3ContentColumns( rc = SQLITE_NOMEM; }else{ rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); + if( rc!=SQLITE_OK ){ + *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); + } } sqlite3_free(zSql); @@ -1281,7 +1285,7 @@ static int fts3InitVtab( if( nCol==0 ){ sqlite3_free((void*)aCol); aCol = 0; - rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString); + rc = fts3ContentColumns(db, argv[1], zContent,&aCol,&nCol,&nString,pzErr); /* If a languageid= option was specified, remove the language id ** column from the aCol[] array. */ diff --git a/manifest b/manifest index 5b339e5c39..b5170f2282 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sincorrect\scolumn\snames\sin\sUPDATE\sstatements\sgenerated\sby\sthe\ssqldiff\nutility. -D 2015-04-09T19:39:54.853 +C Do\snot\sallow\svirtual\stable\sconstructors\sto\sbe\scalled\srecursively. +D 2015-04-10T07:55:07.186 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -78,7 +78,7 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51 F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314 F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d -F ext/fts3/fts3.c 23bd9d37a777342f5c22a648e9b4b005dde9e58f +F ext/fts3/fts3.c 57d863c3bd360e575ecc293570af7c9b0bdd2209 F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe F ext/fts3/fts3Int.h 394858c12a17740f7a1f6bd372c4606d4425a8d1 F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365 @@ -302,7 +302,7 @@ F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90 F src/vdbemem.c c0dc81285b7571b0a31c40f17846fe2397ec1cd9 F src/vdbesort.c 919717d7599fa31d343ec28bffd0f9e91a4ff5f6 F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010 -F src/vtab.c 62d49237bd8f3be4863815a39387b0f9897fa5e1 +F src/vtab.c ff722a886ed61e2e2889ee221b0a4f6dcaabb8e1 F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb F src/wal.c 878c8e1a51cb2ec45c395d26b7d5cd9e1a098e4a F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 @@ -606,7 +606,7 @@ F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d F test/fts3varint.test 752c08ed5d32c5d7dc211b056f4ed68a76b7e36e F test/fts4aa.test 10aac8e9d62c7357590acfabe3fad01e9a9ce1cb F test/fts4check.test 74d77f6cdb768ac49df5afda575cef14ae3d239a -F test/fts4content.test 2e7252557d6d24afa101d9ba1de710d6140e6d06 +F test/fts4content.test abb0c77bc3da3df64fec72e00844d2257a90025d F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01 F test/fts4growth.test df10fde9f47cf5c71861e63fd8efcd573c4f7e53 F test/fts4growth2.test 2f063be1902a73cd087355837c52fed42ac11a5d @@ -1250,7 +1250,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 5063f9070afde9374ea0f2bc338fee840d8b3dd4 -R b81a13af06affec3f4deb7b3b6092ef8 -U drh -Z 7a24354f8d3816810c976cc3a62d01ee +P ee53b46011852e27db23708387fe1e918cc8284c +R 7e9242555b174ae9f2c42129917fe80c +U dan +Z a71357da8ab26f740f6d9ebc28389132 diff --git a/manifest.uuid b/manifest.uuid index 56fcea9bbf..6d3ce3f223 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ee53b46011852e27db23708387fe1e918cc8284c \ No newline at end of file +0a72726da21581ab16cb3e964bd825b8f2e931e4 \ No newline at end of file diff --git a/src/vtab.c b/src/vtab.c index 23f49bafce..d17aa147de 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -24,6 +24,8 @@ struct VtabCtx { VTable *pVTable; /* The virtual table being constructed */ Table *pTab; /* The Table object to which the virtual table belongs */ + VtabCtx *pPrior; /* Parent context (if any) */ + int bDeclared; /* True after sqlite3_declare_vtab() is called */ }; /* @@ -487,15 +489,27 @@ static int vtabCallConstructor( int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**), char **pzErr ){ - VtabCtx sCtx, *pPriorCtx; + VtabCtx sCtx; VTable *pVTable; int rc; const char *const*azArg = (const char *const*)pTab->azModuleArg; int nArg = pTab->nModuleArg; char *zErr = 0; - char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName); + char *zModuleName; int iDb; + VtabCtx *pCtx; + /* Check that the virtual-table is not already being initialized */ + for(pCtx=db->pVtabCtx; pCtx; pCtx=pCtx->pPrior){ + if( pCtx->pTab==pTab ){ + *pzErr = sqlite3MPrintf(db, + "vtable constructor called recursively: %s", pTab->zName + ); + return SQLITE_LOCKED; + } + } + + zModuleName = sqlite3MPrintf(db, "%s", pTab->zName); if( !zModuleName ){ return SQLITE_NOMEM; } @@ -516,11 +530,13 @@ static int vtabCallConstructor( assert( xConstruct ); sCtx.pTab = pTab; sCtx.pVTable = pVTable; - pPriorCtx = db->pVtabCtx; + sCtx.pPrior = db->pVtabCtx; + sCtx.bDeclared = 0; db->pVtabCtx = &sCtx; rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); - db->pVtabCtx = pPriorCtx; + db->pVtabCtx = sCtx.pPrior; if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; + assert( sCtx.pTab==pTab ); if( SQLITE_OK!=rc ){ if( zErr==0 ){ @@ -536,7 +552,7 @@ static int vtabCallConstructor( memset(pVTable->pVtab, 0, sizeof(pVTable->pVtab[0])); pVTable->pVtab->pModule = pMod->pModule; pVTable->nRef = 1; - if( sCtx.pTab ){ + if( sCtx.bDeclared==0 ){ const char *zFormat = "vtable constructor did not declare schema: %s"; *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName); sqlite3VtabUnlock(pVTable); @@ -706,8 +722,8 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){ ** virtual table module. */ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ + VtabCtx *pCtx = db->pVtabCtx; Parse *pParse; - int rc = SQLITE_OK; Table *pTab; char *zErr = 0; @@ -718,11 +734,12 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ } #endif sqlite3_mutex_enter(db->mutex); - if( !db->pVtabCtx || !(pTab = db->pVtabCtx->pTab) ){ + if( !pCtx || pCtx->bDeclared ){ sqlite3Error(db, SQLITE_MISUSE); sqlite3_mutex_leave(db->mutex); return SQLITE_MISUSE_BKPT; } + pTab = pCtx->pTab; assert( (pTab->tabFlags & TF_Virtual)!=0 ); pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); @@ -745,7 +762,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ pParse->pNewTable->nCol = 0; pParse->pNewTable->aCol = 0; } - db->pVtabCtx->pTab = 0; + pCtx->bDeclared = 1; }else{ sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); diff --git a/test/fts4content.test b/test/fts4content.test index 6b2cd3cc8e..481c6ec008 100644 --- a/test/fts4content.test +++ b/test/fts4content.test @@ -48,6 +48,9 @@ ifcapable !fts3 { # # 9.* - Test using content=xxx where xxx is a virtual table. # +# 11.* - Test that circular references (e.g. "t1(content=t1)") are +# detected. +# do_execsql_test 1.1.1 { CREATE TABLE t1(a, b, c); @@ -406,7 +409,7 @@ do_execsql_test 5.1.7 { # do_catchsql_test 6.1.1 { CREATE VIRTUAL TABLE ft7 USING fts4(content=t7); -} {1 {vtable constructor failed: ft7}} +} {1 {no such table: main.t7}} do_execsql_test 6.2.1 { CREATE TABLE t7(one, two); @@ -433,7 +436,7 @@ do_execsql_test 6.2.3 { } do_catchsql_test 6.2.4 { SELECT * FROM ft7; -} {1 {vtable constructor failed: ft7}} +} {1 {no such table: main.t7}} do_execsql_test 6.2.5 { CREATE TABLE t7(x, y); INSERT INTO t7 VALUES('A B', 'B A'); @@ -622,4 +625,15 @@ do_execsql_test 10.7 { {...c d [e] f g...} } +#------------------------------------------------------------------------- +# Test cases 11.* +# +reset_db + +do_catchsql_test 11.1 { + CREATE VIRTUAL TABLE x1 USING fts4(content=x1); +} {1 {vtable constructor called recursively: x1}} + + finish_test + From e918aaba981efb7ec5cca88ca8ae4d509ca84367 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 10 Apr 2015 12:04:57 +0000 Subject: [PATCH 16/26] Fix foreign key CASCADE for cases where the parent key is an INTEGER PRIMARY KEY and the parent table contains other columns named "rowid", "_rowid_", and "oid". FossilOrigin-Name: ed3cbaab6ad49b0cb5b17e44def26c866919387a --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/fkey.c | 3 ++- test/fkey2.test | 4 ++-- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index b5170f2282..b70c671a51 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sallow\svirtual\stable\sconstructors\sto\sbe\scalled\srecursively. -D 2015-04-10T07:55:07.186 +C Fix\sforeign\skey\sCASCADE\sfor\scases\swhere\sthe\sparent\skey\sis\san\sINTEGER\sPRIMARY\nKEY\sand\sthe\sparent\stable\scontains\sother\scolumns\snamed\s"rowid",\s"_rowid_",\nand\s"oid". +D 2015-04-10T12:04:57.414 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -184,7 +184,7 @@ F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac F src/delete.c 37964e6c1d73ff49cbea9ff690c9605fb15f600e F src/expr.c d09dac67d53c78880ba31d56e8ba2be3a6490553 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c e0444b61bed271a76840cbe6182df93a9baa3f12 +F src/fkey.c 3343d551a8d810782257244fb33f2ce191493c39 F src/func.c 1414c24c873c48796ad45942257a179a423ba42f F src/global.c 4f77cadbc5427d00139ba43d0f3979804cbb700e F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 @@ -505,7 +505,7 @@ F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7 F test/filectrl.test 14fa712e42c4cb791e09dfd58a6a03efb47ef13a F test/filefmt.test cb34663f126cbc2d358af552dcaf5c72769b0146 F test/fkey1.test e1d1fa84cde579185ea01358436839703e415a5b -F test/fkey2.test 1db212cda86b0d3ce72714001f7b6381c321341c +F test/fkey2.test 223c624e7eccee21e89c98d4d127ac88d774b940 F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49 F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d F test/fkey5.test 56bcb5a6e8b725b17febc267fb041a6695e86853 @@ -1250,7 +1250,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 ee53b46011852e27db23708387fe1e918cc8284c -R 7e9242555b174ae9f2c42129917fe80c -U dan -Z a71357da8ab26f740f6d9ebc28389132 +P 0a72726da21581ab16cb3e964bd825b8f2e931e4 +R b2dde8f542352409005b61e29f91d905 +U drh +Z 7c6c1370c12f07a8520590c209ac9901 diff --git a/manifest.uuid b/manifest.uuid index 6d3ce3f223..33b43c8925 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0a72726da21581ab16cb3e964bd825b8f2e931e4 \ No newline at end of file +ed3cbaab6ad49b0cb5b17e44def26c866919387a \ No newline at end of file diff --git a/src/fkey.c b/src/fkey.c index fa148ba6a3..3e4b752e86 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -1184,7 +1184,8 @@ static Trigger *fkActionTrigger( iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; assert( iFromCol>=0 ); - tToCol.z = pIdx ? pTab->aCol[pIdx->aiColumn[i]].zName : "oid"; + assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKeynCol) ); + tToCol.z = pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName; tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName; tToCol.n = sqlite3Strlen30(tToCol.z); diff --git a/test/fkey2.test b/test/fkey2.test index 53b90dc91c..8b2871e5a6 100644 --- a/test/fkey2.test +++ b/test/fkey2.test @@ -746,10 +746,10 @@ do_test fkey2-10.2.2 { drop_all_tables do_test fkey2-11.1.1 { execsql { - CREATE TABLE t1(a INTEGER PRIMARY KEY, b); + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, rowid, _rowid_, oid); CREATE TABLE t2(c, d, FOREIGN KEY(c) REFERENCES t1(a) ON UPDATE CASCADE); - INSERT INTO t1 VALUES(10, 100); + INSERT INTO t1 VALUES(10, 100, 'abc', 'def', 'ghi'); INSERT INTO t2 VALUES(10, 100); UPDATE t1 SET a = 15; SELECT * FROM t2; From 4e23536e56f283bd8cf0d787dd9e76e7176435f0 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 10 Apr 2015 16:05:33 +0000 Subject: [PATCH 17/26] In sqlite3_declare_vtab(), avoid accessing the database structure until after the "api-armour" safety-check has completed and the db mutex has been obtained. FossilOrigin-Name: 860e4f8a94901d451fac3954960c1d2f589e8882 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vtab.c | 3 ++- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index b70c671a51..a4b1b68367 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sforeign\skey\sCASCADE\sfor\scases\swhere\sthe\sparent\skey\sis\san\sINTEGER\sPRIMARY\nKEY\sand\sthe\sparent\stable\scontains\sother\scolumns\snamed\s"rowid",\s"_rowid_",\nand\s"oid". -D 2015-04-10T12:04:57.414 +C In\ssqlite3_declare_vtab(),\savoid\saccessing\sthe\sdatabase\sstructure\suntil\safter\sthe\s"api-armour"\ssafety-check\shas\scompleted\sand\sthe\sdb\smutex\shas\sbeen\sobtained. +D 2015-04-10T16:05:33.033 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -302,7 +302,7 @@ F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90 F src/vdbemem.c c0dc81285b7571b0a31c40f17846fe2397ec1cd9 F src/vdbesort.c 919717d7599fa31d343ec28bffd0f9e91a4ff5f6 F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010 -F src/vtab.c ff722a886ed61e2e2889ee221b0a4f6dcaabb8e1 +F src/vtab.c 9ca557215e8591ceb66e0b7c0a579c6df1e54b2d F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb F src/wal.c 878c8e1a51cb2ec45c395d26b7d5cd9e1a098e4a F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 @@ -1250,7 +1250,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 0a72726da21581ab16cb3e964bd825b8f2e931e4 -R b2dde8f542352409005b61e29f91d905 -U drh -Z 7c6c1370c12f07a8520590c209ac9901 +P ed3cbaab6ad49b0cb5b17e44def26c866919387a +R f962720dd8c90d63a1a200cd065fa312 +U dan +Z 666766483214acd3a759f5cb43f45fc3 diff --git a/manifest.uuid b/manifest.uuid index 33b43c8925..909c5925c5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ed3cbaab6ad49b0cb5b17e44def26c866919387a \ No newline at end of file +860e4f8a94901d451fac3954960c1d2f589e8882 \ No newline at end of file diff --git a/src/vtab.c b/src/vtab.c index d17aa147de..9629a00dcb 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -722,7 +722,7 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){ ** virtual table module. */ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ - VtabCtx *pCtx = db->pVtabCtx; + VtabCtx *pCtx; Parse *pParse; int rc = SQLITE_OK; Table *pTab; @@ -734,6 +734,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ } #endif sqlite3_mutex_enter(db->mutex); + pCtx = db->pVtabCtx; if( !pCtx || pCtx->bDeclared ){ sqlite3Error(db, SQLITE_MISUSE); sqlite3_mutex_leave(db->mutex); From 83e63dc3857dbb2220090ef0cd3541cef2189aa3 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 10 Apr 2015 19:41:18 +0000 Subject: [PATCH 18/26] Work toward adding the --changeset option to the sqldiff utility program. Changes are incomplete. This is an incremental check-in. FossilOrigin-Name: 463e38d765f9d055b63792a8ea15c3782657b07f --- manifest | 17 ++++--- manifest.uuid | 2 +- tool/sqldiff.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 135 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index a4b1b68367..c7c3d03725 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\ssqlite3_declare_vtab(),\savoid\saccessing\sthe\sdatabase\sstructure\suntil\safter\sthe\s"api-armour"\ssafety-check\shas\scompleted\sand\sthe\sdb\smutex\shas\sbeen\sobtained. -D 2015-04-10T16:05:33.033 +C Work\stoward\sadding\sthe\s--changeset\soption\sto\sthe\ssqldiff\sutility\sprogram.\nChanges\sare\sincomplete.\s\sThis\sis\san\sincremental\scheck-in. +D 2015-04-10T19:41:18.818 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -1239,7 +1239,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c -F tool/sqldiff.c 050763654cb28d23c4d9516deb348c8632e432cd +F tool/sqldiff.c 3e6f54359a070089ed0d11456e8868dcd3f20e94 F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43 F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f @@ -1250,7 +1250,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 ed3cbaab6ad49b0cb5b17e44def26c866919387a -R f962720dd8c90d63a1a200cd065fa312 -U dan -Z 666766483214acd3a759f5cb43f45fc3 +P 860e4f8a94901d451fac3954960c1d2f589e8882 +R 6c8da3b8e133d42c3c0048f2d2a47a98 +T *branch * sqldiff-changeset +T *sym-sqldiff-changeset * +T -sym-trunk * +U drh +Z b58ac33ed90e0dd7edcdd56b18b68a1d diff --git a/manifest.uuid b/manifest.uuid index 909c5925c5..324240a04b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -860e4f8a94901d451fac3954960c1d2f589e8882 \ No newline at end of file +463e38d765f9d055b63792a8ea15c3782657b07f \ No newline at end of file diff --git a/tool/sqldiff.c b/tool/sqldiff.c index 53c5977ed4..2b46353535 100644 --- a/tool/sqldiff.c +++ b/tool/sqldiff.c @@ -714,6 +714,113 @@ end_diff_one_table: return; } +/* +** Generate a CHANGESET for all differences from main.zTab to aux.zTab. +*/ +static void changeset_one_table(const char *zTab, FILE *out){ + sqlite3_stmt *pStmt; /* SQL statment */ + char *zId = safeId(zTab); /* Escaped name of the table */ + char **azCol = 0; /* List of escaped column names */ + int nCol = 0; /* Number of columns */ + int *aiFlg = 0; /* 0 if column is not part of PK */ + int *aiPk = 0; /* Column numbers for each PK column */ + int nPk = 0; /* Number of PRIMARY KEY columns */ + Str sql; /* SQL for the diff query */ + int i; /* Loop counter */ + const char *zSep; /* List separator */ + + pStmt = db_prepare( + "SELECT A.sql=B.sql FROM main.sqlite_master A, aux.sqlite_master B" + " WHERE A.name=%Q AND B.name=%Q", zTab, zTab + ); + if( SQLITE_ROW==sqlite3_step(pStmt) ){ + if( sqlite3_column_int(pStmt,0)==0 ){ + runtimeError("schema changes for table %s", safeId(zTab)); + } + }else{ + runtimeError("table %s missing from one or both databases", safeId(zTab)); + } + sqlite3_finalize(pStmt); + pStmt = db_prepare("PRAGMA main.table_info=%Q", zTab); + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + nCol++; + azCol = sqlite3_realloc(azCol, sizeof(char*)*nCol); + if( azCol==0 ) runtimeError("out of memory"); + aiFlg = sqlite3_realloc(aiFlg, sizeof(int)*nCol); + if( aiFlg==0 ) runtimeError("out of memory"); + azCol[nCol-1] = safeId((const char*)sqlite3_column_text(pStmt,1)); + aiFlg[nCol-1] = i = sqlite3_column_int(pStmt,5); + if( i>0 ){ + if( i>nPk ){ + nPk = i; + aiPk = sqlite3_realloc(aiPk, sizeof(int)*nPk); + if( aiPk==0 ) runtimeError("out of memory"); + } + aiPk[i-1] = nCol-1; + } + } + sqlite3_finalize(pStmt); + if( nPk==0 ) goto end_changeset_one_table; + strInit(&sql); + if( nCol>nPk ){ + strPrintf(&sql, "SELECT 1"); /* Changes to non-PK columns */ + for(i=0; i0 ) sqlite3_free(azCol[--nCol]); + sqlite3_free(azCol); + sqlite3_free(aiPk); + sqlite3_free(zId); +} + /* ** Print sketchy documentation for this utility program */ @@ -722,6 +829,7 @@ static void showHelp(void){ printf( "Output SQL text that would transform DB1 into DB2.\n" "Options:\n" +" --changeset FILE Write a CHANGESET into FILE\n" " --primarykey Use schema-defined PRIMARY KEYs\n" " --schema Show only differences in the schema\n" " --table TAB Show only differences in table TAB\n" @@ -737,6 +845,7 @@ int main(int argc, char **argv){ char *zSql; sqlite3_stmt *pStmt; char *zTab = 0; + FILE *out = 0; g.zArgv0 = argv[0]; for(i=1; i Date: Fri, 10 Apr 2015 21:16:11 +0000 Subject: [PATCH 19/26] Minor build enhancements for MSVC. FossilOrigin-Name: 40c417a7efb17221cec4a0a703863854bcab8db2 --- Makefile.msc | 6 ++++-- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/msvc.h | 1 + 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index b49a3eb0e1..7ea110e7dd 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -42,8 +42,8 @@ DYNAMIC_SHELL = 0 # !IFNDEF NO_WARN !IF $(USE_FULLWARN)!=0 -NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4152 -wd4189 -wd4206 -wd4210 -NO_WARN = $(NO_WARN) -wd4232 -wd4244 -wd4305 -wd4306 -wd4702 -wd4706 +NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206 +NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4244 -wd4305 -wd4306 -wd4702 -wd4706 !ENDIF !ENDIF @@ -453,11 +453,13 @@ RCC = $(RCC) -I$(TOP)\ext\rtree # options are necessary in order to allow debugging symbols to # work correctly with Visual Studio when using the amalgamation. # +!IFNDEF MKSQLITE3C_ARGS !IF $(DEBUG)>1 MKSQLITE3C_ARGS = --linemacros !ELSE MKSQLITE3C_ARGS = !ENDIF +!ENDIF # Define -DNDEBUG to compile without debugging (i.e., for production usage) # Omitting the define will cause extra debugging code to be inserted and diff --git a/manifest b/manifest index a4b1b68367..d9f7505d75 100644 --- a/manifest +++ b/manifest @@ -1,9 +1,9 @@ -C In\ssqlite3_declare_vtab(),\savoid\saccessing\sthe\sdatabase\sstructure\suntil\safter\sthe\s"api-armour"\ssafety-check\shas\scompleted\sand\sthe\sdb\smutex\shas\sbeen\sobtained. -D 2015-04-10T16:05:33.033 +C Minor\sbuild\senhancements\sfor\sMSVC. +D 2015-04-10T21:16:11.659 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 -F Makefile.msc fa6a6de11af800d89f86e8a4266fd40a46008347 +F Makefile.msc 0078f5781538e07ea38683439f38d5f5ab79ab6e F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858 F README.md d58e3bebc0a4145e0f2a87994015fdb575a8e866 F VERSION 319eb1ced4b4d17a67730f2b7b85f15c1346cb60 @@ -203,7 +203,7 @@ F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534 F src/mem5.c 61eeb90134f9a5be6c2e68d8daae7628b25953fb F src/memjournal.c 3eb2c0b51adbd869cb6a44780323f05fa904dc85 -F src/msvc.h e78002098966e39b2fd9915bd70b7bc3ec8398b7 +F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495 F src/mutex.c 19bf9acba69ca2f367c3761080f8a9f0cf4670a8 F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 F src/mutex_noop.c 529bab0743c3321c940f32c3464de494fd38cfa9 @@ -1250,7 +1250,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 ed3cbaab6ad49b0cb5b17e44def26c866919387a -R f962720dd8c90d63a1a200cd065fa312 -U dan -Z 666766483214acd3a759f5cb43f45fc3 +P 860e4f8a94901d451fac3954960c1d2f589e8882 +R d724f3837aa2139b84d99a7758232948 +U mistachkin +Z add6515d666dc387abaf063a7b8f0157 diff --git a/manifest.uuid b/manifest.uuid index 909c5925c5..5d2f5e3cb5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -860e4f8a94901d451fac3954960c1d2f589e8882 \ No newline at end of file +40c417a7efb17221cec4a0a703863854bcab8db2 \ No newline at end of file diff --git a/src/msvc.h b/src/msvc.h index 4508e6941f..01ebf2b46f 100644 --- a/src/msvc.h +++ b/src/msvc.h @@ -20,6 +20,7 @@ #pragma warning(disable : 4055) #pragma warning(disable : 4100) #pragma warning(disable : 4127) +#pragma warning(disable : 4130) #pragma warning(disable : 4152) #pragma warning(disable : 4189) #pragma warning(disable : 4206) From 4a33507f60067a91786065a082a28fd781753aa3 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 11 Apr 2015 02:08:48 +0000 Subject: [PATCH 20/26] Detect and report oversized records constructed from multiple zeroblobs. FossilOrigin-Name: 9e139afd92116ebc593114ed63b57c8f469653f6 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/vdbe.c | 4 ++-- test/zeroblob.test | 9 +++++++++ 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index d9f7505d75..71aafa2cb1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\sbuild\senhancements\sfor\sMSVC. -D 2015-04-10T21:16:11.659 +C Detect\sand\sreport\soversized\srecords\sconstructed\sfrom\smultiple\szeroblobs. +D 2015-04-11T02:08:48.265 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -293,7 +293,7 @@ F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c F src/util.c 98a7627ca48ad3265b6940915a1d08355eb3fc7e F src/vacuum.c 9460b9de7b2d4e34b0d374894aa6c8a0632be8ec -F src/vdbe.c 86ae6f4774410868af41bd839b72b7081ff03e78 +F src/vdbe.c 06cc2cf42daf8b0c397f69a6fb1818124f3cd93a F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3 F src/vdbeInt.h 9cbaa84f53ddd2d09a0cf61a94337a3a035d08a0 F src/vdbeapi.c 583d56b129dd27f12bed518270de9ebe521e6a75 @@ -1194,7 +1194,7 @@ F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a F test/without_rowid5.test 61256715b686359df48ca1742db50cc7e3e7b862 F test/without_rowid6.test db0dbf03c49030aa3c1ba5f618620334bd2baf5f F test/wordcount.c 9915e06cb33d8ca8109b8700791afe80d305afda -F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688 +F test/zeroblob.test fb3c0e4ab172d386954deda24c03f500e121d80d F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac F tool/build-all-msvc.bat 72e05bc8deca39a547884485c086b915f50a91ed x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 @@ -1250,7 +1250,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 860e4f8a94901d451fac3954960c1d2f589e8882 -R d724f3837aa2139b84d99a7758232948 -U mistachkin -Z add6515d666dc387abaf063a7b8f0157 +P 40c417a7efb17221cec4a0a703863854bcab8db2 +R fd7ff5723f566045f2ba0751ddce0467 +U drh +Z f6419661cff2a502b477cceb45bb8fdd diff --git a/manifest.uuid b/manifest.uuid index 5d2f5e3cb5..c8b77b78ce 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -40c417a7efb17221cec4a0a703863854bcab8db2 \ No newline at end of file +9e139afd92116ebc593114ed63b57c8f469653f6 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index f2de90d14c..8e7247a1e8 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2578,7 +2578,7 @@ case OP_MakeRecord: { u64 nData; /* Number of bytes of data space */ int nHdr; /* Number of bytes of header space */ i64 nByte; /* Data space required for this record */ - int nZero; /* Number of zero bytes at the end of the record */ + i64 nZero; /* Number of zero bytes at the end of the record */ int nVarint; /* Number of bytes in a varint */ u32 serial_type; /* Type field */ Mem *pData0; /* First field to be combined into the record */ @@ -2670,7 +2670,7 @@ case OP_MakeRecord: { if( nVarintdb->aLimit[SQLITE_LIMIT_LENGTH] ){ + if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } diff --git a/test/zeroblob.test b/test/zeroblob.test index f4a1950836..e70fd0b748 100644 --- a/test/zeroblob.test +++ b/test/zeroblob.test @@ -255,5 +255,14 @@ do_test zeroblob-9.8 { db eval {SELECT zeroblob(2) IN (zeroblob(2))} } {1} +# Oversized zeroblob records +# +do_test zeroblob-10.1 { + db eval { + CREATE TABLE t10(a,b,c); + } + catchsql {INSERT INTO t10 VALUES(zeroblob(1e9),zeroblob(1e9),zeroblob(1e9))} +} {1 {string or blob too big}} + finish_test From 2813bde0280a022b7adb2f1d79033aa8de7358a5 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 11 Apr 2015 11:44:27 +0000 Subject: [PATCH 21/26] Do not assume an index contains unique entries unless it is declared UNIQUE and NOT NULL is specified for all columns. Fix for [7b4fee9f6c]. FossilOrigin-Name: e3b1f625518edc0e925116668dca5d25c3232b59 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/where.c | 2 +- test/null.test | 17 +++++++++++++++++ 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 71aafa2cb1..55283a01c9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Detect\sand\sreport\soversized\srecords\sconstructed\sfrom\smultiple\szeroblobs. -D 2015-04-11T02:08:48.265 +C Do\snot\sassume\san\sindex\scontains\sunique\sentries\sunless\sit\sis\sdeclared\sUNIQUE\sand\sNOT\sNULL\sis\sspecified\sfor\sall\scolumns.\sFix\sfor\s[7b4fee9f6c]. +D 2015-04-11T11:44:27.202 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -307,7 +307,7 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb F src/wal.c 878c8e1a51cb2ec45c395d26b7d5cd9e1a098e4a F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804 -F src/where.c 85d832efa5ef57de542db7f430b72fecd3af8b38 +F src/where.c bd435b75b9de53e11b5eb561540e395041ac0cba F src/whereInt.h cbe4aa57326998d89e7698ca65bb7c28541d483c F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -768,7 +768,7 @@ F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161 F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934 F test/notnull.test f8fcf58669ddba79274daa2770d61dfad8274f62 -F test/null.test a8b09b8ed87852742343b33441a9240022108993 +F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3 F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1 F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394 F test/orderby1.test eb246e377612b21a418fbea57047ba8ea88aaa6b @@ -1250,7 +1250,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 40c417a7efb17221cec4a0a703863854bcab8db2 -R fd7ff5723f566045f2ba0751ddce0467 -U drh -Z f6419661cff2a502b477cceb45bb8fdd +P 9e139afd92116ebc593114ed63b57c8f469653f6 +R cb22563425ec3fdd92f04af95791ab8d +U dan +Z a8ae95b3c171e79da5c1dd8c91dd053d diff --git a/manifest.uuid b/manifest.uuid index c8b77b78ce..1f18603ac6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9e139afd92116ebc593114ed63b57c8f469653f6 \ No newline at end of file +e3b1f625518edc0e925116668dca5d25c3232b59 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 921e683d98..a96d9e5add 100644 --- a/src/where.c +++ b/src/where.c @@ -4781,7 +4781,7 @@ static int whereLoopAddBtreeIndex( }else if( eOp & (WO_EQ) ){ pNew->wsFlags |= WHERE_COLUMN_EQ; if( iCol<0 || (nInMul==0 && pNew->u.btree.nEq==pProbe->nKeyCol-1) ){ - if( iCol>=0 && !IsUniqueIndex(pProbe) ){ + if( iCol>=0 && pProbe->uniqNotNull==0 ){ pNew->wsFlags |= WHERE_UNQ_WANTED; }else{ pNew->wsFlags |= WHERE_ONEROW; diff --git a/test/null.test b/test/null.test index f3782a7531..e8eeb9740b 100644 --- a/test/null.test +++ b/test/null.test @@ -278,6 +278,23 @@ do_test null-8.15 { } } {1} +do_execsql_test null-9.1 { + CREATE TABLE t5(a, b, c); + CREATE UNIQUE INDEX t5ab ON t5(a, b); + + INSERT INTO t5 VALUES(1, NULL, 'one'); + INSERT INTO t5 VALUES(1, NULL, 'i'); + INSERT INTO t5 VALUES(NULL, 'x', 'two'); + INSERT INTO t5 VALUES(NULL, 'x', 'ii'); +} + +do_execsql_test null-9.2 { + SELECT * FROM t5 WHERE a = 1 AND b IS NULL; +} {1 {} one 1 {} i} + +do_execsql_test null-9.3 { + SELECT * FROM t5 WHERE a IS NULL AND b = 'x'; +} {{} x two {} x ii} finish_test From 8aad8c482ce0eac0fb9245722d2a63ea490d6818 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 11 Apr 2015 11:53:39 +0000 Subject: [PATCH 22/26] Update tests in whereD.test to account for the change in the previous commit. FossilOrigin-Name: da49700ca148d91e1b8863c2eb6ee79144e83ac9 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/whereD.test | 14 +++++++------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 55283a01c9..378036e42a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sassume\san\sindex\scontains\sunique\sentries\sunless\sit\sis\sdeclared\sUNIQUE\sand\sNOT\sNULL\sis\sspecified\sfor\sall\scolumns.\sFix\sfor\s[7b4fee9f6c]. -D 2015-04-11T11:44:27.202 +C Update\stests\sin\swhereD.test\sto\saccount\sfor\sthe\schange\sin\sthe\sprevious\scommit. +D 2015-04-11T11:53:39.984 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -1171,7 +1171,7 @@ F test/where9.test 729c3ba9b47e8f9f1aab96bae7dad2a524f1d1a2 F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5 F test/whereC.test d6f4ecd4fa2d9429681a5b22a25d2bda8e86ab8a -F test/whereD.test fd9120e262f9da3c45940f52aefeef4d15b904e5 +F test/whereD.test 9eba1f9b18e5b19a0b0bcaae5e8c037260195f2b F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7 F test/whereG.test 69f5ec4b15760a8c860f80e2d55525669390aab3 @@ -1250,7 +1250,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 9e139afd92116ebc593114ed63b57c8f469653f6 -R cb22563425ec3fdd92f04af95791ab8d +P e3b1f625518edc0e925116668dca5d25c3232b59 +R 7890e1f1fdfc32123135ecc1b57978ea U dan -Z a8ae95b3c171e79da5c1dd8c91dd053d +Z 68688658f813a09121106ccdd49ce975 diff --git a/manifest.uuid b/manifest.uuid index 1f18603ac6..f330c7ddcf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e3b1f625518edc0e925116668dca5d25c3232b59 \ No newline at end of file +da49700ca148d91e1b8863c2eb6ee79144e83ac9 \ No newline at end of file diff --git a/test/whereD.test b/test/whereD.test index db993040b0..17fdac7017 100644 --- a/test/whereD.test +++ b/test/whereD.test @@ -129,11 +129,11 @@ do_execsql_test 3.0 { do_searchcount_test 3.1 { SELECT a, b FROM t3 WHERE (a=1 AND b='one') OR (a=2 AND b='two') -} {1 one 2 two search 2} +} {1 one 2 two search 4} do_searchcount_test 3.2 { SELECT a, c FROM t3 WHERE (a=1 AND b='one') OR (a=2 AND b='two') -} {1 i 2 ii search 4} +} {1 i 2 ii search 6} do_searchcount_test 3.4.1 { SELECT y FROM t4 WHERE x='a' @@ -142,24 +142,24 @@ do_searchcount_test 3.4.2 { SELECT a, b FROM t3 WHERE (a=1 AND b=(SELECT y FROM t4 WHERE x='a')) OR (a=2 AND b='two') -} {1 one 2 two search 4} +} {1 one 2 two search 6} do_searchcount_test 3.4.3 { SELECT a, b FROM t3 WHERE (a=2 AND b='two') OR (a=1 AND b=(SELECT y FROM t4 WHERE x='a')) -} {2 two 1 one search 4} +} {2 two 1 one search 6} do_searchcount_test 3.4.4 { SELECT a, b FROM t3 WHERE (a=2 AND b=(SELECT y FROM t4 WHERE x='b')) OR (a=1 AND b=(SELECT y FROM t4 WHERE x='a')) -} {2 two 1 one search 6} +} {2 two 1 one search 8} do_searchcount_test 3.5.1 { SELECT a, b FROM t3 WHERE (a=1 AND b='one') OR rowid=4 -} {1 one 2 two search 2} +} {1 one 2 two search 3} do_searchcount_test 3.5.2 { SELECT a, c FROM t3 WHERE (a=1 AND b='one') OR rowid=4 -} {1 i 2 ii search 2} +} {1 i 2 ii search 3} # Ticket [d02e1406a58ea02d] (2012-10-04) # LEFT JOIN with an OR in the ON clause causes segfault From 697e5dba801332f9e412868c593b8f58fc713844 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 11 Apr 2015 12:07:40 +0000 Subject: [PATCH 23/26] First complete attempt to generate a working changeset. Still contains bugs. FossilOrigin-Name: 5611fa9bd5b8fd762d16ce9b0853c2e779a1a1b7 --- manifest | 15 ++++----- manifest.uuid | 2 +- tool/sqldiff.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 87 insertions(+), 17 deletions(-) diff --git a/manifest b/manifest index c7c3d03725..f2c0b806d6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Work\stoward\sadding\sthe\s--changeset\soption\sto\sthe\ssqldiff\sutility\sprogram.\nChanges\sare\sincomplete.\s\sThis\sis\san\sincremental\scheck-in. -D 2015-04-10T19:41:18.818 +C First\scomplete\sattempt\sto\sgenerate\sa\sworking\schangeset.\s\sStill\scontains\sbugs. +D 2015-04-11T12:07:40.414 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -1239,7 +1239,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c -F tool/sqldiff.c 3e6f54359a070089ed0d11456e8868dcd3f20e94 +F tool/sqldiff.c ed945df30d962d15d26188e33f7c5431cf197487 F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43 F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f @@ -1250,10 +1250,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 860e4f8a94901d451fac3954960c1d2f589e8882 -R 6c8da3b8e133d42c3c0048f2d2a47a98 -T *branch * sqldiff-changeset -T *sym-sqldiff-changeset * -T -sym-trunk * +P 463e38d765f9d055b63792a8ea15c3782657b07f +R c7ffcaee222b675f0ec3e43f31931e14 U drh -Z b58ac33ed90e0dd7edcdd56b18b68a1d +Z c4472641aefb50d8b597b0b444fecd27 diff --git a/manifest.uuid b/manifest.uuid index 324240a04b..4657a0c7e9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -463e38d765f9d055b63792a8ea15c3782657b07f \ No newline at end of file +5611fa9bd5b8fd762d16ce9b0853c2e779a1a1b7 \ No newline at end of file diff --git a/tool/sqldiff.c b/tool/sqldiff.c index 2b46353535..d166174440 100644 --- a/tool/sqldiff.c +++ b/tool/sqldiff.c @@ -714,6 +714,31 @@ end_diff_one_table: return; } +/* +** Write a 64-bit signed integer as a varint onto out +*/ +static void putsVarint(FILE *out, sqlite3_uint64 v){ + int i, n; + unsigned char buf[12], p[12]; + if( v & (((sqlite3_uint64)0xff000000)<<32) ){ + p[8] = (unsigned char)v; + v >>= 8; + for(i=7; i>=0; i--){ + p[i] = (unsigned char)((v & 0x7f) | 0x80); + v >>= 7; + } + fwrite(p, 8, 1, out); + }else{ + n = 9; + do{ + p[n--] = (unsigned char)((v & 0x7f) | 0x80); + v >>= 7; + }while( v!=0 ); + buf[9] &= 0x7f; + fwrite(buf+n+1, 9-n, 1, out); + } +} + /* ** Generate a CHANGESET for all differences from main.zTab to aux.zTab. */ @@ -726,7 +751,7 @@ static void changeset_one_table(const char *zTab, FILE *out){ int *aiPk = 0; /* Column numbers for each PK column */ int nPk = 0; /* Number of PRIMARY KEY columns */ Str sql; /* SQL for the diff query */ - int i; /* Loop counter */ + int i, j; /* Loop counters */ const char *zSep; /* List separator */ pStmt = db_prepare( @@ -763,7 +788,7 @@ static void changeset_one_table(const char *zTab, FILE *out){ if( nPk==0 ) goto end_changeset_one_table; strInit(&sql); if( nCol>nPk ){ - strPrintf(&sql, "SELECT 1"); /* Changes to non-PK columns */ + strPrintf(&sql, "SELECT %d", SQLITE_UPDATE); for(i=0; i=0; j-=8) putc((uX>>j)&0xff, out); + break; + case SQLITE_FLOAT: + rX = sqlite3_column_int64(pStmt,i); + memcpy(&uX, &rX, 8); + for(j=56; j>=0; j-=8) putc((uX>>j)&0xff, out); + break; + case SQLITE_TEXT: + iX = sqlite3_column_bytes(pStmt,i); + putsVarint(out, (sqlite3_uint64)iX); + fwrite(sqlite3_column_text(pStmt,i),1,iX,out); + break; + case SQLITE_BLOB: + iX = sqlite3_column_bytes(pStmt,i); + putsVarint(out, (sqlite3_uint64)iX); + fwrite(sqlite3_column_blob(pStmt,i),1,iX,out); + break; + case SQLITE_NULL: + break; + } + } + } + sqlite3_finalize(pStmt); end_changeset_one_table: while( nCol>0 ) sqlite3_free(azCol[--nCol]); From 6e42ce44db4d367c64c704f953e575d0f42310e5 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 11 Apr 2015 13:48:01 +0000 Subject: [PATCH 24/26] The --changeset option now appears to be working. FossilOrigin-Name: 1a2e2803920dcf64190d81d8a487d6c3c9bb28ee --- manifest | 12 ++-- manifest.uuid | 2 +- tool/sqldiff.c | 161 +++++++++++++++++++++++++++++++++++-------------- 3 files changed, 124 insertions(+), 51 deletions(-) diff --git a/manifest b/manifest index f2c0b806d6..336a1877e9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C First\scomplete\sattempt\sto\sgenerate\sa\sworking\schangeset.\s\sStill\scontains\sbugs. -D 2015-04-11T12:07:40.414 +C The\s--changeset\soption\snow\sappears\sto\sbe\sworking. +D 2015-04-11T13:48:01.693 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -1239,7 +1239,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c -F tool/sqldiff.c ed945df30d962d15d26188e33f7c5431cf197487 +F tool/sqldiff.c 51c05cc1435507736b8b5a41a0498016041b3e48 F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43 F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f @@ -1250,7 +1250,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 463e38d765f9d055b63792a8ea15c3782657b07f -R c7ffcaee222b675f0ec3e43f31931e14 +P 5611fa9bd5b8fd762d16ce9b0853c2e779a1a1b7 +R 907cf695d8fcffe3003a321f9aace7fc U drh -Z c4472641aefb50d8b597b0b444fecd27 +Z 3b5f839006775d8054dcfb8aab08f0fa diff --git a/manifest.uuid b/manifest.uuid index 4657a0c7e9..a5255d3652 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5611fa9bd5b8fd762d16ce9b0853c2e779a1a1b7 \ No newline at end of file +1a2e2803920dcf64190d81d8a487d6c3c9bb28ee \ No newline at end of file diff --git a/tool/sqldiff.c b/tool/sqldiff.c index d166174440..4455c582ef 100644 --- a/tool/sqldiff.c +++ b/tool/sqldiff.c @@ -719,7 +719,7 @@ end_diff_one_table: */ static void putsVarint(FILE *out, sqlite3_uint64 v){ int i, n; - unsigned char buf[12], p[12]; + unsigned char p[12]; if( v & (((sqlite3_uint64)0xff000000)<<32) ){ p[8] = (unsigned char)v; v >>= 8; @@ -734,8 +734,45 @@ static void putsVarint(FILE *out, sqlite3_uint64 v){ p[n--] = (unsigned char)((v & 0x7f) | 0x80); v >>= 7; }while( v!=0 ); - buf[9] &= 0x7f; - fwrite(buf+n+1, 9-n, 1, out); + p[9] &= 0x7f; + fwrite(p+n+1, 9-n, 1, out); + } +} + +/* +** Write an SQLite value onto out. +*/ +static void putValue(FILE *out, sqlite3_value *pVal){ + int iDType = sqlite3_value_type(pVal); + sqlite3_int64 iX; + double rX; + sqlite3_uint64 uX; + int j; + + putc(iDType, out); + switch( iDType ){ + case SQLITE_INTEGER: + iX = sqlite3_value_int64(pVal); + memcpy(&uX, &iX, 8); + for(j=56; j>=0; j-=8) putc((uX>>j)&0xff, out); + break; + case SQLITE_FLOAT: + rX = sqlite3_value_int64(pVal); + memcpy(&uX, &rX, 8); + for(j=56; j>=0; j-=8) putc((uX>>j)&0xff, out); + break; + case SQLITE_TEXT: + iX = sqlite3_value_bytes(pVal); + putsVarint(out, (sqlite3_uint64)iX); + fwrite(sqlite3_value_text(pVal),1,iX,out); + break; + case SQLITE_BLOB: + iX = sqlite3_value_bytes(pVal); + putsVarint(out, (sqlite3_uint64)iX); + fwrite(sqlite3_value_blob(pVal),1,iX,out); + break; + case SQLITE_NULL: + break; } } @@ -751,7 +788,7 @@ static void changeset_one_table(const char *zTab, FILE *out){ int *aiPk = 0; /* Column numbers for each PK column */ int nPk = 0; /* Number of PRIMARY KEY columns */ Str sql; /* SQL for the diff query */ - int i, j; /* Loop counters */ + int i, k; /* Loop counters */ const char *zSep; /* List separator */ pStmt = db_prepare( @@ -789,8 +826,14 @@ static void changeset_one_table(const char *zTab, FILE *out){ strInit(&sql); if( nCol>nPk ){ strPrintf(&sql, "SELECT %d", SQLITE_UPDATE); - for(i=0; i=0; j-=8) putc((uX>>j)&0xff, out); - break; - case SQLITE_FLOAT: - rX = sqlite3_column_int64(pStmt,i); - memcpy(&uX, &rX, 8); - for(j=56; j>=0; j-=8) putc((uX>>j)&0xff, out); - break; - case SQLITE_TEXT: - iX = sqlite3_column_bytes(pStmt,i); - putsVarint(out, (sqlite3_uint64)iX); - fwrite(sqlite3_column_text(pStmt,i),1,iX,out); - break; - case SQLITE_BLOB: - iX = sqlite3_column_bytes(pStmt,i); - putsVarint(out, (sqlite3_uint64)iX); - fwrite(sqlite3_column_blob(pStmt,i),1,iX,out); - break; - case SQLITE_NULL: - break; + switch( sqlite3_column_int(pStmt,0) ){ + case SQLITE_UPDATE: { + for(k=1, i=0; i Date: Sat, 11 Apr 2015 20:20:29 +0000 Subject: [PATCH 25/26] Fix a problem with sorting large amounts of partially ordered data. FossilOrigin-Name: acca97efda86a0c020854d2dd9da16f5879986b1 --- manifest | 17 ++++++++--------- manifest.uuid | 2 +- src/vdbesort.c | 9 ++------- test/orderby1.test | 29 +++++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/manifest b/manifest index 871fd87da4..e73c590925 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\s--changeset\soption\sto\sthe\ssqldiff\sutility\sprogram,\sfor\sgenerating\na\ssessions\schangeset\sfile\sinstead\sof\san\sSQL\sdiff. -D 2015-04-11T13:49:16.216 +C Fix\sa\sproblem\swith\ssorting\slarge\samounts\sof\spartially\sordered\sdata. +D 2015-04-11T20:20:29.810 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -300,7 +300,7 @@ F src/vdbeapi.c 583d56b129dd27f12bed518270de9ebe521e6a75 F src/vdbeaux.c 413dc496248ac18eb0c19e35e86bb1ffd47b8907 F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90 F src/vdbemem.c c0dc81285b7571b0a31c40f17846fe2397ec1cd9 -F src/vdbesort.c 919717d7599fa31d343ec28bffd0f9e91a4ff5f6 +F src/vdbesort.c a9d39d99969462908f50d09918791883c5b067ab F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010 F src/vtab.c 9ca557215e8591ceb66e0b7c0a579c6df1e54b2d F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb @@ -771,7 +771,7 @@ F test/notnull.test f8fcf58669ddba79274daa2770d61dfad8274f62 F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3 F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1 F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394 -F test/orderby1.test eb246e377612b21a418fbea57047ba8ea88aaa6b +F test/orderby1.test d69a2c99c023c85b014ece2cf691caec16a40d6d F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04 F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99 F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4 @@ -1250,8 +1250,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 da49700ca148d91e1b8863c2eb6ee79144e83ac9 1a2e2803920dcf64190d81d8a487d6c3c9bb28ee -R c078ada2bdea31973177a0bd82842009 -T +closed 1a2e2803920dcf64190d81d8a487d6c3c9bb28ee -U drh -Z 157b78d075c326a9e01bf8b58e910074 +P f9a3a8391c28cf13d76ec54f471735d35059acea +R 20d1ab6a886883435eefbe113ce65f82 +U dan +Z 26f0ad0889bc54d15cfec6237366d6c5 diff --git a/manifest.uuid b/manifest.uuid index 76f7b8530a..89b4e6fdf1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f9a3a8391c28cf13d76ec54f471735d35059acea \ No newline at end of file +acca97efda86a0c020854d2dd9da16f5879986b1 \ No newline at end of file diff --git a/src/vdbesort.c b/src/vdbesort.c index bbdafa8230..869ff4f2a3 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -887,30 +887,24 @@ static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){ */ static void vdbeSortSubtaskCleanup(sqlite3 *db, SortSubtask *pTask){ sqlite3DbFree(db, pTask->pUnpacked); - pTask->pUnpacked = 0; #if SQLITE_MAX_WORKER_THREADS>0 /* pTask->list.aMemory can only be non-zero if it was handed memory ** from the main thread. That only occurs SQLITE_MAX_WORKER_THREADS>0 */ if( pTask->list.aMemory ){ sqlite3_free(pTask->list.aMemory); - pTask->list.aMemory = 0; }else #endif { assert( pTask->list.aMemory==0 ); vdbeSorterRecordFree(0, pTask->list.pList); } - pTask->list.pList = 0; if( pTask->file.pFd ){ sqlite3OsCloseFree(pTask->file.pFd); - pTask->file.pFd = 0; - pTask->file.iEof = 0; } if( pTask->file2.pFd ){ sqlite3OsCloseFree(pTask->file2.pFd); - pTask->file2.pFd = 0; - pTask->file2.iEof = 0; } + memset(pTask, 0, sizeof(SortSubtask)); } #ifdef SQLITE_DEBUG_SORTER_THREADS @@ -1090,6 +1084,7 @@ void sqlite3VdbeSorterReset(sqlite3 *db, VdbeSorter *pSorter){ for(i=0; inTask; i++){ SortSubtask *pTask = &pSorter->aTask[i]; vdbeSortSubtaskCleanup(db, pTask); + pTask->pSorter = pSorter; } if( pSorter->list.aMemory==0 ){ vdbeSorterRecordFree(0, pSorter->list.pList); diff --git a/test/orderby1.test b/test/orderby1.test index 6674e32220..164c3f25db 100644 --- a/test/orderby1.test +++ b/test/orderby1.test @@ -495,5 +495,34 @@ do_execsql_test 7.0 { SELECT * FROM t7 WHERE a=?1 ORDER BY rowid; } {~/ORDER BY/} +#------------------------------------------------------------------------- +# Test a partial sort large enough to cause the sorter to spill data +# to disk. +# +reset_db +do_execsql_test 8.0 { + PRAGMA cache_size = 5; + CREATE TABLE t1(a, b); + CREATE INDEX i1 ON t1(a); +} + +do_eqp_test 8.1 { + SELECT * FROM t1 ORDER BY a, b; +} { + 0 0 0 {SCAN TABLE t1 USING INDEX i1} + 0 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY} +} + +do_execsql_test 8.2 { + WITH cnt(i) AS ( + SELECT 1 UNION ALL SELECT i+1 FROM cnt WHERE i<10000 + ) + INSERT INTO t1 SELECT i%2, randomblob(500) FROM cnt; +} + +do_test 8.3 { + db eval { SELECT * FROM t1 ORDER BY a, b } { incr res $a } + set res +} 5000 finish_test From 11b04817785a3d23789ca80829cc598840878946 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 12 Apr 2015 01:22:04 +0000 Subject: [PATCH 26/26] Avoid problems when a query has a GROUP BY and an ORDER BY but no FROM clause. FossilOrigin-Name: e527d96a1e098ade4e9d124b630a8c2ea2ac9b36 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/where.c | 2 +- test/orderby1.test | 3 +++ 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 17f4391705..7967b35884 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Optimizations\sfor\sVACUUM,\sCREATE\sINDEX\sand\ssome\scases\sof\sORDER\sBY. -D 2015-04-11T20:44:28.726 +C Avoid\sproblems\swhen\sa\squery\shas\sa\sGROUP\sBY\sand\san\sORDER\sBY\sbut\sno\sFROM\sclause. +D 2015-04-12T01:22:04.580 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -307,7 +307,7 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb F src/wal.c 878c8e1a51cb2ec45c395d26b7d5cd9e1a098e4a F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804 -F src/where.c bd435b75b9de53e11b5eb561540e395041ac0cba +F src/where.c 9952e4749f481707595692f2f13d3ce3b64ffdc8 F src/whereInt.h cbe4aa57326998d89e7698ca65bb7c28541d483c F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -771,7 +771,7 @@ F test/notnull.test f8fcf58669ddba79274daa2770d61dfad8274f62 F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3 F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1 F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394 -F test/orderby1.test d69a2c99c023c85b014ece2cf691caec16a40d6d +F test/orderby1.test 870e150450437d3980badbde3d0166b81d9e33f6 F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04 F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99 F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4 @@ -1250,7 +1250,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 acca97efda86a0c020854d2dd9da16f5879986b1 cf7590f607d94a120385576b538484ca738349e2 -R 4a3267783e1ce12038a61c7c4ca15ba8 -U dan -Z 05508ac040af16f75cf3f23dcdb1072a +P 79326d6eece926fd1c148b29f0b726208d8b44c0 +R b8a99417c5276ad65ad7b525e5ae16a3 +U drh +Z ba0a0070ee213de4cf49a8279f3da0ad diff --git a/manifest.uuid b/manifest.uuid index 695e755462..df7dea6773 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -79326d6eece926fd1c148b29f0b726208d8b44c0 \ No newline at end of file +e527d96a1e098ade4e9d124b630a8c2ea2ac9b36 \ No newline at end of file diff --git a/src/where.c b/src/where.c index a96d9e5add..42e950e41e 100644 --- a/src/where.c +++ b/src/where.c @@ -6241,7 +6241,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ pWInfo->revMask = pFrom->revLoop; } if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP) - && pWInfo->nOBSat==pWInfo->pOrderBy->nExpr + && pWInfo->nOBSat==pWInfo->pOrderBy->nExpr && nLoop>0 ){ Bitmask revMask = 0; int nOrder = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, diff --git a/test/orderby1.test b/test/orderby1.test index 164c3f25db..3e785c54e4 100644 --- a/test/orderby1.test +++ b/test/orderby1.test @@ -463,6 +463,9 @@ do_execsql_test 5.1 { do_execsql_test 5.2 { SELECT 5 UNION ALL SELECT 3 ORDER BY 1 } {3 5} +do_execsql_test 5.3 { + SELECT 986 AS x GROUP BY X ORDER BY X +} {986} # The following test (originally derived from a single test within fuzz.test) # verifies that a PseudoTable cursor is not closed prematurely in a deeply