diff --git a/manifest b/manifest index 48fac5609a..216763e303 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Implement\sthe\sout2-prerelease\sopcode\sdesign\spattern.\s(CVS\s4681) -D 2008-01-04T22:01:03 +C Get\srid\sof\sOP_Dup,\sOP_MemStore,\sOP_MemLoad,\sand\sOP_MemMove.\s\sReplace\nwith\sOP_Copy,\sOP_SCopy,\sand\sOP_Move.\s\sAdd\sthe\sinfrastructure\sfor\noperation\sproperties\sin1,\sin2,\sin3,\sout2,\sand\sout3\sbut\sdo\snot\syet\nuse\sany\sof\sthese.\s(CVS\s4682) +D 2008-01-05T04:06:04 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -69,7 +69,7 @@ F mkdll.sh 5f8438dcac98e795d7df6529159a1ec566de0183 F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f F mkextw.sh 1a866b53637dab137191341cc875575a5ca110fb F mkopcodec.awk 3fb9bf077053c968451f4dd03d11661ac373f9d1 -F mkopcodeh.awk 71abda1cad4c3c7385834ced713c0271f2b13161 +F mkopcodeh.awk b5b810762528f195111fb9b72bbd224a007a5260 F mkso.sh 24bde4c09e6fe80f718db3c31c068f45e13a2f2c F publish.sh 1c0658c63d70f182a8f5e17cc28422f1b237f51d F publish_osx.sh eca87df1e3d43d128d97d3261fd48b3d6877996e @@ -79,24 +79,24 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4 F sqlite3.pc.in abed4664817e1cd500f2276142c71958087c16bc F src/alter.c 5a54f58d9481ac14c4e58b702f3f8758dee84d04 -F src/analyze.c 117e600989d4308578140b646f5caaec6b751f16 +F src/analyze.c 4e24deeee2b93e91a2197953515fa175bfab27f2 F src/attach.c 1c96631e56cdc51d3d70736bf61f1fe01c62cbea F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627 F src/btmutex.c 5d39da37c9d1282f3c6f9967afae6a34ee36b7ff F src/btree.c 5164b32950cfd41f2c5c31e8ff82c4a499918aef F src/btree.h 19dcf5ad23c17b98855da548e9a8e3eb4429d5eb F src/btreeInt.h 1c5a9da165718ef7de81e35ce9ab5d9ba9283f76 -F src/build.c eac0f7e670035ee1087edc7ca223da844bf8940d +F src/build.c 739eeee868e97a69c27e72636ca5be824da87703 F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0 F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131 F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6 -F src/delete.c 056f96bbbfaf27cb90f03e1d21abeab88a26235c +F src/delete.c f943c27bf37f2f37d7e16dc4e94421870ce68c6c F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b -F src/expr.c 57f7c39724c8dee8b4a547dfa58c344bee528996 +F src/expr.c d317c8081a05eaa5720a10e0067dfa0864f762db F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53 -F src/insert.c 907fa2dfde1330d9971ba180ad735ea4daf6ad03 +F src/insert.c fb46be04638fca9b319a216e83e2bb57e8621fcc F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2 F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35 @@ -127,11 +127,11 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b F src/pager.c 0cb6ccea4b9615627d61d7c4417cedc45776d429 F src/pager.h f504f7ae84060fee0416a853e368d3d113c3d6fa F src/parse.y 2ae06e8d3190faace49c5b82e7cea1fc60d084a1 -F src/pragma.c ff8841222bb9779f1ebed0c4d0016530221e7fe8 +F src/pragma.c 6f5918141e1a100975666d88a4bd3c6cd6da4f3d F src/prepare.c f1bb8eb642082e618a359c08e3e107490eafe0e3 F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910 F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da -F src/select.c 30110ce6ce891dcb93a922ee4a51946983df0a33 +F src/select.c 1a6664131fb0e250826fd26189b0e615d726fbcd F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c 5391e889384d2062249f668110d64ed16f601c4b F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f @@ -163,12 +163,12 @@ F src/test_server.c a6ece6c835e7eae835054124e09e947e422b1ac5 F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59 F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730 F src/tokenize.c a4e04438c11fed2c67ec47fe3edbef9cca2d1b48 -F src/trigger.c 713b501b12ea41bf0297a2cf78f7d954c4a25d13 -F src/update.c e57d0083b0800ae514f3226761d019f195f15cb2 +F src/trigger.c 91ff1552b5c2cd66a077563a026d183c1dc993d6 +F src/update.c 3dc744343c81c7ed97d9e1ed5e5887e256921062 F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736 F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624 F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0 -F src/vdbe.c a2d9e868ef2ac65310478d32a33e9bdffc74281e +F src/vdbe.c 8a2d438d47e38542ca4ee519528ea859cee9ecfa F src/vdbe.h bb128757b84280504a1243c450fd13ead248ede5 F src/vdbeInt.h 31bd686595356284d5484592e2dc6e58025aa346 F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c @@ -177,7 +177,7 @@ F src/vdbeblob.c b90f7494c408d47ce6835000b01e40b371e27baf F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6 F src/vdbemem.c 123994fcd344993d2fb050a83b91b341bbbd08b4 F src/vtab.c 03014b2bfa8096ecac5fcdc80d34cd76e06af52a -F src/where.c d015536e273de18196554f13265d80ec9e988766 +F src/where.c af005c6a5875b230648e7f1a38993cd848161313 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/all.test ee350b9ab15b175fc0a8fb51bf2141ed3a3b9cba @@ -323,7 +323,7 @@ F test/icu.test e6bfae7f625c88fd14df6f540fe835bdfc1e4329 F test/in.test 87270d14e2dd870da77d178985b43fea4675eb56 F test/in2.test b1f447f4f0f67e9f83ff931e7e2e30873f9ea055 F test/in3.test e335959db24d71d6cfdff9553c90ce2b56fb978c -F test/incrblob.test 602dbfa956904d6e58c45635b58850ad0f02d927 +F test/incrblob.test 854c23b7ff8dd3822f675936b22c094655b3c739 F test/incrblob_err.test 5273097dc7c97f9b7008423a6ffd5c80d21923cb F test/incrvacuum.test 1ed44535e89a0fa10c48c1aa0a3d48ee72bcc733 F test/incrvacuum2.test a958e378c193c4012cb3787804d863487f1dfad1 @@ -603,7 +603,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 717bcd11a222fe100e25c5b2eb6de8b6b9930de1 -R 4486249090525dc5e5cc1ca96f44eb9a +P fe057a88d0038ac349ea41883b979ceba6ae410a +R 42deacb2e7b246f14ca2d74e7526fed1 U drh -Z c5a3c782e07a8605f750b96c4ed10a88 +Z b60a5382e66d036aa3cd3e890b046e32 diff --git a/manifest.uuid b/manifest.uuid index 80ad73844e..57dc5a4c21 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fe057a88d0038ac349ea41883b979ceba6ae410a \ No newline at end of file +cc149eb9ca3c672cc6fea3528353234ac2ed5745 \ No newline at end of file diff --git a/mkopcodeh.awk b/mkopcodeh.awk index 00823d5e4b..de04fab611 100644 --- a/mkopcodeh.awk +++ b/mkopcodeh.awk @@ -53,6 +53,11 @@ jump[name] = 0 nopush[name] = 0 out2_prerelease[name] = 0 + in1[name] = 0 + in2[name] = 0 + in3[name] = 0 + out2[name] = 0 + out3[name] = 0 for(i=3; i0 then it is always the case the D>0 so division by zero ** is never possible. */ - sqlite3VdbeAddOp1(v, OP_MemLoad, iMem); + sqlite3VdbeAddOp1(v, OP_SCopy, iMem); addr = sqlite3VdbeAddOp0(v, OP_IfNot); sqlite3VdbeAddOp1(v, OP_NewRowid, iStatCur); sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pTab->zName, 0); sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pIdx->zName, 0); - sqlite3VdbeAddOp1(v, OP_MemLoad, iMem); + sqlite3VdbeAddOp1(v, OP_SCopy, iMem); sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, " ", 0); for(i=0; i @@ -881,7 +881,7 @@ void sqlite3StartTable( } sqlite3OpenMasterTable(pParse, iDb); sqlite3VdbeAddOp0(v, OP_NewRowid); - sqlite3VdbeAddOp0(v, OP_Dup); + sqlite3VdbeAddOp0(v, OP_Copy); sqlite3VdbeAddOp0(v, OP_Null); sqlite3CodeInsert(pParse, 0, OPFLAG_APPEND); sqlite3VdbeAddOp0(v, OP_Close); @@ -1493,7 +1493,7 @@ void sqlite3EndTable( if( pSelect ){ SelectDest dest = {SRT_Table, 1, 0}; Table *pSelTab; - sqlite3VdbeAddOp1(v, OP_Dup, 0); + sqlite3VdbeAddOp0(v, OP_Copy); sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, 0, iDb); pParse->nTab = 2; sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0); @@ -2235,7 +2235,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ v = sqlite3GetVdbe(pParse); if( v==0 ) return; if( memRootPage>=0 ){ - sqlite3VdbeAddOp1(v, OP_MemLoad, memRootPage); + sqlite3VdbeAddOp1(v, OP_SCopy, memRootPage); tnum = 0; }else{ tnum = pIndex->tnum; @@ -2638,7 +2638,7 @@ void sqlite3CreateIndex( */ sqlite3BeginWriteOperation(pParse, 1, iDb); sqlite3VdbeAddOp1(v, OP_CreateIndex, iDb); - sqlite3VdbeAddOp2(v, OP_MemStore, iMem, 0); + sqlite3VdbeAddOp2(v, OP_Copy, 0, iMem); /* Gather the complete text of the CREATE INDEX statement into ** the zStmt variable diff --git a/src/delete.c b/src/delete.c index 4a6a5d0ab7..6ce8ad8f5c 100644 --- a/src/delete.c +++ b/src/delete.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** -** $Id: delete.c,v 1.148 2008/01/04 22:01:03 drh Exp $ +** $Id: delete.c,v 1.149 2008/01/05 04:06:04 drh Exp $ */ #include "sqliteInt.h" @@ -68,8 +68,8 @@ void sqlite3CodeInsert(Parse *p, int iCur, u8 flags){ int iData = ++p->nMem; int iKey = ++p->nMem; Vdbe *v = sqlite3GetVdbe(p); - sqlite3VdbeAddOp2(v, OP_MemStore, iData, 1); - sqlite3VdbeAddOp2(v, OP_MemStore, iKey, 1); + sqlite3VdbeAddOp2(v, OP_Move, 0, iData); + sqlite3VdbeAddOp2(v, OP_Move, 0, iKey); sqlite3VdbeAddOp3(v, OP_Insert, iCur, iData, iKey); sqlite3VdbeChangeP5(v, sqlite3VdbeCurrentAddr(v)-1, flags); } @@ -87,7 +87,7 @@ int sqlite3StackToReg(Parse *p, int nVal){ assert(v); p->nMem += nVal; for(i=nVal-1; i>=0; i--){ - sqlite3VdbeAddOp2(v, OP_MemStore, iRet+i, 1); + sqlite3VdbeAddOp2(v, OP_Move, 0, iRet+i); } return iRet; } @@ -96,7 +96,7 @@ void sqlite3RegToStack(Parse *p, int iReg, int nVal){ Vdbe *v = sqlite3GetVdbe(p); assert(v); for(i=0; inColumn; j++){ int idx = pIdx->aiColumn[j]; if( idx==pTab->iPKey ){ - sqlite3VdbeAddOp1(v, OP_Dup, j); + sqlite3VdbeAddOp1(v, OP_Copy, -j); }else{ sqlite3VdbeAddOp2(v, OP_Column, iCur, idx); sqlite3ColumnDefault(v, pTab, idx); diff --git a/src/expr.c b/src/expr.c index a6cb1e17b7..2586885e08 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.330 2008/01/04 22:01:03 drh Exp $ +** $Id: expr.c,v 1.331 2008/01/05 04:06:04 drh Exp $ */ #include "sqliteInt.h" #include @@ -308,8 +308,7 @@ Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){ } depth = atoi((char*)&pToken->z[1]); p->iTable = ++pParse->nMem; - sqlite3VdbeAddOp1(v, OP_Dup, depth); - sqlite3VdbeAddOp2(v, OP_MemStore, p->iTable, 1); + sqlite3VdbeAddOp2(v, OP_Copy, -depth, p->iTable); return p; } @@ -1606,7 +1605,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int mustBeUnique){ int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); sqlite3VdbeUsesBtree(v, iDb); - sqlite3VdbeAddOp1(v, OP_MemLoad, iMem); + sqlite3VdbeAddOp1(v, OP_SCopy, iMem); iAddr = sqlite3VdbeAddOp2(v, OP_If, 0, iMem); sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem); @@ -1643,7 +1642,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int mustBeUnique){ iDb = sqlite3SchemaToIndex(db, pIdx->pSchema); sqlite3VdbeUsesBtree(v, iDb); - sqlite3VdbeAddOp1(v, OP_MemLoad, iMem); + sqlite3VdbeAddOp1(v, OP_SCopy, iMem); iAddr = sqlite3VdbeAddOp2(v, OP_If, 0, iMem); sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem); @@ -1700,7 +1699,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ */ if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->trigStack ){ int mem = ++pParse->nMem; - sqlite3VdbeAddOp1(v, OP_MemLoad, mem); + sqlite3VdbeAddOp1(v, OP_SCopy, mem); testAddr = sqlite3VdbeAddOp0(v, OP_If); assert( testAddr>0 || pParse->db->mallocFailed ); sqlite3VdbeAddOp2(v, OP_Integer, 1, mem); @@ -1966,7 +1965,7 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ AggInfo *pAggInfo = pExpr->pAggInfo; struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg]; if( !pAggInfo->directMode ){ - sqlite3VdbeAddOp1(v, OP_MemLoad, pCol->iMem); + sqlite3VdbeAddOp1(v, OP_SCopy, pCol->iMem); break; }else if( pAggInfo->useSortingIdx ){ sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdx, @@ -1980,7 +1979,7 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ if( pExpr->iTable<0 ){ /* This only happens when coding check constraints */ assert( pParse->ckOffset>0 ); - sqlite3VdbeAddOp2(v, OP_Dup, pParse->ckOffset-pExpr->iColumn-1, 1); + sqlite3VdbeAddOp1(v, OP_SCopy, -(pParse->ckOffset-pExpr->iColumn-1)); }else{ sqlite3ExprCodeGetColumn(v, pExpr->pTab, pExpr->iColumn, pExpr->iTable, target); @@ -2029,7 +2028,7 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ break; } case TK_REGISTER: { - sqlite3VdbeAddOp1(v, OP_MemLoad, pExpr->iTable); + sqlite3VdbeAddOp1(v, OP_SCopy, pExpr->iTable); break; } #ifndef SQLITE_OMIT_CAST @@ -2138,7 +2137,7 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ sqlite3ErrorMsg(pParse, "misuse of aggregate: %T", &pExpr->span); }else{ - sqlite3VdbeAddOp1(v, OP_MemLoad, pInfo->aFunc[pExpr->iAgg].iMem); + sqlite3VdbeAddOp1(v, OP_SCopy, pInfo->aFunc[pExpr->iAgg].iMem); } break; } @@ -2202,7 +2201,7 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ if( pExpr->iColumn==0 ){ sqlite3CodeSubselect(pParse, pExpr); } - sqlite3VdbeAddOp1(v, OP_MemLoad, pExpr->iColumn); + sqlite3VdbeAddOp1(v, OP_SCopy, pExpr->iColumn); VdbeComment((v, "load subquery result")); break; } @@ -2254,7 +2253,7 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ struct ExprList_item *pLItem = pExpr->pList->a; Expr *pRight = pLItem->pExpr; sqlite3ExprCode(pParse, pLeft, 0); - sqlite3VdbeAddOp0(v, OP_Dup); + sqlite3VdbeAddOp0(v, OP_Copy); sqlite3ExprCode(pParse, pRight, 0); codeCompare(pParse, pLeft, pRight, OP_Ge, 0, 0); sqlite3VdbeAddOp1(v, OP_Pull, 1); @@ -2291,7 +2290,7 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ for(i=0; ipLeft ){ - sqlite3VdbeAddOp2(v, OP_Dup, 1, 1); + sqlite3VdbeAddOp1(v, OP_SCopy, -1); jumpInst = codeCompare(pParse, pExpr->pLeft, aListelem[i].pExpr, OP_Ne, 0, 1); sqlite3VdbeAddOp1(v, OP_Pop, 1); @@ -2339,7 +2338,7 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ #endif } if( target && !inReg ){ - sqlite3VdbeAddOp2(v, OP_MemStore, target, 1); + sqlite3VdbeAddOp2(v, OP_Move, 0, target); stackChng = 0; } if( pParse->ckOffset ){ @@ -2372,7 +2371,7 @@ void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr){ if( addr2>addr1+1 || ((pOp = sqlite3VdbeGetOp(v, addr1))!=0 && pOp->opcode==OP_Function) ){ iMem = pExpr->iTable = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_MemStore, iMem, 0); + sqlite3VdbeAddOp2(v, OP_Copy, 0, iMem); pExpr->op = TK_REGISTER; } } @@ -2479,7 +2478,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Expr *pLeft = pExpr->pLeft; Expr *pRight = pExpr->pList->a[0].pExpr; sqlite3ExprCode(pParse, pLeft, 0); - sqlite3VdbeAddOp2(v, OP_Dup, 0, 0); + sqlite3VdbeAddOp0(v, OP_Copy); sqlite3ExprCode(pParse, pRight, 0); addr = codeCompare(pParse, pLeft, pRight, OP_Lt, 0, !jumpIfNull); @@ -2591,7 +2590,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Expr *pLeft = pExpr->pLeft; Expr *pRight = pExpr->pList->a[0].pExpr; sqlite3ExprCode(pParse, pLeft, 0); - sqlite3VdbeAddOp2(v, OP_Dup, 0, 0); + sqlite3VdbeAddOp0(v, OP_Copy); sqlite3ExprCode(pParse, pRight, 0); addr = sqlite3VdbeCurrentAddr(v); codeCompare(pParse, pLeft, pRight, OP_Ge, addr+3, !jumpIfNull); diff --git a/src/insert.c b/src/insert.c index 7d7bb7c62c..9762ab7394 100644 --- a/src/insert.c +++ b/src/insert.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.211 2008/01/04 22:01:03 drh Exp $ +** $Id: insert.c,v 1.212 2008/01/05 04:06:04 drh Exp $ */ #include "sqliteInt.h" @@ -171,9 +171,9 @@ static int autoIncBegin( sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pTab->zName, 0); sqlite3VdbeAddOp2(v, OP_Ne, 0x100, addr+11); sqlite3VdbeAddOp2(v, OP_Rowid, iCur, 0); - sqlite3VdbeAddOp2(v, OP_MemStore, memId-1, 1); + sqlite3VdbeAddOp2(v, OP_Move, 0, memId-1); sqlite3VdbeAddOp2(v, OP_Column, iCur, 1); - sqlite3VdbeAddOp2(v, OP_MemStore, memId, 1); + sqlite3VdbeAddOp2(v, OP_Move, 0, memId); sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+12); sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+3); sqlite3VdbeAddOp2(v, OP_Close, iCur, 0); @@ -214,12 +214,12 @@ static void autoIncEnd( assert( v ); addr = sqlite3VdbeCurrentAddr(v); sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); - sqlite3VdbeAddOp2(v, OP_MemLoad, memId-1, 0); + sqlite3VdbeAddOp2(v, OP_SCopy, memId-1, 0); sqlite3VdbeAddOp2(v, OP_NotNull, -1, addr+6); sqlite3VdbeAddOp2(v, OP_Pop, 1, 0); sqlite3VdbeAddOp1(v, OP_NewRowid, iCur); sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pTab->zName, 0); - sqlite3VdbeAddOp2(v, OP_MemLoad, memId, 0); + sqlite3VdbeAddOp2(v, OP_SCopy, memId, 0); sqlite3VdbeAddOp2(v, OP_MakeRecord, 2, 0); sqlite3CodeInsert(pParse, iCur, OPFLAG_APPEND); sqlite3VdbeAddOp2(v, OP_Close, iCur, 0); @@ -728,9 +728,7 @@ void sqlite3Insert( if( useTempTable ){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, iRowid); }else if( pSelect ){ - sqlite3VdbeAddOp3(v, OP_Dup, nColumn - keyColumn - 1, 1, iRowid); - /* TODO: Avoid this use of the stack. */ - sqlite3VdbeAddOp2(v, OP_MemStore, iRowid, 1); + sqlite3VdbeAddOp2(v, OP_SCopy, -(nColumn - keyColumn - 1), iRowid); }else{ VdbeOp *pOp; sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, 0); @@ -743,7 +741,7 @@ void sqlite3Insert( pOp->p3 = counterMem; }else{ /* TODO: Avoid this use of the stack. */ - sqlite3VdbeAddOp2(v, OP_MemStore, iRowid, 1); + sqlite3VdbeAddOp2(v, OP_Move, 0, iRowid); } } /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid @@ -758,8 +756,7 @@ void sqlite3Insert( }else if( IsVirtual(pTab) ){ sqlite3VdbeAddOp2(v, OP_Null, 0, iRowid); }else{ - sqlite3VdbeAddOp3(v, OP_NewRowid, base, 0, counterMem); - sqlite3VdbeAddOp2(v, OP_MemStore, iRowid, 1); + sqlite3VdbeAddOp3(v, OP_NewRowid, base, iRowid, counterMem); appendFlag = 1; } autoIncStep(pParse, counterMem, iRowid); @@ -796,9 +793,7 @@ void sqlite3Insert( }else if( useTempTable ){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore); }else if( pSelect ){ - sqlite3VdbeAddOp2(v, OP_Dup, nColumn-j-1, 1); - /* TODO: Avoid this use of the stack */ - sqlite3VdbeAddOp2(v, OP_MemStore, iRegStore, 1); + sqlite3VdbeAddOp2(v, OP_SCopy, -(nColumn-j-1), iRegStore); }else{ sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore); } @@ -1005,7 +1000,7 @@ void sqlite3GenerateConstraintChecks( if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){ onError = OE_Abort; } - sqlite3VdbeAddOp2(v, OP_Dup, nCol-1-i, 1); + sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol-1-i)); addr = sqlite3VdbeAddOp2(v, OP_NotNull, 1, 0); assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail || onError==OE_Ignore || onError==OE_Replace ); @@ -1027,7 +1022,7 @@ void sqlite3GenerateConstraintChecks( } case OE_Replace: { sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, 0); - sqlite3VdbeAddOp2(v, OP_Push, nCol-i, 0); + sqlite3VdbeAddOp1(v, OP_Push, nCol-i); break; } } @@ -1068,11 +1063,11 @@ void sqlite3GenerateConstraintChecks( } if( isUpdate ){ - sqlite3VdbeAddOp2(v, OP_Dup, nCol+1, 1); - sqlite3VdbeAddOp2(v, OP_Dup, nCol+1, 1); + sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+1)); + sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+1)); jumpInst1 = sqlite3VdbeAddOp2(v, OP_Eq, 0, 0); } - sqlite3VdbeAddOp2(v, OP_Dup, nCol, 1); + sqlite3VdbeAddOp1(v, OP_SCopy, -nCol); jumpInst2 = sqlite3VdbeAddOp2(v, OP_NotExists, base, 0); switch( onError ){ default: { @@ -1089,7 +1084,7 @@ void sqlite3GenerateConstraintChecks( case OE_Replace: { sqlite3GenerateRowIndexDelete(v, pTab, base, 0); if( isUpdate ){ - sqlite3VdbeAddOp2(v, OP_Dup, nCol+hasTwoRowids, 1); + sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+hasTwoRowids)); sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0); } seenReplace = 1; @@ -1105,7 +1100,7 @@ void sqlite3GenerateConstraintChecks( sqlite3VdbeJumpHere(v, jumpInst2); if( isUpdate ){ sqlite3VdbeJumpHere(v, jumpInst1); - sqlite3VdbeAddOp2(v, OP_Dup, nCol+1, 1); + sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+1)); sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0); } } @@ -1120,13 +1115,13 @@ void sqlite3GenerateConstraintChecks( extra++; /* Create a key for accessing the index entry */ - sqlite3VdbeAddOp2(v, OP_Dup, nCol+extra, 1); + sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+extra)); for(i=0; inColumn; i++){ int idx = pIdx->aiColumn[i]; if( idx==pTab->iPKey ){ - sqlite3VdbeAddOp2(v, OP_Dup, i+extra+nCol+1, 1); + sqlite3VdbeAddOp1(v, OP_SCopy, -(i+extra+nCol+1)); }else{ - sqlite3VdbeAddOp2(v, OP_Dup, i+extra+nCol-idx, 1); + sqlite3VdbeAddOp1(v, OP_SCopy, -(i+extra+nCol-idx)); } } jumpInst1 = sqlite3VdbeAddOp2(v, OP_MakeIdxRec, pIdx->nColumn, 0); @@ -1147,7 +1142,7 @@ void sqlite3GenerateConstraintChecks( /* Check to see if the new index entry will be unique */ - sqlite3VdbeAddOp2(v, OP_Dup, extra+nCol+1+hasTwoRowids, 1); + sqlite3VdbeAddOp1(v, OP_SCopy, -(extra+nCol+1+hasTwoRowids)); jumpInst2 = sqlite3VdbeAddOp2(v, OP_IsUnique, base+iCur+1, 0); /* Generate code that executes if the new index entry is not unique */ @@ -1193,7 +1188,7 @@ void sqlite3GenerateConstraintChecks( int iRowid = sqlite3StackToReg(pParse, 1); sqlite3GenerateRowDelete(pParse->db, v, pTab, base, iRowid, 0); if( isUpdate ){ - sqlite3VdbeAddOp2(v, OP_Dup, nCol+extra+1+hasTwoRowids, 1); + sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+extra+1+hasTwoRowids)); sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0); } seenReplace = 1; @@ -1245,8 +1240,8 @@ void sqlite3CompleteInsertion( sqlite3TableAffinityStr(v, pTab); #ifndef SQLITE_OMIT_TRIGGER if( newIdx>=0 ){ - sqlite3VdbeAddOp2(v, OP_Dup, 1, 0); - sqlite3VdbeAddOp2(v, OP_Dup, 1, 0); + sqlite3VdbeAddOp1(v, OP_Copy, -1); + sqlite3VdbeAddOp1(v, OP_Copy, -1); sqlite3CodeInsert(pParse, newIdx, 0); } #endif @@ -1566,7 +1561,7 @@ static int xferOptimization( emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); if( pDest->iPKey>=0 ){ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, 0); - sqlite3VdbeAddOp2(v, OP_Dup, 0, 0); + sqlite3VdbeAddOp0(v, OP_Copy); addr2 = sqlite3VdbeAddOp2(v, OP_NotExists, iDest, 0); sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, "PRIMARY KEY must be unique", P4_STATIC); diff --git a/src/pragma.c b/src/pragma.c index 7db7895632..a63459f428 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.158 2008/01/04 22:01:03 drh Exp $ +** $Id: pragma.c,v 1.159 2008/01/05 04:06:04 drh Exp $ */ #include "sqliteInt.h" #include @@ -300,7 +300,7 @@ void sqlite3Pragma( static const VdbeOpList getCacheSize[] = { { OP_ReadCookie, 0, 0, 2}, /* 0 */ { OP_AbsValue, 0, 0, 0}, - { OP_Dup, 0, 0, 0}, + { OP_Copy, 0, 0, 0}, { OP_Integer, 0, 0, 0}, { OP_Ne, 0, 6, 0}, { OP_Integer, 0, 0, 0}, /* 5 */ @@ -830,7 +830,7 @@ void sqlite3Pragma( ** error message */ static const VdbeOpList endCode[] = { - { OP_MemLoad, 1, 0, 0}, + { OP_SCopy, 1, 0, 0}, { OP_Integer, 0, 0, 0}, { OP_Ne, 0, 0, 0}, /* 2 */ { OP_String8, 0, 0, 0}, /* 3 */ @@ -933,8 +933,8 @@ void sqlite3Pragma( { OP_Rewind, 0, 0, 0}, /* 1 */ { OP_MemIncr, 1, 3, 0}, { OP_Next, 0, 0, 0}, /* 3 */ - { OP_MemLoad, 2, 0, 0}, - { OP_MemLoad, 3, 0, 0}, + { OP_SCopy, 2, 0, 0}, + { OP_SCopy, 3, 0, 0}, { OP_Eq, 0, 0, 0}, /* 6 */ { OP_MemIncr, -1, 1, 0}, { OP_String8, 0, 0, 0}, /* 8 */ diff --git a/src/select.c b/src/select.c index 9d6f5873f0..dd768646bf 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.384 2008/01/04 22:01:03 drh Exp $ +** $Id: select.c,v 1.385 2008/01/05 04:06:04 drh Exp $ */ #include "sqliteInt.h" @@ -634,7 +634,7 @@ static int selectInnerLoop( ** ORDER BY in this case since the order of entries in the set ** does not matter. But there might be a LIMIT clause, in which ** case the order does matter */ - sqlite3VdbeAddOp2(v, OP_MemLoad, iMem+1, 0); + sqlite3VdbeAddOp2(v, OP_SCopy, iMem+1, 0); pushOntoSorter(pParse, pOrderBy, p); }else{ sqlite3VdbeAddOp4(v, OP_RegMakeRec, iMem, 0, 0, &p->affinity, 1); @@ -658,11 +658,11 @@ static int selectInnerLoop( */ case SRT_Mem: { assert( nColumn==1 ); - sqlite3VdbeAddOp2(v, OP_MemLoad, iMem+1, 0); + sqlite3VdbeAddOp2(v, OP_SCopy, iMem+1, 0); if( pOrderBy ){ pushOntoSorter(pParse, pOrderBy, p); }else{ - sqlite3VdbeAddOp2(v, OP_MemStore, iParm, 1); + sqlite3VdbeAddOp2(v, OP_Move, 0, iParm); /* The LIMIT clause will jump out of the loop for us */ } break; @@ -679,7 +679,7 @@ static int selectInnerLoop( sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, 0); pushOntoSorter(pParse, pOrderBy, p); }else if( eDest==SRT_Subroutine ){ - for(i=0; ipLimit, 0); sqlite3VdbeAddOp2(v, OP_MustBeInt, 0, 0); - sqlite3VdbeAddOp2(v, OP_MemStore, iLimit, 1); + sqlite3VdbeAddOp2(v, OP_Move, 0, iLimit); VdbeComment((v, "LIMIT counter")); sqlite3VdbeAddOp2(v, OP_IfMemZero, iLimit, iBreak); - sqlite3VdbeAddOp2(v, OP_MemLoad, iLimit, 0); + sqlite3VdbeAddOp2(v, OP_SCopy, iLimit, 0); } if( p->pOffset ){ p->iOffset = iOffset = ++pParse->nMem; @@ -1763,7 +1763,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ if( v==0 ) return; sqlite3ExprCode(pParse, p->pOffset, 0); sqlite3VdbeAddOp2(v, OP_MustBeInt, 0, 0); - sqlite3VdbeAddOp2(v, OP_MemStore, iOffset, p->pLimit==0); + sqlite3VdbeAddOp2(v, p->pLimit==0 ? OP_Move : OP_Copy, 0, iOffset); VdbeComment((v, "OFFSET counter")); addr1 = sqlite3VdbeAddOp2(v, OP_IfMemPos, iOffset, 0); sqlite3VdbeAddOp2(v, OP_Pop, 1, 0); @@ -1779,7 +1779,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ sqlite3VdbeAddOp2(v, OP_Integer, -1, iLimit+1); addr2 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); sqlite3VdbeJumpHere(v, addr1); - sqlite3VdbeAddOp2(v, OP_MemStore, iLimit+1, 1); + sqlite3VdbeAddOp2(v, OP_Move, 0, iLimit+1); VdbeComment((v, "LIMIT+OFFSET")); sqlite3VdbeJumpHere(v, addr2); } @@ -3547,13 +3547,13 @@ int sqlite3Select( sAggInfo.directMode = 1; sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, 0); } - sqlite3VdbeAddOp2(v, OP_MemStore, iBMem+j, jnExpr-1); + sqlite3VdbeAddOp2(v, jnExpr-1?OP_Move:OP_Copy, 0, iBMem+j); } for(j=pGroupBy->nExpr-1; j>=0; j--){ if( jnExpr-1 ){ - sqlite3VdbeAddOp2(v, OP_MemLoad, iBMem+j, 0); + sqlite3VdbeAddOp2(v, OP_SCopy, iBMem+j, 0); } - sqlite3VdbeAddOp2(v, OP_MemLoad, iAMem+j, 0); + sqlite3VdbeAddOp2(v, OP_SCopy, iAMem+j, 0); if( j==0 ){ sqlite3VdbeAddOp2(v, OP_Eq, 0x200, addrProcessRow); }else{ @@ -3573,7 +3573,7 @@ int sqlite3Select( */ sqlite3VdbeResolveLabel(v, addrGroupByChange); for(j=0; jnExpr; j++){ - sqlite3VdbeAddOp2(v, OP_MemMove, iAMem+j, iBMem+j); + sqlite3VdbeAddOp2(v, OP_Move, iBMem+j, iAMem+j); } sqlite3VdbeAddOp2(v, OP_Gosub, 0, addrOutputRow); VdbeComment((v, "output one row")); diff --git a/src/trigger.c b/src/trigger.c index c6ec0e0816..9fe781f008 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -237,8 +237,8 @@ void sqlite3FinishTrigger( { OP_String8, 0, 0, 0 }, /* 6: SQL */ { OP_Concat, 0, 0, 0 }, { OP_MakeRecord, 5, 0, 0 }, /* 8: "aaada" */ - { OP_MemStore, 0, 1, 0 }, /* 9: Store data */ - { OP_MemStore, 0, 1, 0 }, /* 10: Store key */ + { OP_Move, 0, 0, 0 }, /* 9: Store data */ + { OP_Move, 0, 0, 0 }, /* 10: Store key */ { OP_Insert, 0, 0, 0 }, }; int addr; @@ -258,9 +258,9 @@ void sqlite3FinishTrigger( sqlite3VdbeChangeP4(v, addr+5, "CREATE TRIGGER ", P4_STATIC); sqlite3VdbeChangeP4(v, addr+6, (char*)pAll->z, pAll->n); sqlite3VdbeChangeP4(v, addr+8, "aaada", P4_STATIC); - sqlite3VdbeChangeP1(v, addr+9, iData); + sqlite3VdbeChangeP2(v, addr+9, iData); + sqlite3VdbeChangeP2(v, addr+10, iKey); sqlite3VdbeChangeP2(v, addr+11, iData); - sqlite3VdbeChangeP1(v, addr+10, iKey); sqlite3VdbeChangeP3(v, addr+11, iKey); sqlite3ChangeCookie(db, v, iDb); sqlite3VdbeAddOp2(v, OP_Close, 0, 0); diff --git a/src/update.c b/src/update.c index 1953711f1f..467352cdf4 100644 --- a/src/update.c +++ b/src/update.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** -** $Id: update.c,v 1.158 2008/01/04 22:01:03 drh Exp $ +** $Id: update.c,v 1.159 2008/01/05 04:06:04 drh Exp $ */ #include "sqliteInt.h" @@ -456,7 +456,7 @@ void sqlite3Update( ** So make the cursor point at the old record. */ sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, iRowid); - sqlite3VdbeAddOp2(v, OP_MemLoad, iRowid, 0); + sqlite3VdbeAddOp2(v, OP_SCopy, iRowid, 0); /* If the record number will change, push the record number as it ** will be after the update. (The old record number is currently diff --git a/src/vdbe.c b/src/vdbe.c index aea4fd33f6..558b75bfdd 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.679 2008/01/04 22:01:03 drh Exp $ +** $Id: vdbe.c,v 1.680 2008/01/05 04:06:04 drh Exp $ */ #include "sqliteInt.h" #include @@ -470,6 +470,7 @@ int sqlite3VdbeExec( Mem *pIn1, *pIn2; /* Input operands */ Mem *pOut; /* Output operand */ int nPop = 0; /* Number of times to pop the stack */ + u8 opProperty; #ifdef VDBE_PROFILE unsigned long long start; /* CPU clock count at start of opcode */ int origPc; /* Program counter at start of opcode */ @@ -596,7 +597,8 @@ int sqlite3VdbeExec( ** then the output is pushed onto the stack. The P2 operand ** is initialized to a NULL. */ - if( (opcodeProperty[pOp->opcode]&OPFLG_OUT2_PRERELEASE)!=0 ){ + opProperty = opcodeProperty[pOp->opcode]; + if( (opProperty & OPFLG_OUT2_PRERELEASE)!=0 ){ assert( pOp->p2>=0 ); if( pOp->p2==0 ){ pOut = ++pTos; @@ -606,6 +608,71 @@ int sqlite3VdbeExec( sqlite3VdbeMemRelease(pOut); } pOut->flags = MEM_Null; + }else + + /* Do common setup for opcodes marked with one of the following + ** combinations of properties. + ** + ** in1 + ** in1 in2 + ** in1 in2 out3 + ** in1 in3 + ** in1 out2 + ** + ** Variables pIn1 and pIn2 are made to point to the first two + ** inputs and pOut points to the output. Variable nPop holds the + ** number of times that the stack should be popped after the + ** the instruction. + */ + if( (opProperty & OPFLG_IN1)!=0 ){ + assert( pOp->p1>=0 ); + if( pOp->p1==0 ){ + pIn1 = pTos; + nPop = 1; + }else{ + assert( pOp->p1<=p->nMem ); + pIn1 = &p->aMem[pOp->p1]; + } + if( (opProperty & OPFLG_IN2)!=0 ){ + assert( pOp->p2>=0 ); + if( pOp->p2==0 ){ + pIn2 = &pTos[-nPop]; + nPop++; + }else{ + assert( pOp->p2<=p->nMem ); + pIn2 = &p->aMem[pOp->p2]; + } + if( (opProperty & OPFLG_OUT3)!=0 ){ + assert( pOp->p3>=0 ); + if( pOp->p3==0 ){ + pTos++; + pOut = &pTos[-nPop]; + pOut->flags = MEM_Null; + }else{ + assert( pOp->p3<=p->nMem ); + pOut = &p->aMem[pOp->p3]; + } + } + }else if( (opProperty & OPFLG_IN3)!=0 ){ + assert( pOp->p3>=0 ); + if( pOp->p3==0 ){ + pIn2 = &pTos[-nPop]; + nPop++; + }else{ + assert( pOp->p3<=p->nMem ); + pIn2 = &p->aMem[pOp->p3]; + } + }else if( (opProperty & OPFLG_OUT2)!=0 ){ + assert( pOp->p2>=0 ); + if( pOp->p2==0 ){ + pTos++; + pOut = &pTos[-nPop]; + pOut->flags = MEM_Null; + }else{ + assert( pOp->p2<=p->nMem ); + pOut = &p->aMem[pOp->p2]; + } + } } switch( pOp->opcode ){ @@ -926,28 +993,77 @@ case OP_Pop: { /* no-push */ break; } -/* Opcode: Dup P1 P2 * +/* Opcode: Move P1 P2 * * * ** -** A copy of the P1-th element of the stack -** is made and pushed onto the top of the stack. -** The top of the stack is element 0. So the -** instruction "Dup 0 0 0" will make a copy of the -** top of the stack. +** Move the value in P1 into P2. If P1 is positive then read from the +** P1-th register. If P1 is zero or negative read from the stack. +** When P1 is 0 read from the top the stack. When P1 is -1 read from +** the next entry down on the stack. And so forth. ** -** If the content of the P1-th element is a dynamically -** allocated string, then a new copy of that string -** is made if P2==0. If P2!=0, then just a pointer -** to the string is copied. +** If P2 is zero, push the new value onto the top of the stack. +** If P2 is positive, write into the P2-th register. ** -** Also see the Pull instruction. +** If P1 is zero then the stack is popped once. The stack is +** unchanged for all other values of P1. The P1 value contains +** a NULL after this operation. */ -case OP_Dup: { - Mem *pFrom = &pTos[-pOp->p1]; - assert( pFrom<=pTos && pFrom>=p->aStack ); - pTos++; - sqlite3VdbeMemShallowCopy(pTos, pFrom, MEM_Ephem); - if( pOp->p2 ){ - Deephemeralize(pTos); +/* Opcode: Copy P1 P2 * * * +** +** Make a copy of P1 into P2. If P1 is positive then read from the +** P1-th register. If P1 is zero or negative read from the stack. +** When P1 is 0 read from the top the stack. When P1 is -1 read from +** the next entry down on the stack. And so forth. +** +** If P2 is zero, push the new value onto the top of the stack. +** If P2 is positive, write into the P2-th register. +** +** This instruction makes a deep copy of the value. A duplicate +** is made of any string or blob constant. See also OP_SCopy. +*/ +/* Opcode: SCopy P1 P2 * * * +** +** Make a shallow copy of P1 into P2. If P1 is positive then read from the +** P1-th register. If P1 is zero or negative read from the stack. +** When P1 is 0 read from the top the stack. When P1 is -1 read from +** the next entry down on the stack. And so forth. +** +** If P2 is zero, push the new value onto the top of the stack. +** If P2 is positive, write into the P2-th register. +** +** This instruction makes a shallow copy of the value. If the value +** is a string or blob, then the copy is only a pointer to the +** original and hence if the original changes so will the copy. +** Worse, if the original is deallocated, the copy becomes invalid. +** Thus the program must guarantee that the original will not change +** during the lifetime of the copy. Use OP_Copy to make a complete +** copy. +*/ +case OP_Move: +case OP_Copy: +case OP_SCopy: { + if( pOp->p1<=0 ){ + pIn1 = &pTos[pOp->p1]; + assert( pIn1>=p->aStack ); + }else{ + assert( pOp->p1<=p->nMem ); + pIn1 = &p->aMem[pOp->p1]; + } + assert( pOp->p2>=0 ); + if( pOp->p2==0 ){ + pOut = ++pTos; + pOut->flags = MEM_Null; + }else{ + assert( pOp->p2<=p->nMem ); + pOut = &p->aMem[pOp->p2]; + } + if( pOp->opcode==OP_Move ){ + rc = sqlite3VdbeMemMove(pOut, pIn1); + if( pOp->p1==0 ) pTos--; + }else{ + sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); + if( pOp->opcode==OP_Copy ){ + Deephemeralize(pOut); + } } break; } @@ -959,8 +1075,6 @@ case OP_Dup: { ** top of the stack is element 0, so "Pull 0 0 0" is ** a no-op. "Pull 1 0 0" swaps the top two elements of ** the stack. -** -** See also the Dup instruction. */ case OP_Pull: { /* no-push */ Mem *pFrom = &pTos[-pOp->p1]; @@ -2681,7 +2795,7 @@ case OP_Transaction: { /* no-push */ break; } -/* Opcode: ReadCookie P1 P2 P3 +/* Opcode: ReadCookie P1 P2 P3 * * ** ** Read cookie number P3 from database P1 and write it into register ** P2 or push it onto the stack if P2==0. @@ -4615,46 +4729,6 @@ case OP_ContextPop: { /* no-push */ } #endif /* #ifndef SQLITE_OMIT_TRIGGER */ -/* Opcode: MemStore P1 P2 * -** -** Write the top of the stack into memory location P1. -** P1 should be a small integer since space is allocated -** for all memory locations between 0 and P1 inclusive. -** -** After the data is stored in the memory location, the -** stack is popped once if P2 is 1. If P2 is zero, then -** the original data remains on the stack. -*/ -case OP_MemStore: { /* no-push */ - assert( pTos>=p->aStack ); - assert( pOp->p1>0 && pOp->p1<=p->nMem ); - rc = sqlite3VdbeMemMove(&p->aMem[pOp->p1], pTos); - pTos--; - - /* If P2 is 0 then fall thru to the next opcode, OP_MemLoad, that will - ** restore the top of the stack to its original value. - */ - if( pOp->p2 ){ - break; - } -} -/* Opcode: MemLoad P1 * * -** -** Push a copy of the value in memory location P1 onto the stack. -** -** If the value is a string, then the value pushed is a pointer to -** the string that is stored in the memory location. If the memory -** location is subsequently changed (using OP_MemStore) then the -** value pushed onto the stack will change too. -*/ -case OP_MemLoad: { - int i = pOp->p1; - assert( i>0 && i<=p->nMem ); - pTos++; - sqlite3VdbeMemShallowCopy(pTos, &p->aMem[i], MEM_Ephem); - break; -} - #ifndef SQLITE_OMIT_AUTOINCREMENT /* Opcode: MemMax P1 P2 * ** @@ -4768,19 +4842,6 @@ case OP_IfMemNull: { /* no-push, jump */ break; } -/* Opcode: MemMove P1 P2 * -** -** Move the content of memory cell P2 over to memory cell P1. -** Any prior content of P1 is erased. Memory cell P2 is left -** containing a NULL. -*/ -case OP_MemMove: { - assert( pOp->p1>0 && pOp->p1<=p->nMem ); - assert( pOp->p2>0 && pOp->p2<=p->nMem ); - rc = sqlite3VdbeMemMove(&p->aMem[pOp->p1], &p->aMem[pOp->p2]); - break; -} - /* Opcode: AggStep P1 P2 P4 ** ** Execute the step function for an aggregate. The @@ -5306,6 +5367,12 @@ default: { *****************************************************************************/ } + /* Pop the stack if necessary */ + if( nPop ){ + popStack(&pTos, nPop); + nPop = 0; + } + /* Make sure the stack limit was not exceeded */ assert( pTos>=&p->aStack[-1] && pTos<=pStackLimit ); diff --git a/src/where.c b/src/where.c index 0dbb614fff..5f512abb00 100644 --- a/src/where.c +++ b/src/where.c @@ -16,7 +16,7 @@ ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** -** $Id: where.c,v 1.273 2008/01/04 22:01:03 drh Exp $ +** $Id: where.c,v 1.274 2008/01/05 04:06:04 drh Exp $ */ #include "sqliteInt.h" @@ -1827,7 +1827,7 @@ static void codeAllEqualityTerms( sqlite3VdbeAddOp2(v, OP_IsNull, termsInMem ? -1 : -(j+1), pLevel->brk); } if( termsInMem ){ - sqlite3VdbeAddOp2(v, OP_MemStore, pLevel->iMem+j+1, 1); + sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem+j+1); } } @@ -1835,7 +1835,7 @@ static void codeAllEqualityTerms( */ if( termsInMem ){ for(j=0; jiMem+j+1, 0); + sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem+j+1, 0); } } } @@ -2362,7 +2362,7 @@ WhereInfo *sqlite3WhereBegin( assert( pEnd->leftCursor==iCur ); sqlite3ExprCode(pParse, pX->pRight, 0); pLevel->iMem = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_MemStore, pLevel->iMem, 1); + sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem); if( pX->op==TK_LT || pX->op==TK_GT ){ testOp = bRev ? OP_Le : OP_Ge; }else{ @@ -2376,7 +2376,7 @@ WhereInfo *sqlite3WhereBegin( pLevel->p2 = start; if( testOp!=OP_Noop ){ sqlite3VdbeAddOp2(v, OP_Rowid, iCur, 0); - sqlite3VdbeAddOp2(v, OP_MemLoad, pLevel->iMem, 0); + sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0); sqlite3VdbeAddOp2(v, testOp, SQLITE_AFF_NUMERIC|0x100, brk); } }else if( pLevel->flags & WHERE_COLUMN_RANGE ){ @@ -2410,7 +2410,7 @@ WhereInfo *sqlite3WhereBegin( ** start key. */ for(j=0; jiMem, 1); + sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem); } }else if( bRev ){ sqlite3VdbeAddOp2(v, OP_Last, iIdxCur, brk); @@ -2493,7 +2493,7 @@ WhereInfo *sqlite3WhereBegin( buildIndexProbe(v, nCol, pIdx); if( bRev ){ pLevel->iMem = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_MemStore, pLevel->iMem, 1); + sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem); testOp = OP_IdxLT; }else{ int op = btmEq ? OP_MoveGe : OP_MoveGt; @@ -2511,7 +2511,7 @@ WhereInfo *sqlite3WhereBegin( */ start = sqlite3VdbeCurrentAddr(v); if( testOp!=OP_Noop ){ - sqlite3VdbeAddOp2(v, OP_MemLoad, pLevel->iMem, 0); + sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0); sqlite3VdbeAddOp2(v, testOp, iIdxCur, nxt); if( (topEq && !bRev) || (!btmEq && bRev) ){ sqlite3VdbeChangeP4(v, -1, "+", P4_STATIC); @@ -2548,7 +2548,7 @@ WhereInfo *sqlite3WhereBegin( ** the search */ buildIndexProbe(v, nEq, pIdx); - sqlite3VdbeAddOp2(v, OP_MemStore, pLevel->iMem, 0); + sqlite3VdbeAddOp2(v, OP_Copy, 0, pLevel->iMem); /* Generate code (1) to move to the first matching element of the table. ** Then generate code (2) that jumps to "nxt" after the cursor is past @@ -2558,13 +2558,13 @@ WhereInfo *sqlite3WhereBegin( if( bRev ){ /* Scan in reverse order */ sqlite3VdbeAddOp2(v, OP_MoveLe, iIdxCur, nxt); - start = sqlite3VdbeAddOp2(v, OP_MemLoad, pLevel->iMem, 0); + start = sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0); sqlite3VdbeAddOp2(v, OP_IdxLT, iIdxCur, nxt); pLevel->op = OP_Prev; }else{ /* Scan in the forward order */ sqlite3VdbeAddOp2(v, OP_MoveGe, iIdxCur, nxt); - start = sqlite3VdbeAddOp2(v, OP_MemLoad, pLevel->iMem, 0); + start = sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0); sqlite3VdbeAddOp4(v, OP_IdxGE, iIdxCur, nxt, 0, "+", P4_STATIC); pLevel->op = OP_Next; } diff --git a/test/incrblob.test b/test/incrblob.test index 46f86e2e59..d64fead727 100644 --- a/test/incrblob.test +++ b/test/incrblob.test @@ -9,7 +9,7 @@ # #*********************************************************************** # -# $Id: incrblob.test,v 1.17 2007/10/09 08:29:32 danielk1977 Exp $ +# $Id: incrblob.test,v 1.18 2008/01/05 04:06:04 drh Exp $ # set testdir [file dirname $argv0] @@ -83,7 +83,6 @@ do_test incrblob-1.3.10 { close $::blob } {} - #------------------------------------------------------------------------ # incrblob-2.*: #