-C Add\sthe\sSQLITE_BUG_COMPATIBLE_20160819\scompile-time\soption\sto\somit\sthe\serror\nmessage\swhen\san\sunrecognized\sargument\sis\sprovided\sto\sthe\sVACUUM\scommand.
-D 2017-02-18T13:47:11.181
+C Add\san\soptimization\sto\sOP_Column\sto\sspeed\sup\ssequential\sOP_Column\ninstructions\sthat\sread\searlier\sfields\sfrom\sthe\ssame\scursor.\sAttempt\sto\sreorder\nOP_Column\sopcodes\sso\sas\sto\stake\sadvantage\sof\sthis.
+D 2017-02-18T20:05:05.184
F Makefile.in edb6bcdd37748d2b1c3422ff727c748df7ffe918
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc a89ea37ab5928026001569f056973b9059492fe2
F src/date.c dc3f1391d9297f8c748132813aaffcb117090d6e
F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d
F src/delete.c 0d9d5549d42e79ce4d82ff1db1e6c81e36d2f67c
-F src/expr.c 8a29e9b72d4b642189999c41782cd6c5bc43512f
+F src/expr.c 980e4627f5d5efe8366ca5123e9d393e495a404c
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 2e9aabe1aee76273aff8a84ee92c464e095400ae
F src/func.c c67273e1ec08abbdcc14c189892a3ff6eeece86b
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c f9bc0de45a30a450da47b3766de00be89bf9be79
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
-F src/select.c d12f3539f80db38b09015561b569e0eb1c4b6c5f
+F src/select.c e32cc5c546d77c217d1b61b17eb953471c8bbd19
F src/shell.c bf976d5301be9d8a4c52852c97909cc9a41ee20d
F src/sqlite.h.in 751ff125eb159c8f92c182b8df980a5e4f50e966
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae
-F src/sqliteInt.h 46fe8e5aee3825d77fa771216ef263dc947030e7
+F src/sqliteInt.h e30c066962672158359575ddd550db8200107275
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
F src/tokenize.c 25ccc63ae2c4163933221f3181c9982b47cd08d2
F src/treeview.c 4e44ade3bfe59d82005039f72e09333ce2b4162c
F src/trigger.c c9f0810043b265724fdb1bdd466894f984dfc182
-F src/update.c 456d4a4656f8a03c2abc88a51b19172197400e58
+F src/update.c bcfda1d123d19e86479a619e37a2f3b5aaa978e5
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
F src/util.c ca8440ede81e155d15cff7c101654f60b55a9ae6
F src/vacuum.c 1fe4555cd8c9b263afb85b5b4ee3a4a4181ad569
-F src/vdbe.c 16f378640570c24442fd7191b136b5d6380f5c7b
-F src/vdbe.h 59998ffd71d7caa8886bc78dafaf8caeccd4c13c
-F src/vdbeInt.h 4e4b15b2e1330e1636e4e01974eab2b0b985092f
+F src/vdbe.c 337429082b858125a6dee0803a2140039a94ab07
+F src/vdbe.h 0a52f346f6c89ab144adc11d1c04e94f74425eaa
+F src/vdbeInt.h 6186ba2bd4d4299ada9c17a61a23761c4cb5757b
F src/vdbeapi.c 3e4a8893feeb78620f4aac4ac5b85d92255b97e1
-F src/vdbeaux.c 4122458d33318ab039c4b5da1ca4e7c9221c38e4
+F src/vdbeaux.c fb1d5bfb60ba6b75a964d91fe5d054cb3dd31839
F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9
F src/vdbemem.c 3b5a9a5b375458d3e12a50ae1aaa41eeec2175fd
F src/vdbesort.c eda25cb2d1727efca6f7862fea32b8aa33c0face
F src/walker.c 91a6df7435827e41cff6bb7df50ea00934ee78b0
F src/where.c 01baf58b72f3ddb7793cdee2871f751e3e09b35e
F src/whereInt.h c0b092180f04608d80c258174b0a14a1f9c8d02f
-F src/wherecode.c 677e95413c472c0b413023b6b69a47f40fce1b04
+F src/wherecode.c 373faba5f8df4d22cd3db9f239ec71a1d0c99e8b
F src/whereexpr.c 130cdd1a43af71b19755270fb1224874cf55158c
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 8cc9d74c176a78aeebfbb39198c21b5dd547ff52
-R 57839b570efd132c834489fe34d93e5e
-U drh
-Z 38cfd439ab0cfeae01cbf1d291727475
+P 491814272dce7e937b4734fcbc2ad69e12377b56
+R edee9ca5068aff62e1a1b155721f75af
+T *branch * sort-column-opcodes
+T *sym-sort-column-opcodes *
+T -sym-trunk *
+U dan
+Z b7f122691d1e00c6c9a153ed5456e504
-491814272dce7e937b4734fcbc2ad69e12377b56
\ No newline at end of file
+c1adf95958d5210bf9f89fc86d0f6fc6ce32c480
\ No newline at end of file
exprToRegister(pExpr, iMem);
}
+/*
+** Return the value of (*p1) - (*p2), as defined by the sort order described
+** in the comment above reorderColumnFetch().
+*/
+static int compareOpCode(VdbeOp *p1, VdbeOp *p2){
+ int res;
+
+ assert( p1->opcode==OP_Column || p1->opcode==OP_VColumn
+ || p1->opcode==OP_Copy || p1->opcode==OP_SCopy
+ || p1->opcode==OP_Rowid || p1->opcode==OP_RealAffinity
+ );
+ assert( p2->opcode==OP_Column || p2->opcode==OP_VColumn
+ || p2->opcode==OP_Copy || p2->opcode==OP_SCopy
+ || p2->opcode==OP_Rowid || p2->opcode==OP_RealAffinity
+ );
+
+ assert( OP_VColumn>OP_Column && OP_Rowid>OP_Column );
+ assert( OP_Column>OP_RealAffinity );
+ assert( OP_RealAffinity>OP_Copy && OP_RealAffinity>OP_SCopy );
+
+ res = (int)(p2->opcode) - (int)(p1->opcode);
+ if( res==0 ){
+ res = p1->p1 - p2->p1;
+ if( res==0 ){
+ res = p2->p2 - p1->p2;
+ }
+ }
+ return res;
+}
+
+/*
+** The VM instructions from iFirst to the current address were generated
+** in order to populate an array of registers with the results of a series
+** of TK_COLUMN expressions. This guarantees that the specified range
+** contains opcodes of the following types only:
+**
+** Rowid
+** Column
+** VColumn
+** RealAffinity
+** Copy
+** SCopy
+**
+** This function sorts the opcodes so all of the OP_Column appear in a
+** contiguous block, sorted by (p1, p2 DESC). The VDBE layer processes
+** OP_Column instructions in this order more efficiently.
+**
+** In practice, the array is sorted so that all instructions of each type
+** of opcode are arranged into a contiguous group. Given the following,
+** this is a safe re-ordering:
+**
+** * All Rowid, VColumn and Column instructions appear before all
+** RealAffinity instructions (that might operate on the result of
+** a VColumn or Column), and
+**
+** * All RealAffinity instructions occur before all Copy and SCopy
+** instructions (which might read a column-cache entry populated
+** by a prior Column+RealAffinity).
+*/
+static void reorderColumnFetch(sqlite3 *db, Vdbe *v, int iFirst){
+ int iEnd = sqlite3VdbeCurrentAddr(v);
+ int nOp = iEnd-iFirst;
+ if( nOp>1 ){
+ VdbeOp *aSpace = (VdbeOp*)sqlite3StackAllocRaw(db, sizeof(VdbeOp) * nOp);
+ if( aSpace ){
+ int sz;
+ VdbeOp *aOp = sqlite3VdbeGetOp(v, iFirst);
+ VdbeOp *a1 = aOp;
+ VdbeOp *a2 = aSpace;
+ for(sz=1; sz<nOp; sz=sz*2){
+ int i;
+ for(i=0; i<nOp; i+=(sz*2)){
+ /* Merge the two lists of sz elements each starting at a1[i] and
+ ** a1[i+sz] into a sz element list at a2[i]. */
+ int e1 = MIN(i+sz, nOp);
+ int e2 = MIN(i+sz*2, nOp);
+ int i2 = i+sz;
+ int i1 = i;
+ int iOut = i;
+
+ while( i1<e1 || i2<e2 ){
+ if( i1>=e1 || (i2<e2 && compareOpCode(&a1[i2], &a1[i1])<0) ){
+ a2[iOut++] = a1[i2++];
+ }else{
+ a2[iOut++] = a1[i1++];
+ }
+ }
+ }
+ SWAP(VdbeOp*, a1, a2);
+ }
+ if( a1!=aOp ){
+ memcpy(aOp, a1, sizeof(VdbeOp)*nOp);
+ }
+ sqlite3StackFree(db, aSpace);
+ }
+ }
+}
+
/*
** Generate code that pushes the value of every element of the given
** expression list into a sequence of registers beginning at target.
){
struct ExprList_item *pItem;
int i, j, n;
+ int iFirst = -1;
u8 copyOp = (flags & SQLITE_ECEL_DUP) ? OP_Copy : OP_SCopy;
Vdbe *v = pParse->pVdbe;
assert( pList!=0 );
if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR;
for(pItem=pList->a, i=0; i<n; i++, pItem++){
Expr *pExpr = pItem->pExpr;
+ if( iFirst>0 ){
+ if( pExpr->op!=TK_COLUMN ){
+ reorderColumnFetch(pParse->db, v, iFirst);
+ iFirst = -1;
+ }
+ }else{
+ if( pExpr->op==TK_COLUMN ) iFirst = sqlite3VdbeCurrentAddr(v);
+ }
if( (flags & SQLITE_ECEL_REF)!=0 && (j = pItem->u.x.iOrderByCol)>0 ){
if( flags & SQLITE_ECEL_OMITREF ){
i--;
}
}
}
+ if( iFirst>0 ) reorderColumnFetch(pParse->db, v, iFirst);
return n;
}
iSortTab = iTab;
bSeq = 1;
}
- for(i=0, iCol=nKey+bSeq; i<nSortData; i++){
- int iRead;
+ iCol = nKey+bSeq;
+ for(i=0; i<nSortData; i++){
+ if( aOutEx[i].u.x.iOrderByCol==0 ) iCol++;
+ }
+ for(i=nSortData-1; i>=0; i--){
+ if( aOutEx[i].u.x.iOrderByCol==0 ){
+ sqlite3VdbeAddOp3(v, OP_Column, iSortTab, --iCol, regRow+i);
+ VdbeComment((v, "%s", aOutEx[i].zName?aOutEx[i].zName:aOutEx[i].zSpan));
+ }
+ }
+ for(i=nSortData-1; i>=0; i--){
if( aOutEx[i].u.x.iOrderByCol ){
- iRead = aOutEx[i].u.x.iOrderByCol-1;
- }else{
- iRead = iCol++;
+ int iRead = aOutEx[i].u.x.iOrderByCol-1;
+ sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i);
+ VdbeComment((v, "%s", aOutEx[i].zName?aOutEx[i].zName:aOutEx[i].zSpan));
}
- sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i);
- VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan));
}
switch( eDest ){
case SRT_Table:
#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */
#define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */
+#define OPFLAG_CONTINUE 0x01
+
/*
* Each trigger present in the database schema is stored as an instance of
* struct Trigger.
newmask = sqlite3TriggerColmask(
pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
);
+#if 1
+ for(i=pTab->nCol-1; i>=0; i--){
+#else
for(i=0; i<pTab->nCol; i++){
+#endif
if( i==pTab->iPKey ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
}else{
}
}
-
/*
** Execute as much of a VDBE program as we can.
** This is the core of sqlite3_step().
if( pC->szRow>=aOffset[p2+1] ){
/* This is the common case where the desired content fits on the original
** page - where the content is not on an overflow page */
- zData = pC->aRow + aOffset[p2];
- if( t<12 ){
- sqlite3VdbeSerialGet(zData, t, pDest);
- }else{
- /* If the column value is a string, we need a persistent value, not
- ** a MEM_Ephem value. This branch is a fast short-cut that is equivalent
- ** to calling sqlite3VdbeSerialGet() and sqlite3VdbeDeephemeralize().
- */
- static const u16 aFlag[] = { MEM_Blob, MEM_Str|MEM_Term };
- pDest->n = len = (t-12)/2;
- pDest->enc = encoding;
- if( pDest->szMalloc < len+2 ){
- pDest->flags = MEM_Null;
- if( sqlite3VdbeMemGrow(pDest, len+2, 0) ) goto no_mem;
+ while( 1 ){
+ zData = pC->aRow + aOffset[p2];
+ if( t<12 ){
+ sqlite3VdbeSerialGet(zData, t, pDest);
}else{
- pDest->z = pDest->zMalloc;
+ /* If the column value is a string, we need a persistent value, not
+ ** a MEM_Ephem value. This branch is a fast short-cut that is
+ ** equivalent to calling sqlite3VdbeSerialGet() and
+ ** sqlite3VdbeDeephemeralize().
+ */
+ static const u16 aFlag[] = { MEM_Blob, MEM_Str|MEM_Term };
+ pDest->n = len = (t-12)/2;
+ pDest->enc = encoding;
+ if( pDest->szMalloc < len+2 ){
+ pDest->flags = MEM_Null;
+ if( sqlite3VdbeMemGrow(pDest, len+2, 0) ) goto no_mem;
+ }else{
+ pDest->z = pDest->zMalloc;
+ }
+ memcpy(pDest->z, zData, len);
+ pDest->z[len] = 0;
+ pDest->z[len+1] = 0;
+ pDest->flags = aFlag[t&1];
+ }
+
+ if( (pOp->p5 & OPFLAG_CONTINUE)==0 ) break;
+ UPDATE_MAX_BLOBSIZE(pDest);
+ REGISTER_TRACE(pOp->p3, pDest);
+ pOp++;
+ p2 = pOp->p2;
+ t = pC->aType[p2];
+ pDest = &aMem[pOp->p3];
+ memAboutToChange(p, pDest);
+ if( VdbeMemDynamic(pDest) ){
+ sqlite3VdbeMemSetNull(pDest);
}
- memcpy(pDest->z, zData, len);
- pDest->z[len] = 0;
- pDest->z[len+1] = 0;
- pDest->flags = aFlag[t&1];
}
}else{
pDest->enc = encoding;
VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8);
void sqlite3VdbeSetVarmask(Vdbe*, int);
+void sqlite3VdbeUsesAltMap(Vdbe*);
#ifndef SQLITE_OMIT_TRACE
char *sqlite3VdbeExpandSql(Vdbe*, const char*);
#endif
bft readOnly:1; /* True for statements that do not write */
bft bIsReader:1; /* True for statements that read */
bft isPrepareV2:1; /* True if prepared with prepare_v2() */
+ bft usesAltMap:1; /* True if uses VdbeCursor.aAltMap[] */
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
u32 aCounter[5]; /* Counters used by sqlite3_stmt_status() */
}
if( pOp==p->aOp ) break;
pOp--;
+
+ if( p->usesAltMap==0
+ && pOp[0].opcode==OP_Column && pOp[1].opcode==OP_Column
+ && pOp[0].p1==pOp[1].p1 && pOp[0].p2>=pOp[1].p2
+ ){
+ pOp->p5 |= OPFLAG_CONTINUE;
+ }
}
sqlite3DbFree(p->db, pParse->aLabel);
pParse->aLabel = 0;
}
}
+/*
+** Set the "uses-alt-map" flag.
+*/
+void sqlite3VdbeUsesAltMap(Vdbe *v){
+ v->usesAltMap = 1;
+}
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
}
sqlite3VdbeChangeP4(v, -1, (char*)ai, P4_INTARRAY);
}
+ sqlite3VdbeUsesAltMap(v);
}
}