From: drh Date: Thu, 7 Nov 2013 21:25:13 +0000 (+0000) Subject: Enable the WHERE_ONEPASS_DESIRED optimization for UPDATE operations on X-Git-Tag: version-3.8.2~133 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=702ba9f2e32a88ad8d6f97124c833027b7dc6ab0;p=thirdparty%2Fsqlite.git Enable the WHERE_ONEPASS_DESIRED optimization for UPDATE operations on WITHOUT ROWID tables. FossilOrigin-Name: 215307985590c2f3f7aa0d5a0b7799155a506045 --- diff --git a/manifest b/manifest index ed50f198f9..bdbe0c7818 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\s--stats\sand\s--summary\soptions\sto\sthe\swordcount.c\stest\sprogram. -D 2013-11-07T19:43:21.798 +C Enable\sthe\sWHERE_ONEPASS_DESIRED\soptimization\sfor\sUPDATE\soperations\son\nWITHOUT\sROWID\stables. +D 2013-11-07T21:25:13.536 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in d12e4455cf7a36e42d3949876c1c3b88ff70867a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -275,7 +275,7 @@ F src/test_vfstrace.c 34b544e80ba7fb77be15395a609c669df2e660a2 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c ec4c1a62b890bf1dbcdb966399e140b904c700a4 F src/trigger.c 53d6b5d50b3b23d4fcd0a36504feb5cff9aed716 -F src/update.c 516e0ea0f853bfb852e098f3b643a3f2bfd423ef +F src/update.c a1580fb4ad99246d4a286348e80c806385dd102f F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918 F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 @@ -292,7 +292,7 @@ F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74 -F src/where.c 1a99f1275fb5db2d76b0093ae1c1936c3b036aa0 +F src/where.c 30462cf04157b872b4443724739ef617b1535686 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 @@ -1135,7 +1135,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 9ad5b74c26c5a18068a2418a2092a05c226912c2 -R 7eb08ca6a9c5e8c1ab9bbee56e904b5c +P 8aa21e6791d408c8f018bd779e09cb7e7179f884 +R 90320f23fbcc029ca5605efdad336f38 U drh -Z ae0666d0d2115aaaa9008a758df6593e +Z eb9342f786dc77889731ffb09a64422a diff --git a/manifest.uuid b/manifest.uuid index fbffe55460..e84b015710 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8aa21e6791d408c8f018bd779e09cb7e7179f884 \ No newline at end of file +215307985590c2f3f7aa0d5a0b7799155a506045 \ No newline at end of file diff --git a/src/update.c b/src/update.c index 065e5d6158..9b6671eb2f 100644 --- a/src/update.c +++ b/src/update.c @@ -128,6 +128,7 @@ void sqlite3Update( #endif int newmask; /* Mask of NEW.* columns accessed by BEFORE triggers */ int iEph = 0; /* Ephemeral table holding all primary key values */ + int nKey; /* Number of elements in regKey */ /* Register Allocations */ int regRowCount = 0; /* A count of rows changed */ @@ -353,6 +354,7 @@ void sqlite3Update( }else{ int iPk; /* First of nPk memory cells holding PRIMARY KEY value */ i16 nPk; /* Number of components of the PRIMARY KEY */ + int addrOpen; /* Address of the OpenEphemeral instruction */ assert( pPk!=0 ); nPk = pPk->nKeyCol; @@ -360,19 +362,28 @@ void sqlite3Update( pParse->nMem += nPk; regKey = ++pParse->nMem; iEph = pParse->nTab++; - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk); + sqlite3VdbeAddOp2(v, OP_Null, 0, iPk); + addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk); sqlite3VdbeSetP4KeyInfo(pParse, pPk); - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, 0, 0); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, + WHERE_ONEPASS_DESIRED, 0); if( pWInfo==0 ) goto update_cleanup; + okOnePass = sqlite3WhereOkOnePass(pWInfo); for(i=0; iaiColumn[i], iPk+i); } - sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey, - sqlite3IndexAffinityStr(v, pPk), P4_TRANSIENT); - sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, regKey); + if( okOnePass ){ + sqlite3VdbeChangeToNoop(v, addrOpen); + nKey = nPk; + regKey = iPk; + }else{ + sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey, + sqlite3IndexAffinityStr(v, pPk), P4_TRANSIENT); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, regKey); + nKey = 0; + } sqlite3WhereEnd(pWInfo); - okOnePass = 0; } /* Initialize the count of updated rows @@ -417,14 +428,17 @@ void sqlite3Update( /* Top of the update loop */ labelBreak = sqlite3VdbeMakeLabel(v); - if( pPk ){ + if( okOnePass ){ + labelContinue = labelBreak; + sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); + if( pPk ){ + sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey); + } + }else if( pPk ){ labelContinue = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); addrTop = sqlite3VdbeAddOp2(v, OP_RowKey, iEph, regKey); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0); - }else if( okOnePass ){ - labelContinue = labelBreak; - sqlite3VdbeAddOp2(v, OP_IsNull, regOldRowid, labelBreak); }else{ labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, labelBreak, regOldRowid); @@ -516,7 +530,7 @@ void sqlite3Update( ** documentation. */ if( pPk ){ - sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0); + sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue,regKey,nKey); }else{ sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); } @@ -548,7 +562,7 @@ void sqlite3Update( /* Delete the index entries associated with the current record. */ if( pPk ){ - j1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, 0); + j1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey); }else{ j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid); } @@ -592,10 +606,12 @@ void sqlite3Update( /* Repeat the above with the next record to be updated, until ** all record selected by the WHERE clause have been updated. */ - if( pPk ){ + if( okOnePass ){ + /* Nothing to do at end-of-loop for a single-pass */ + }else if( pPk ){ sqlite3VdbeResolveLabel(v, labelContinue); sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); - }else if( !okOnePass ){ + }else{ sqlite3VdbeAddOp2(v, OP_Goto, 0, labelContinue); } sqlite3VdbeResolveLabel(v, labelBreak); diff --git a/src/where.c b/src/where.c index 02bec9549c..c26465e970 100644 --- a/src/where.c +++ b/src/where.c @@ -4639,9 +4639,10 @@ static int whereLoopAddBtree( /* Full scan via index */ if( b + || !HasRowid(pTab) || ( m==0 && pProbe->bUnordered==0 - && (!HasRowid(pTab) || pProbe->szIdxRowszTabRow) + && (pProbe->szIdxRowszTabRow) && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 && sqlite3GlobalConfig.bUseCis && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan) @@ -4657,7 +4658,6 @@ static int whereLoopAddBtree( pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 1 + (15*pProbe->szIdxRow)/pTab->szTabRow; }else{ - assert( b!=0 ); /* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N) ** which we will simplify to just N*log2(N) */ pNew->rRun = rSize + rLogSize; @@ -5990,7 +5990,9 @@ WhereInfo *sqlite3WhereBegin( if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 && (pWInfo->a[0].pWLoop->wsFlags & WHERE_ONEROW)!=0 ){ pWInfo->okOnePass = 1; - pWInfo->a[0].pWLoop->wsFlags &= ~WHERE_IDX_ONLY; + if( HasRowid(pTabList->a[0].pTab) ){ + pWInfo->a[0].pWLoop->wsFlags &= ~WHERE_IDX_ONLY; + } } /* Open all tables in the pTabList and any indices selected for