diff --git a/manifest b/manifest index ebe09dacca..658e313c2b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Optimize\strigger\scompilation\sto\savoid\spopulating\sthe\sOLD.*\sand\sNEW.*\spseudo-tables\swith\sdata\sthat\swill\snever\sbe\sused.\sSome\stesting\sto\scome.\s(CVS\s4651) -D 2008-01-01T19:02:09 +C Begin\ssetting\sa\sfoundation\son\swhich\sto\sconvert\sthe\sVM\sfrom\sa\sstack-based\nto\sa\sregister-based\smachine.\s\sEverything\sis\sstill\smostly\sstack\sbased\swith\nthis\scheck-in.\s\sThis\schange\smerely\sbegins\sadding\sinfrastructure\sto\ssupport\na\sregister-based\sarchitecture.\s(CVS\s4652) +D 2008-01-02T00:34:37 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -79,7 +79,7 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4 F sqlite3.pc.in abed4664817e1cd500f2276142c71958087c16bc F src/alter.c 23d18ec53ef27fcb5e5ae9ca050217231ae15a0d -F src/analyze.c fd1a3d756c1a20fca3c505bed0398f4cdca83cb8 +F src/analyze.c cb25936f0148ee65c825a49f8064292a98050a50 F src/attach.c 95658e74e3e0d1cbdb8658817516d4d1467fc13d F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627 F src/btmutex.c 5d39da37c9d1282f3c6f9967afae6a34ee36b7ff @@ -90,13 +90,13 @@ F src/build.c cbfd98ceb95c61c226cd60a845fa7967b66c8931 F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0 F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131 F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6 -F src/delete.c 6c090aeb5e97a224ee1f232a02359ee79e8ab411 +F src/delete.c a4843531af1354882ea7dbe53fa5f46b581ae73c F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b -F src/expr.c d0969aa79a8e12f8ba49ffe97ae671bee47e37dc +F src/expr.c c3fb939d6801071ce19243521ca444eca40b057a F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53 -F src/insert.c 3c82c974150506bed75f58dec3744503bf112dd4 +F src/insert.c 355c482603c8c5151b23c3c7661cf1044ec34d29 F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2 F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35 @@ -127,16 +127,16 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b F src/pager.c 0cb6ccea4b9615627d61d7c4417cedc45776d429 F src/pager.h f504f7ae84060fee0416a853e368d3d113c3d6fa F src/parse.y a780b33ef45dd7b3272319cf91e609d6f109a31c -F src/pragma.c dd5b1983168eacba1a5084571775b904ea95404f +F src/pragma.c 4a7f377a509eb14e35b09d4bf7b808ef647aad0b F src/prepare.c 7aeba7851773fbe3950a26b35d3389bef0eb1c62 F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910 F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da -F src/select.c 247d668f5be042b914ed8e46edf9cdb57a1eca29 +F src/select.c 55b1a99e1d28a6ec3db2870a9f3f932fb3e7cb2a F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c 77895a54c2082157e169c857a2e244525ec25af7 F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb -F src/sqliteInt.h cf993fe510f6a4cdc18e60b80eee3725c2f1001e +F src/sqliteInt.h 942a52122bbffb8a16d606ceb531a3529f3557a1 F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4 F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf @@ -163,21 +163,21 @@ 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 24bdfee77ce9472db91267597225506c31fc3d9b -F src/update.c 59124a9d5d52bb411f6fba6475b93f2f443fc971 +F src/trigger.c f8e2d42cf1782ffc14a9d7cee1d1a406f9b0c8c4 +F src/update.c fee857007be57b68a7539c26cc5563d8fbaf3f82 F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736 F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624 F src/vacuum.c 25ffbd766f25bca099ead1c1e11f5528c86102b8 -F src/vdbe.c b2f1bcd4b9c9db31dbd79f387139d6740627fa8c -F src/vdbe.h 79e09ff13b85457abe437d9814454534ebbc1fe3 -F src/vdbeInt.h 630145b9bfaa19190ab491f52658a7db550f2247 -F src/vdbeapi.c dd2c43317294e0a013e9f634ee4209a3ea459b43 -F src/vdbeaux.c 5bc14ff3da6c6b3b7f643cbc3d50a344e9b599f8 +F src/vdbe.c 56a6e80d3357622305cffe6ea509e5d643e7dadb +F src/vdbe.h a042e6d3b567ac81f182ca5b4639807621355822 +F src/vdbeInt.h 2985f1369273e635898cf5952237efcb3fdb21f3 +F src/vdbeapi.c 4acfaab3e10c99eb66c5332979d7b14a1c3505ae +F src/vdbeaux.c bca64691ad6bb11e45b5ccf494d9f088d23b3575 F src/vdbeblob.c 82f51cdf9b0c0af729732fde48c824e498c0a1ca F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6 F src/vdbemem.c 123994fcd344993d2fb050a83b91b341bbbd08b4 F src/vtab.c f819d55ef638d45e09ce00009d435da8bf16f528 -F src/where.c 4d71db7ee641cd28cdef88cc6149bd3a51d2e671 +F src/where.c 49901aac9ad568c9c92f914150e91c1663f3978d F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/all.test ee350b9ab15b175fc0a8fb51bf2141ed3a3b9cba @@ -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 b51782ccac28598eec7adc9302fe7d1986bfdaf8 -R 904ead844e1f41e01a54c3518029f00d -U danielk1977 -Z 755babd79b5a2ad03f400826316421af +P e08a33ed7255c22ce2805363f44a1d7770acb2dd +R 31f346602d71de9f0cbdcecc99b8f06d +U drh +Z 1c9d96c8f34a418a83b5bab17073581f diff --git a/manifest.uuid b/manifest.uuid index 8c20d9c76c..bfca76ce3a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e08a33ed7255c22ce2805363f44a1d7770acb2dd \ No newline at end of file +051ec01f2799e095516015f2ef0180e50fac387c \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index a0d94683a9..13e3ad34b1 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code associated with the ANALYZE command. ** -** @(#) $Id: analyze.c,v 1.24 2007/11/15 13:10:23 danielk1977 Exp $ +** @(#) $Id: analyze.c,v 1.25 2008/01/02 00:34:37 drh Exp $ */ #ifndef SQLITE_OMIT_ANALYZE #include "sqliteInt.h" @@ -123,7 +123,7 @@ static void analyzeOneTable( */ assert( iDb==sqlite3SchemaToIndex(pParse->db, pIdx->pSchema) ); sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); - VdbeComment((v, "# %s", pIdx->zName)); + VdbeComment((v, "%s", pIdx->zName)); sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum, (char *)pKey, P3_KEYINFO_HANDOFF); nCol = pIdx->nColumn; diff --git a/src/delete.c b/src/delete.c index 77a2c6d822..f2a63d51f7 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.135 2008/01/01 19:02:09 danielk1977 Exp $ +** $Id: delete.c,v 1.136 2008/01/02 00:34:37 drh Exp $ */ #include "sqliteInt.h" @@ -76,7 +76,7 @@ void sqlite3OpenTable( assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName); sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); - VdbeComment((v, "# %s", pTab->zName)); + VdbeComment((v, "%s", pTab->zName)); sqlite3VdbeAddOp(v, opcode, iCur, pTab->tnum); sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol); } @@ -391,8 +391,7 @@ void sqlite3DeleteFrom( ** invoke the callback function. */ if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){ - sqlite3VdbeAddOp(v, OP_MemLoad, memCnt, 0); - sqlite3VdbeAddOp(v, OP_Callback, 1, 0); + sqlite3VdbeAddOp(v, OP_ResultRow, memCnt, 1); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", P3_STATIC); } diff --git a/src/expr.c b/src/expr.c index 7fd53ae6c7..05932e2f2b 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.321 2008/01/01 19:02:09 danielk1977 Exp $ +** $Id: expr.c,v 1.322 2008/01/02 00:34:37 drh Exp $ */ #include "sqliteInt.h" #include @@ -1647,7 +1647,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int mustBeUnique){ sqlite3VdbeAddOp(v, OP_MemInt, 1, iMem); sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); - VdbeComment((v, "# %s", pIdx->zName)); + VdbeComment((v, "%s", pIdx->zName)); sqlite3VdbeOp3(v,OP_OpenRead,iTab,pIdx->tnum,pKey,P3_KEYINFO_HANDOFF); eType = IN_INDEX_INDEX; sqlite3VdbeAddOp(v, OP_SetNumColumns, iTab, pIdx->nColumn); @@ -1806,11 +1806,11 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ if( pExpr->op==TK_SELECT ){ sop = SRT_Mem; sqlite3VdbeAddOp(v, OP_MemNull, iMem, 0); - VdbeComment((v, "# Init subquery result")); + VdbeComment((v, "Init subquery result")); }else{ sop = SRT_Exists; sqlite3VdbeAddOp(v, OP_MemInt, 0, iMem); - VdbeComment((v, "# Init EXISTS result")); + VdbeComment((v, "Init EXISTS result")); } sqlite3ExprDelete(pSel->pLimit); pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &one); @@ -2174,7 +2174,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ sqlite3CodeSubselect(pParse, pExpr); } sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0); - VdbeComment((v, "# load subquery result")); + VdbeComment((v, "load subquery result")); break; } case TK_IN: { @@ -2301,7 +2301,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ assert( pExpr->iColumn == OE_Ignore ); sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->trigStack->ignoreJump); - VdbeComment((v, "# raise(IGNORE)")); + VdbeComment((v, "raise(IGNORE)")); } stackChng = 0; break; @@ -2344,6 +2344,26 @@ void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr){ } #endif +/* +** Generate code to evaluate an expression and store the result in +** a designated register. If the target register number is negative, +** allocate a new register to store the result. Return the target +** register number regardless. +** +** The current implementation is a rough prototype for experimental +** purposes. There are many optimization opportunities here. +*/ +int sqlite3ExprIntoReg(Parse *pParse, Expr *pExpr, int target){ + Vdbe *v = pParse->pVdbe; + if( v==0 ) return -1; + sqlite3ExprCode(pParse, pExpr); + if( target<0 ){ + target = pParse->nMem++; + } + sqlite3VdbeAddOp(v, OP_MemStore, target, 1); + return target; +} + /* ** Generate code that pushes the value of every element of the given ** expression list onto the stack. diff --git a/src/insert.c b/src/insert.c index 7f72e95d44..6e3440deaa 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.198 2008/01/01 19:02:09 danielk1977 Exp $ +** $Id: insert.c,v 1.199 2008/01/02 00:34:37 drh Exp $ */ #include "sqliteInt.h" @@ -129,8 +129,8 @@ static int readsTable(Vdbe *v, int iStartAddr, int iDb, Table *pTab){ } } #ifndef SQLITE_OMIT_VIRTUALTABLE - if( pOp->opcode==OP_VOpen && pOp->p3==(const char*)pTab->pVtab ){ - assert( pOp->p3!=0 ); + if( pOp->opcode==OP_VOpen && pOp->p3.p==(const char*)pTab->pVtab ){ + assert( pOp->p3.p!=0 ); assert( pOp->p3type==P3_VTAB ); return 1; } @@ -875,8 +875,7 @@ void sqlite3Insert( ** invoke the callback function. */ if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){ - sqlite3VdbeAddOp(v, OP_MemLoad, iCntMem, 0); - sqlite3VdbeAddOp(v, OP_Callback, 1, 0); + sqlite3VdbeAddOp(v, OP_ResultRow, iCntMem, 1); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", P3_STATIC); } @@ -1298,7 +1297,7 @@ void sqlite3OpenTableAndIndices( KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); assert( pIdx->pSchema==pTab->pSchema ); sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); - VdbeComment((v, "# %s", pIdx->zName)); + VdbeComment((v, "%s", pIdx->zName)); sqlite3VdbeOp3(v, op, i+base, pIdx->tnum, (char*)pKey, P3_KEYINFO_HANDOFF); } if( pParse->nTab<=base+i ){ @@ -1597,12 +1596,12 @@ static int xferOptimization( sqlite3VdbeAddOp(v, OP_Close, iDest, 0); sqlite3VdbeAddOp(v, OP_Integer, iDbSrc, 0); pKey = sqlite3IndexKeyinfo(pParse, pSrcIdx); - VdbeComment((v, "# %s", pSrcIdx->zName)); + VdbeComment((v, "%s", pSrcIdx->zName)); sqlite3VdbeOp3(v, OP_OpenRead, iSrc, pSrcIdx->tnum, (char*)pKey, P3_KEYINFO_HANDOFF); sqlite3VdbeAddOp(v, OP_Integer, iDbDest, 0); pKey = sqlite3IndexKeyinfo(pParse, pDestIdx); - VdbeComment((v, "# %s", pDestIdx->zName)); + VdbeComment((v, "%s", pDestIdx->zName)); sqlite3VdbeOp3(v, OP_OpenWrite, iDest, pDestIdx->tnum, (char*)pKey, P3_KEYINFO_HANDOFF); addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iSrc, 0); diff --git a/src/pragma.c b/src/pragma.c index 9ab09f1a14..3fe341b8d7 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.153 2007/12/29 13:39:20 danielk1977 Exp $ +** $Id: pragma.c,v 1.154 2008/01/02 00:34:37 drh Exp $ */ #include "sqliteInt.h" #include @@ -147,12 +147,13 @@ static int changeTempStorage(Parse *pParse, const char *zStorageType){ */ static void returnSingleInt(Parse *pParse, const char *zLabel, int value){ Vdbe *v = sqlite3GetVdbe(pParse); - sqlite3VdbeAddOp(v, OP_Integer, value, 0); + int mem = pParse->nMem++; + sqlite3VdbeAddOp(v, OP_MemInt, value, mem); if( pParse->explain==0 ){ sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, P3_STATIC); } - sqlite3VdbeAddOp(v, OP_Callback, 1, 0); + sqlite3VdbeAddOp(v, OP_ResultRow, mem, 1); } #ifndef SQLITE_OMIT_FLAG_PRAGMAS diff --git a/src/select.c b/src/select.c index 142244c0dd..23f2c70a21 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.373 2008/01/01 19:02:09 danielk1977 Exp $ +** $Id: select.c,v 1.374 2008/01/02 00:34:37 drh Exp $ */ #include "sqliteInt.h" @@ -422,7 +422,7 @@ static void codeOffset( sqlite3VdbeAddOp(v, OP_Pop, nPop, 0); } sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue); - VdbeComment((v, "# skip OFFSET records")); + VdbeComment((v, "skip OFFSET records")); sqlite3VdbeJumpHere(v, addr); } } @@ -446,7 +446,7 @@ static void codeDistinct( sqlite3VdbeAddOp(v, OP_Distinct, iTab, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp(v, OP_Pop, N+1, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, addrRepeat); - VdbeComment((v, "# skip indistinct records")); + VdbeComment((v, "skip indistinct records")); sqlite3VdbeAddOp(v, OP_IdxInsert, iTab, 0); } @@ -1710,7 +1710,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ sqlite3ExprCode(pParse, p->pLimit); sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); sqlite3VdbeAddOp(v, OP_MemStore, iLimit, 1); - VdbeComment((v, "# LIMIT counter")); + VdbeComment((v, "LIMIT counter")); sqlite3VdbeAddOp(v, OP_IfMemZero, iLimit, iBreak); sqlite3VdbeAddOp(v, OP_MemLoad, iLimit, 0); } @@ -1721,7 +1721,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ sqlite3ExprCode(pParse, p->pOffset); sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); sqlite3VdbeAddOp(v, OP_MemStore, iOffset, p->pLimit==0); - VdbeComment((v, "# OFFSET counter")); + VdbeComment((v, "OFFSET counter")); addr1 = sqlite3VdbeAddOp(v, OP_IfMemPos, iOffset, 0); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); sqlite3VdbeAddOp(v, OP_Integer, 0, 0); @@ -1737,7 +1737,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp(v, OP_MemStore, iLimit+1, 1); - VdbeComment((v, "# LIMIT+OFFSET")); + VdbeComment((v, "LIMIT+OFFSET")); sqlite3VdbeJumpHere(v, addr2); } } @@ -1887,7 +1887,7 @@ static int multiSelect( p->iOffset = pPrior->iOffset; if( p->iLimit>=0 ){ addr = sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, 0); - VdbeComment((v, "# Jump ahead if LIMIT reached")); + VdbeComment((v, "Jump ahead if LIMIT reached")); } rc = sqlite3Select(pParse, p, eDest, iParm, 0, 0, 0, aff); p->pPrior = pPrior; @@ -3381,9 +3381,9 @@ int sqlite3Select( iBMem = pParse->nMem; pParse->nMem += pGroupBy->nExpr; sqlite3VdbeAddOp(v, OP_MemInt, 0, iAbortFlag); - VdbeComment((v, "# clear abort flag")); + VdbeComment((v, "clear abort flag")); sqlite3VdbeAddOp(v, OP_MemInt, 0, iUseFlag); - VdbeComment((v, "# indicate accumulator empty")); + VdbeComment((v, "indicate accumulator empty")); sqlite3VdbeAddOp(v, OP_Goto, 0, addrInitializeLoop); /* Generate a subroutine that outputs a single row of the result @@ -3395,11 +3395,11 @@ int sqlite3Select( */ addrSetAbort = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp(v, OP_MemInt, 1, iAbortFlag); - VdbeComment((v, "# set abort flag")); + VdbeComment((v, "set abort flag")); sqlite3VdbeAddOp(v, OP_Return, 0, 0); addrOutputRow = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp(v, OP_IfMemPos, iUseFlag, addrOutputRow+2); - VdbeComment((v, "# Groupby result generator entry point")); + VdbeComment((v, "Groupby result generator entry point")); sqlite3VdbeAddOp(v, OP_Return, 0, 0); finalizeAggFunctions(pParse, &sAggInfo); if( pHaving ){ @@ -3412,7 +3412,7 @@ int sqlite3Select( goto select_end; } sqlite3VdbeAddOp(v, OP_Return, 0, 0); - VdbeComment((v, "# end groupby result generator")); + VdbeComment((v, "end groupby result generator")); /* Generate a subroutine that will reset the group-by accumulator */ @@ -3456,7 +3456,7 @@ int sqlite3Select( sqlite3VdbeAddOp(v, OP_IdxInsert, sAggInfo.sortingIdx, 0); sqlite3WhereEnd(pWInfo); sqlite3VdbeAddOp(v, OP_Sort, sAggInfo.sortingIdx, addrEnd); - VdbeComment((v, "# GROUP BY sort")); + VdbeComment((v, "GROUP BY sort")); sAggInfo.useSortingIdx = 1; } @@ -3502,11 +3502,11 @@ int sqlite3Select( sqlite3VdbeAddOp(v, OP_MemMove, iAMem+j, iBMem+j); } sqlite3VdbeAddOp(v, OP_Gosub, 0, addrOutputRow); - VdbeComment((v, "# output one row")); + VdbeComment((v, "output one row")); sqlite3VdbeAddOp(v, OP_IfMemPos, iAbortFlag, addrEnd); - VdbeComment((v, "# check abort flag")); + VdbeComment((v, "check abort flag")); sqlite3VdbeAddOp(v, OP_Gosub, 0, addrReset); - VdbeComment((v, "# reset accumulator")); + VdbeComment((v, "reset accumulator")); /* Update the aggregate accumulators based on the content of ** the current row @@ -3514,7 +3514,7 @@ int sqlite3Select( sqlite3VdbeResolveLabel(v, addrProcessRow); updateAccumulator(pParse, &sAggInfo); sqlite3VdbeAddOp(v, OP_MemInt, 1, iUseFlag); - VdbeComment((v, "# indicate data in accumulator")); + VdbeComment((v, "indicate data in accumulator")); /* End of the loop */ @@ -3528,7 +3528,7 @@ int sqlite3Select( /* Output the final row of result */ sqlite3VdbeAddOp(v, OP_Gosub, 0, addrOutputRow); - VdbeComment((v, "# output final row")); + VdbeComment((v, "output final row")); } /* endif pGroupBy */ else { diff --git a/src/sqliteInt.h b/src/sqliteInt.h index a59ec170f6..f6ff826981 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.627 2008/01/01 19:02:09 danielk1977 Exp $ +** @(#) $Id: sqliteInt.h,v 1.628 2008/01/02 00:34:37 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -1729,6 +1729,7 @@ void sqlite3WhereEnd(WhereInfo*); void sqlite3ExprCodeGetColumn(Vdbe*, Table*, int, int); void sqlite3ExprCode(Parse*, Expr*); void sqlite3ExprCodeAndCache(Parse*, Expr*); +int sqlite3ExprIntoReg(Parse*,Expr*,int); int sqlite3ExprCodeExprList(Parse*, ExprList*); void sqlite3ExprIfTrue(Parse*, Expr*, int, int); void sqlite3ExprIfFalse(Parse*, Expr*, int, int); diff --git a/src/trigger.c b/src/trigger.c index 4748b4ecba..2bde7c2f0d 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -677,7 +677,7 @@ static int codeTriggerProgram( assert( pTriggerStep!=0 ); assert( v!=0 ); sqlite3VdbeAddOp(v, OP_ContextPush, 0, 0); - VdbeComment((v, "# begin trigger %s", pStepList->pTrig->name)); + VdbeComment((v, "begin trigger %s", pStepList->pTrig->name)); while( pTriggerStep ){ orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin; pParse->trigStack->orconf = orconf; @@ -727,7 +727,7 @@ static int codeTriggerProgram( pTriggerStep = pTriggerStep->pNext; } sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0); - VdbeComment((v, "# end trigger %s", pStepList->pTrig->name)); + VdbeComment((v, "end trigger %s", pStepList->pTrig->name)); return 0; } diff --git a/src/update.c b/src/update.c index 2ed1142126..0edc861b44 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.145 2008/01/01 19:02:09 danielk1977 Exp $ +** $Id: update.c,v 1.146 2008/01/02 00:34:37 drh Exp $ */ #include "sqliteInt.h" @@ -59,12 +59,13 @@ void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i){ sqlite3_value *pValue; u8 enc = ENC(sqlite3VdbeDb(v)); Column *pCol = &pTab->aCol[i]; + VdbeComment((v, "%s.%s", pTab->zName, pCol->zName)); assert( inCol ); - sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc, pCol->affinity, &pValue); + sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc, + pCol->affinity, &pValue); if( pValue ){ + sqlite3VdbeAddOp(v, OP_DfltValue, 0, 0); sqlite3VdbeChangeP3(v, -1, (const char *)pValue, P3_MEM); - }else{ - VdbeComment((v, "# %s.%s", pTab->zName, pCol->zName)); } } } @@ -555,8 +556,7 @@ void sqlite3Update( ** invoke the callback function. */ if( db->flags & SQLITE_CountRows && !pParse->trigStack && pParse->nested==0 ){ - sqlite3VdbeAddOp(v, OP_MemLoad, memCnt, 0); - sqlite3VdbeAddOp(v, OP_Callback, 1, 0); + sqlite3VdbeAddOp(v, OP_ResultRow, memCnt, 1); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", P3_STATIC); } diff --git a/src/vdbe.c b/src/vdbe.c index e9d69af8df..4c1071e21a 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.661 2007/12/17 16:20:07 drh Exp $ +** $Id: vdbe.c,v 1.662 2008/01/02 00:34:37 drh Exp $ */ #include "sqliteInt.h" #include @@ -477,7 +477,7 @@ int sqlite3VdbeExec( popStack(&pTos, p->popStack); p->popStack = 0; } - p->resOnStack = 0; + p->pResultSet = 0; db->busyHandler.nBusy = 0; CHECK_FOR_INTERRUPT; sqlite3VdbeIOTraceSql(p); @@ -679,8 +679,8 @@ case OP_Halt: { /* no-push */ p->rc = pOp->p1; p->pc = pc; p->errorAction = pOp->p2; - if( pOp->p3 ){ - sqlite3SetString(&p->zErrMsg, pOp->p3, (char*)0); + if( pOp->p3.p ){ + sqlite3SetString(&p->zErrMsg, pOp->p3.p, (char*)0); } rc = sqlite3VdbeHalt(p); assert( rc==SQLITE_BUSY || rc==SQLITE_OK ); @@ -733,9 +733,9 @@ case OP_Integer: { */ case OP_Int64: { pTos++; - assert( pOp->p3!=0 ); + assert( pOp->p3.p!=0 ); pTos->flags = MEM_Int; - memcpy(&pTos->u.i, pOp->p3, 8); + memcpy(&pTos->u.i, pOp->p3.p, 8); break; } @@ -747,7 +747,7 @@ case OP_Int64: { case OP_Real: { /* same as TK_FLOAT, */ pTos++; pTos->flags = MEM_Real; - memcpy(&pTos->r, pOp->p3, 8); + memcpy(&pTos->r, pOp->p3.p, 8); break; } @@ -757,23 +757,23 @@ case OP_Real: { /* same as TK_FLOAT, */ ** into an OP_String before it is executed for the first time. */ case OP_String8: { /* same as TK_STRING */ - assert( pOp->p3!=0 ); + assert( pOp->p3.p!=0 ); pOp->opcode = OP_String; - pOp->p1 = strlen(pOp->p3); + pOp->p1 = strlen(pOp->p3.p); #ifndef SQLITE_OMIT_UTF16 if( encoding!=SQLITE_UTF8 ){ pTos++; - sqlite3VdbeMemSetStr(pTos, pOp->p3, -1, SQLITE_UTF8, SQLITE_STATIC); + sqlite3VdbeMemSetStr(pTos, pOp->p3.p, -1, SQLITE_UTF8, SQLITE_STATIC); if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pTos, encoding) ) goto no_mem; if( SQLITE_OK!=sqlite3VdbeMemDynamicify(pTos) ) goto no_mem; pTos->flags &= ~(MEM_Dyn); pTos->flags |= MEM_Static; if( pOp->p3type==P3_DYNAMIC ){ - sqlite3_free(pOp->p3); + sqlite3_free(pOp->p3.p); } pOp->p3type = P3_DYNAMIC; - pOp->p3 = pTos->z; + pOp->p3.p = pTos->z; pOp->p1 = pTos->n; if( pOp->p1>SQLITE_MAX_LENGTH ){ goto too_big; @@ -793,9 +793,9 @@ case OP_String8: { /* same as TK_STRING */ */ case OP_String: { pTos++; - assert( pOp->p3!=0 ); + assert( pOp->p3.p!=0 ); pTos->flags = MEM_Str|MEM_Static|MEM_Term; - pTos->z = pOp->p3; + pTos->z = pOp->p3.p; pTos->n = pOp->p1; pTos->enc = encoding; break; @@ -824,24 +824,24 @@ case OP_Null: { */ case OP_HexBlob: { /* same as TK_BLOB */ pOp->opcode = OP_Blob; - pOp->p1 = strlen(pOp->p3)/2; + pOp->p1 = strlen(pOp->p3.p)/2; if( pOp->p1>SQLITE_MAX_LENGTH ){ goto too_big; } if( pOp->p1 ){ - char *zBlob = sqlite3HexToBlob(db, pOp->p3); + char *zBlob = sqlite3HexToBlob(db, pOp->p3.p); if( !zBlob ) goto no_mem; if( pOp->p3type==P3_DYNAMIC ){ - sqlite3_free(pOp->p3); + sqlite3_free(pOp->p3.p); } - pOp->p3 = zBlob; + pOp->p3.p = zBlob; pOp->p3type = P3_DYNAMIC; }else{ if( pOp->p3type==P3_DYNAMIC ){ - sqlite3_free(pOp->p3); + sqlite3_free(pOp->p3.p); } pOp->p3type = P3_STATIC; - pOp->p3 = ""; + pOp->p3.p = ""; } /* Fall through to the next case, OP_Blob. */ @@ -859,7 +859,7 @@ case OP_HexBlob: { /* same as TK_BLOB */ case OP_Blob: { pTos++; assert( pOp->p1 <= SQLITE_MAX_LENGTH ); - sqlite3VdbeMemSetStr(pTos, pOp->p3, pOp->p1, 0, 0); + sqlite3VdbeMemSetStr(pTos, pOp->p3.p, pOp->p1, 0, 0); pTos->enc = encoding; break; } @@ -997,7 +997,7 @@ case OP_Callback: { /* no-push */ ** the stack. Note that ephemeral data is never stored in memory ** cells so we do not have to worry about them. */ - pFirstColumn = &pTos[0-pOp->p1]; + pFirstColumn = &pTos[1-pOp->p1]; for(pMem = p->aStack; pMemresOnStack = 1; + p->pResultSet = pFirstColumn; p->nCallback++; p->popStack = pOp->p1; p->pc = pc + 1; @@ -1026,6 +1026,56 @@ case OP_Callback: { /* no-push */ goto vdbe_return; } +/* Opcode: ResultRow P1 P2 * +** +** The registers P1 throught P1+P2-1 contain a single row of +** results. This opcode causes the sqlite3_step() call to terminate +** with an SQLITE_ROW return code and it sets up the sqlite3_stmt +** structure to provide access to the top P1 values as the result +** row. When the sqlite3_step() function is run again, the top P1 +** values will be automatically popped from the stack before the next +** instruction executes. +*/ +case OP_ResultRow: { /* no-push */ + Mem *pMem; + int i; + assert( p->nResColumn==pOp->p2 ); + assert( pOp->p1>=0 ); + assert( pOp->p1+pOp->p2nMem ); + + /* Data in the pager might be moved or changed out from under us + ** in between the return from this sqlite3_step() call and the + ** next call to sqlite3_step(). So deephermeralize everything on + ** the stack. Note that ephemeral data is never stored in memory + ** cells so we do not have to worry about them. + */ + for(pMem = p->aStack; pMem<=pTos; pMem++){ + Deephemeralize(pMem); + } + + /* Invalidate all ephemeral cursor row caches */ + p->cacheCtr = (p->cacheCtr + 2)|1; + + /* Make sure the results of the current row are \000 terminated + ** and have an assigned type. The results are deephemeralized as + ** as side effect. + */ + pMem = p->pResultSet = &p->aMem[pOp->p1]; + for(i=0; ip2; i++){ + sqlite3VdbeMemNulTerminate(&pMem[i]); + storeTypeInfo(&pMem[i], encoding); + } + + /* Return SQLITE_ROW + */ + p->nCallback++; + p->popStack = 0; + p->pc = pc + 1; + p->pTos = pTos; + rc = SQLITE_ROW; + goto vdbe_return; +} + /* Opcode: Concat P1 P2 * ** ** Look at the first P1+2 elements of the stack. Append them all @@ -1288,10 +1338,10 @@ case OP_Function: { assert( pOp->p3type==P3_FUNCDEF || pOp->p3type==P3_VDBEFUNC ); if( pOp->p3type==P3_FUNCDEF ){ - ctx.pFunc = (FuncDef*)pOp->p3; + ctx.pFunc = (FuncDef*)pOp->p3.p; ctx.pVdbeFunc = 0; }else{ - ctx.pVdbeFunc = (VdbeFunc*)pOp->p3; + ctx.pVdbeFunc = (VdbeFunc*)pOp->p3.p; ctx.pFunc = ctx.pVdbeFunc->pFunc; } @@ -1304,7 +1354,7 @@ case OP_Function: { assert( pOp>p->aOp ); assert( pOp[-1].p3type==P3_COLLSEQ ); assert( pOp[-1].opcode==OP_CollSeq ); - ctx.pColl = (CollSeq *)pOp[-1].p3; + ctx.pColl = (CollSeq *)pOp[-1].p3.p; } if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; (*ctx.pFunc->xFunc)(&ctx, n, apVal); @@ -1329,7 +1379,7 @@ case OP_Function: { */ if( ctx.pVdbeFunc ){ sqlite3VdbeDeleteAuxData(ctx.pVdbeFunc, pOp->p1); - pOp->p3 = (char *)ctx.pVdbeFunc; + pOp->p3.p = (char *)ctx.pVdbeFunc; pOp->p3type = P3_VDBEFUNC; } @@ -1724,10 +1774,10 @@ case OP_Ge: { /* same as TK_GE, no-push */ applyAffinity(pTos, affinity, encoding); } - assert( pOp->p3type==P3_COLLSEQ || pOp->p3==0 ); + assert( pOp->p3type==P3_COLLSEQ || pOp->p3.p==0 ); ExpandBlob(pNos); ExpandBlob(pTos); - res = sqlite3MemCompare(pNos, pTos, (CollSeq*)pOp->p3); + res = sqlite3MemCompare(pNos, pTos, (CollSeq*)pOp->p3.p); switch( pOp->opcode ){ case OP_Eq: res = res==0; break; case OP_Ne: res = res!=0; break; @@ -1982,19 +2032,22 @@ case OP_SetNumColumns: { /* no-push */ ** ** Interpret the data that cursor P1 points to as a structure built using ** the MakeRecord instruction. (See the MakeRecord opcode for additional -** information about the format of the data.) Push onto the stack the value -** of the P2-th column contained in the data. If there are less that (P2+1) -** values in the record, push a NULL onto the stack. +** information about the format of the data.) Extract the P2-th column +** from this record. If there are less that (P2+1) +** values in the record, extract a NULL. +** +** The value extracted is pushed onto the stack. Or if P3 is an integer +** register number, then the value is written into that register. ** ** If the KeyAsData opcode has previously executed on this cursor, then the ** field might be extracted from the key rather than the data. ** -** If the column contains fewer than P2 fields, then push a NULL. Or -** if P3 is of type P3_MEM, then push the P3 value. The P3 value will -** be default value for a column that has been added using the ALTER TABLE -** ADD COLUMN command. If P3 is an ordinary string, just push a NULL. -** When P3 is a string it is really just a comment describing the value -** to be pushed, not a default value. +** If the column contains fewer than P2 fields, then extract a NULL. Or +** if the next instruction is OP_DfltValue then the P3 argument to the +** OP_DfltValue instruction will be a P3_MEM. Use the P3 argument of +** the OP_DfltValue instruction as the extracted value instead of NULL. +** The OP_DfltValue P3 value will be a default value for a column +** that has been added using the ALTER TABLE ADD COLUMN command. */ case OP_Column: { u32 payloadSize; /* Number of bytes in the record */ @@ -2009,12 +2062,18 @@ case OP_Column: { int len; /* The length of the serialized data for the column */ int i; /* Loop counter */ char *zData; /* Part of the record being decoded */ + Mem *pDest; /* Where to write the extracted value */ Mem sMem; /* For storing the record being decoded */ sMem.flags = 0; assert( p1nCursor ); - pTos++; - pTos->flags = MEM_Null; + if( pOp->p3type==P3_INT32 ){ + assert( pOp->p3.i>=0 && pOp->p3.inMem ); + pDest = &p->aMem[pOp->p3.i]; + }else{ + pDest = ++pTos; + } + sqlite3VdbeMemSetNull(pDest); /* This block sets the variable payloadSize to be the total number of ** bytes in the record. @@ -2071,8 +2130,8 @@ case OP_Column: { /* If payloadSize is 0, then just push a NULL onto the stack. */ if( payloadSize==0 ){ - assert( pTos->flags==MEM_Null ); - break; + assert( pDest->flags==MEM_Null ); + goto op_column_out; } if( payloadSize>SQLITE_MAX_LENGTH ){ goto too_big; @@ -2197,38 +2256,52 @@ case OP_Column: { } zData = sMem.z; } - sqlite3VdbeSerialGet((u8*)zData, aType[p2], pTos); - pTos->enc = encoding; + sqlite3VdbeSerialGet((u8*)zData, aType[p2], pDest); + pDest->enc = encoding; }else{ - if( pOp->p3type==P3_MEM ){ - sqlite3VdbeMemShallowCopy(pTos, (Mem *)(pOp->p3), MEM_Static); + if( pOp[1].opcode==OP_DfltValue ){ + assert( pOp[1].p3type==P3_MEM ); + sqlite3VdbeMemShallowCopy(pDest, (Mem *)(pOp[1].p3.p), MEM_Static); }else{ - pTos->flags = MEM_Null; + assert( pDest->flags==MEM_Null ); } } /* If we dynamically allocated space to hold the data (in the ** sqlite3VdbeMemFromBtree() call above) then transfer control of that - ** dynamically allocated space over to the pTos structure. + ** dynamically allocated space over to the pDest structure. ** This prevents a memory copy. */ if( (sMem.flags & MEM_Dyn)!=0 ){ - assert( pTos->flags & MEM_Ephem ); - assert( pTos->flags & (MEM_Str|MEM_Blob) ); - assert( pTos->z==sMem.z ); + assert( pDest->flags & MEM_Ephem ); + assert( pDest->flags & (MEM_Str|MEM_Blob) ); + assert( pDest->z==sMem.z ); assert( sMem.flags & MEM_Term ); - pTos->flags &= ~MEM_Ephem; - pTos->flags |= MEM_Dyn|MEM_Term; + pDest->flags &= ~MEM_Ephem; + pDest->flags |= MEM_Dyn|MEM_Term; } - /* pTos->z might be pointing to sMem.zShort[]. Fix that so that we + /* pDest->z might be pointing to sMem.zShort[]. Fix that so that we ** can abandon sMem */ - rc = sqlite3VdbeMemMakeWriteable(pTos); + rc = sqlite3VdbeMemMakeWriteable(pDest); op_column_out: + if( pOp[1].opcode==OP_DfltValue ){ + pc++; + } break; } +/* Opcode: DfltValue * * P3 +** +** This instruction always follows an OP_Column. This instruction +** does nothing by itself. It is just a place holder for the default +** value for the previous OP_Column instruction. +*/ +case OP_DfltValue: { /* no-push */ + assert( 0 ); +} + /* Opcode: MakeRecord P1 P2 P3 ** ** Convert the top abs(P1) entries of the stack into a single entry @@ -2265,6 +2338,24 @@ op_column_out: ** and appends that extra integer to the end of the record as a varint. ** This results in an index key. */ +/* +** Opcode: RegMakeRec P1 P2 P3 +** +** Works like OP_MakeRecord except data is taken from registers +** rather than from the stack. The P1 register is an integer which +** is the number of register to use in building the new record. +** Data is taken from P1+1, P1+2, ..., P1+mem[P1]. +*/ +/* +** Opcode: RegMakeIRec P1 P2 P3 +** +** Works like OP_MakeIdxRec except data is taken from registers +** rather than from the stack. The P1 register is an integer which +** is the number of register to use in building the new record. +** Data is taken from P1+1, P1+2, ..., P1+mem[P1]. +*/ +case OP_RegMakeRec: +case OP_RegMakeIRec: case OP_MakeIdxRec: case OP_MakeRecord: { /* Assuming the record contains N fields, the record format looks @@ -2302,14 +2393,31 @@ case OP_MakeRecord: { int i; /* Space used in zNewRecord[] */ char zTemp[NBFS]; /* Space to hold small records */ - leaveOnStack = ((pOp->p1<0)?1:0); - nField = pOp->p1 * (leaveOnStack?-1:1); + if( pOp->p1<0 ){ + assert( pOp->opcode==OP_MakeRecord || pOp->opcode==OP_MakeIdxRec ); + leaveOnStack = 1; + nField = -pOp->p1; + }else{ + leaveOnStack = 0; + nField = pOp->p1; + } jumpIfNull = pOp->p2; - addRowid = pOp->opcode==OP_MakeIdxRec; - zAffinity = pOp->p3; + addRowid = pOp->opcode==OP_MakeIdxRec || pOp->opcode==OP_RegMakeIRec; + zAffinity = pOp->p3.p; - pData0 = &pTos[1-nField]; - assert( pData0>=p->aStack ); + if( pOp->opcode==OP_RegMakeRec || pOp->opcode==OP_RegMakeIRec ){ + Mem *pCount; + assert( nField>=0 && nFieldnMem ); + pCount = &p->aMem[nField]; + assert( pCount->flags & MEM_Int ); + assert( pCount->u.i>=0 && pCount->u.i+nFieldnMem ); + assert( leaveOnStack==1 ); + nField = pCount->u.i; + pData0 = &pCount[1]; + }else{ + pData0 = &pTos[1-nField]; + assert( pData0>=p->aStack ); + } containsNull = 0; file_format = p->minWriteFileFormat; @@ -2771,10 +2879,10 @@ case OP_OpenWrite: { /* no-push */ /* We always provide a key comparison function. If the table being ** opened is of type INTKEY, the comparision function will be ignored. */ rc = sqlite3BtreeCursor(pX, p2, wrFlag, - sqlite3VdbeRecordCompare, pOp->p3, + sqlite3VdbeRecordCompare, pOp->p3.p, &pCur->pCursor); if( pOp->p3type==P3_KEYINFO ){ - pCur->pKeyInfo = (KeyInfo*)pOp->p3; + pCur->pKeyInfo = (KeyInfo*)pOp->p3.p; pCur->pIncrKey = &pCur->pKeyInfo->incrKey; pCur->pKeyInfo->enc = ENC(p->db); }else{ @@ -2869,15 +2977,15 @@ case OP_OpenEphemeral: { /* no-push */ ** opening it. If a transient table is required, just use the ** automatically created table with root-page 1 (an INTKEY table). */ - if( pOp->p3 ){ + if( pOp->p3.p ){ int pgno; assert( pOp->p3type==P3_KEYINFO ); rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_ZERODATA); if( rc==SQLITE_OK ){ assert( pgno==MASTER_ROOT+1 ); rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, sqlite3VdbeRecordCompare, - pOp->p3, &pCx->pCursor); - pCx->pKeyInfo = (KeyInfo*)pOp->p3; + pOp->p3.p, &pCx->pCursor); + pCx->pKeyInfo = (KeyInfo*)pOp->p3.p; pCx->pKeyInfo->enc = ENC(p->db); pCx->pIncrKey = &pCx->pKeyInfo->incrKey; } @@ -3546,9 +3654,9 @@ case OP_Insert: { /* no-push */ pC->cacheStatus = CACHE_STALE; /* Invoke the update-hook if required. */ - if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p3 ){ + if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p3.p ){ const char *zDb = db->aDb[pC->iDb].zName; - const char *zTbl = pOp->p3; + const char *zTbl = pOp->p3.p; int op = ((pOp->p2 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); assert( pC->isTable ); db->xUpdateCallback(db->pUpdateArg, op, zDb, zTbl, iKey); @@ -3586,7 +3694,7 @@ case OP_Delete: { /* no-push */ /* If the update-hook will be invoked, set iKey to the rowid of the ** row being deleted. */ - if( db->xUpdateCallback && pOp->p3 ){ + if( db->xUpdateCallback && pOp->p3.p ){ assert( pC->isTable ); if( pC->rowidIsValid ){ iKey = pC->lastRowid; @@ -3606,9 +3714,9 @@ case OP_Delete: { /* no-push */ pC->cacheStatus = CACHE_STALE; /* Invoke the update-hook if required. */ - if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p3 ){ + if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p3.p ){ const char *zDb = db->aDb[pC->iDb].zName; - const char *zTbl = pOp->p3; + const char *zTbl = pOp->p3.p; db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, iKey); assert( pC->iDb>=0 ); } @@ -4058,8 +4166,8 @@ case OP_IdxGE: { /* no-push */ assert( pTos->flags & MEM_Blob ); /* Created using OP_MakeRecord */ assert( pC->deferredMoveto==0 ); ExpandBlob(pTos); - *pC->pIncrKey = pOp->p3!=0; - assert( pOp->p3==0 || pOp->opcode!=OP_IdxGT ); + *pC->pIncrKey = pOp->p3.p!=0; + assert( pOp->p3.p==0 || pOp->opcode!=OP_IdxGT ); rc = sqlite3VdbeIdxKeyCompare(pC, pTos->n, (u8*)pTos->z, &res); *pC->pIncrKey = 0; if( rc!=SQLITE_OK ){ @@ -4151,9 +4259,9 @@ case OP_Clear: { /* no-push */ */ #if 0 Btree *pBt = db->aDb[pOp->p2].pBt; - if( db->xUpdateCallback && pOp->p3 ){ + if( db->xUpdateCallback && pOp->p3.p ){ const char *zDb = db->aDb[pOp->p2].zName; - const char *zTbl = pOp->p3; + const char *zTbl = pOp->p3.p; BtCursor *pCur = 0; int fin = 0; @@ -4259,7 +4367,7 @@ case OP_ParseSchema: { /* no-push */ initData.pzErrMsg = &p->zErrMsg; zSql = sqlite3MPrintf(db, "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s", - db->aDb[iDb].zName, zMaster, pOp->p3); + db->aDb[iDb].zName, zMaster, pOp->p3.p); if( zSql==0 ) goto no_mem; sqlite3SafetyOff(db); assert( db->init.busy==0 ); @@ -4299,7 +4407,7 @@ case OP_LoadAnalysis: { /* no-push */ ** schema consistent with what is on disk. */ case OP_DropTable: { /* no-push */ - sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p3); + sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p3.p); break; } @@ -4311,7 +4419,7 @@ case OP_DropTable: { /* no-push */ ** schema consistent with what is on disk. */ case OP_DropIndex: { /* no-push */ - sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p3); + sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p3.p); break; } @@ -4323,7 +4431,7 @@ case OP_DropIndex: { /* no-push */ ** schema consistent with what is on disk. */ case OP_DropTrigger: { /* no-push */ - sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p3); + sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p3.p); break; } @@ -4669,7 +4777,7 @@ case OP_AggStep: { /* no-push */ apVal[i] = pRec; storeTypeInfo(pRec, encoding); } - ctx.pFunc = (FuncDef*)pOp->p3; + ctx.pFunc = (FuncDef*)pOp->p3.p; assert( pOp->p1>=0 && pOp->p1nMem ); ctx.pMem = pMem = &p->aMem[pOp->p1]; pMem->n++; @@ -4683,7 +4791,7 @@ case OP_AggStep: { /* no-push */ assert( pOp>p->aOp ); assert( pOp[-1].p3type==P3_COLLSEQ ); assert( pOp[-1].opcode==OP_CollSeq ); - ctx.pColl = (CollSeq *)pOp[-1].p3; + ctx.pColl = (CollSeq *)pOp[-1].p3.p; } (ctx.pFunc->xStep)(&ctx, n, apVal); popStack(&pTos, n); @@ -4712,7 +4820,7 @@ case OP_AggFinal: { /* no-push */ assert( pOp->p1>=0 && pOp->p1nMem ); pMem = &p->aMem[pOp->p1]; assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); - rc = sqlite3VdbeMemFinalize(pMem, (FuncDef*)pOp->p3); + rc = sqlite3VdbeMemFinalize(pMem, (FuncDef*)pOp->p3.p); if( rc==SQLITE_ERROR ){ sqlite3SetString(&p->zErrMsg, sqlite3_value_text(pMem), (char*)0); } @@ -4805,7 +4913,7 @@ case OP_TableLock: { /* no-push */ assert( (p->btreeMask & (1<aDb[p1].pBt, pOp->p2, isWriteLock); if( rc==SQLITE_LOCKED ){ - const char *z = (const char *)pOp->p3; + const char *z = (const char *)pOp->p3.p; sqlite3SetString(&p->zErrMsg, "database table is locked: ", z, (char*)0); } break; @@ -4819,7 +4927,7 @@ case OP_TableLock: { /* no-push */ ** for that table. */ case OP_VBegin: { /* no-push */ - rc = sqlite3VtabBegin(db, (sqlite3_vtab *)pOp->p3); + rc = sqlite3VtabBegin(db, (sqlite3_vtab *)pOp->p3.p); break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -4831,7 +4939,7 @@ case OP_VBegin: { /* no-push */ ** for that table. */ case OP_VCreate: { /* no-push */ - rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p3, &p->zErrMsg); + rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p3.p, &p->zErrMsg); break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -4844,7 +4952,7 @@ case OP_VCreate: { /* no-push */ */ case OP_VDestroy: { /* no-push */ p->inVtabMethod = 2; - rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p3); + rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p3.p); p->inVtabMethod = 0; break; } @@ -4861,7 +4969,7 @@ case OP_VOpen: { /* no-push */ Cursor *pCur = 0; sqlite3_vtab_cursor *pVtabCursor = 0; - sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3); + sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3.p); sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule; assert(pVtab && pModule); @@ -4935,7 +5043,7 @@ case OP_VFilter: { /* no-push */ if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; p->inVtabMethod = 1; - rc = pModule->xFilter(pCur->pVtabCursor, pTos->u.i, pOp->p3, nArg, apArg); + rc = pModule->xFilter(pCur->pVtabCursor, pTos->u.i, pOp->p3.p, nArg, apArg); p->inVtabMethod = 0; if( rc==SQLITE_OK ){ res = pModule->xEof(pCur->pVtabCursor); @@ -5080,7 +5188,7 @@ case OP_VNext: { /* no-push */ ** to the xRename method. */ case OP_VRename: { /* no-push */ - sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3); + sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3.p); assert( pVtab->pModule->xRename ); Stringify(pTos, encoding); @@ -5121,7 +5229,7 @@ case OP_VRename: { /* no-push */ ** is set to the value of the rowid for the row just inserted. */ case OP_VUpdate: { /* no-push */ - sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3); + sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3.p); sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule; int nArg = pOp->p2; assert( pOp->p3type==P3_VTAB ); diff --git a/src/vdbe.h b/src/vdbe.h index eee9db2a0e..7c4b6caf54 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -15,7 +15,7 @@ ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** -** $Id: vdbe.h,v 1.115 2007/11/14 06:48:48 danielk1977 Exp $ +** $Id: vdbe.h,v 1.116 2008/01/02 00:34:37 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ @@ -35,10 +35,16 @@ typedef struct Vdbe Vdbe; */ struct VdbeOp { u8 opcode; /* What operation to perform */ + char p3type; /* One of the P3_xxx constants defined below */ int p1; /* First operand */ int p2; /* Second parameter (often the jump destination) */ - char *p3; /* Third parameter */ - int p3type; /* One of the P3_xxx constants defined below */ + union { /* Third parameter */ + int i; /* Integer value if p3type==P3_INT32 */ + char *p; /* A pointer for all other value sof p3type */ + } p3; +#ifdef SQLITE_DEBUG + char *zComment; /* Comment to improve readability */ +#endif #ifdef VDBE_PROFILE int cnt; /* Number of times this instruction was executed */ long long cycles; /* Total time spend executing this instruction */ @@ -74,6 +80,7 @@ typedef struct VdbeOpList VdbeOpList; #define P3_MPRINTF (-11) /* P3 is a string obtained from sqlite3_mprintf() */ #define P3_REAL (-12) /* P3 is a 64-bit floating point value */ #define P3_INT64 (-13) /* P3 is a 64-bit signed integer */ +#define P3_INT32 (-14) /* P3 is a 32-bit signed integer */ /* When adding a P3 argument using P3_KEYINFO, a copy of the KeyInfo structure ** is made. That copy is freed when the Vdbe is finalized. But if the @@ -116,6 +123,7 @@ typedef struct VdbeOpList VdbeOpList; Vdbe *sqlite3VdbeCreate(sqlite3*); int sqlite3VdbeAddOp(Vdbe*,int,int,int); int sqlite3VdbeOp3(Vdbe*,int,int,int,const char *zP3,int); +int sqlite3VdbeOp3Int(Vdbe*,int,int,int,int); int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1); void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); diff --git a/src/vdbeInt.h b/src/vdbeInt.h index a807bdda33..4c4111f23a 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -323,7 +323,7 @@ struct Vdbe { char **azResColumn; /* Values for one row of result */ int popStack; /* Pop the stack this much on entry to VdbeExec() */ char *zErrMsg; /* Error message written here */ - u8 resOnStack; /* True if there are result values on the stack */ + Mem *pResultSet; /* Pointer to an array of results */ u8 explain; /* True if EXPLAIN present on SQL command */ u8 changeCntOn; /* True to update the change-counter */ u8 aborted; /* True if ROLLBACK in another VM causes an abort */ diff --git a/src/vdbeapi.c b/src/vdbeapi.c index e340f27a8a..eb854c43fe 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -293,10 +293,10 @@ static int sqlite3Step(Vdbe *p){ if( db->xTrace && !db->init.busy ){ assert( p->nOp>0 ); assert( p->aOp[p->nOp-1].opcode==OP_Noop ); - assert( p->aOp[p->nOp-1].p3!=0 ); + assert( p->aOp[p->nOp-1].p3.p!=0 ); assert( p->aOp[p->nOp-1].p3type==P3_DYNAMIC ); sqlite3SafetyOff(db); - db->xTrace(db->pTraceArg, p->aOp[p->nOp-1].p3); + db->xTrace(db->pTraceArg, p->aOp[p->nOp-1].p3.p); if( sqlite3SafetyOn(db) ){ p->rc = SQLITE_MISUSE; return SQLITE_MISUSE; @@ -314,7 +314,7 @@ static int sqlite3Step(Vdbe *p){ */ #ifdef SQLITE_DEBUG if( (db->flags & SQLITE_SqlTrace)!=0 ){ - sqlite3DebugPrintf("SQL-trace: %s\n", p->aOp[p->nOp-1].p3); + sqlite3DebugPrintf("SQL-trace: %s\n", p->aOp[p->nOp-1].p3.p); } #endif /* SQLITE_DEBUG */ @@ -345,9 +345,9 @@ static int sqlite3Step(Vdbe *p){ elapseTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0 - p->startTime; assert( p->nOp>0 ); assert( p->aOp[p->nOp-1].opcode==OP_Noop ); - assert( p->aOp[p->nOp-1].p3!=0 ); + assert( p->aOp[p->nOp-1].p3.p!=0 ); assert( p->aOp[p->nOp-1].p3type==P3_DYNAMIC ); - db->xProfile(db->pProfileArg, p->aOp[p->nOp-1].p3, elapseTime); + db->xProfile(db->pProfileArg, p->aOp[p->nOp-1].p3.p, elapseTime); } #endif @@ -564,7 +564,7 @@ int sqlite3_column_count(sqlite3_stmt *pStmt){ */ int sqlite3_data_count(sqlite3_stmt *pStmt){ Vdbe *pVm = (Vdbe *)pStmt; - if( pVm==0 || !pVm->resOnStack ) return 0; + if( pVm==0 || pVm->pResultSet==0 ) return 0; return pVm->nResColumn; } @@ -581,10 +581,10 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){ Mem *pOut; pVm = (Vdbe *)pStmt; - if( pVm && pVm->resOnStack && inResColumn && i>=0 ){ + if( pVm && pVm->pResultSet!=0 && inResColumn && i>=0 ){ sqlite3_mutex_enter(pVm->db->mutex); vals = sqlite3_data_count(pStmt); - pOut = &pVm->pTos[(1-vals)+i]; + pOut = &pVm->pResultSet[i]; }else{ static const Mem nullMem = {{0}, 0.0, 0, "", 0, MEM_Null, SQLITE_NULL }; if( pVm->db ){ @@ -1001,7 +1001,7 @@ static void createVarMap(Vdbe *p){ for(j=0, pOp=p->aOp; jnOp; j++, pOp++){ if( pOp->opcode==OP_Variable ){ assert( pOp->p1>0 && pOp->p1<=p->nVar ); - p->azVar[pOp->p1-1] = pOp->p3; + p->azVar[pOp->p1-1] = pOp->p3.p; } } p->okVar = 1; diff --git a/src/vdbeaux.c b/src/vdbeaux.c index b5239d650b..69d1612a75 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -152,7 +152,7 @@ int sqlite3VdbeAddOp(Vdbe *p, int op, int p1, int p2){ pOp->opcode = op; pOp->p1 = p1; pOp->p2 = p2; - pOp->p3 = 0; + pOp->p3.p = 0; pOp->p3type = P3_NOTUSED; p->expired = 0; #ifdef SQLITE_DEBUG @@ -162,14 +162,38 @@ int sqlite3VdbeAddOp(Vdbe *p, int op, int p1, int p2){ } /* -** Add an opcode that includes the p3 value. +** Add an opcode that includes the p3 value as a pointer. */ -int sqlite3VdbeOp3(Vdbe *p, int op, int p1, int p2, const char *zP3,int p3type){ +int sqlite3VdbeOp3( + Vdbe *p, /* Add the opcode to this VM */ + int op, /* The new opcode */ + int p1, int p2, /* P1 and P2 operands */ + const char *zP3, /* The P3 operand */ + int p3type /* P3 operand type */ +){ int addr = sqlite3VdbeAddOp(p, op, p1, p2); sqlite3VdbeChangeP3(p, addr, zP3, p3type); return addr; } +/* +** Add an opcode that includes the p3 value as an integer. +*/ +int sqlite3VdbeOp3Int( + Vdbe *p, /* Add the opcode to this VM */ + int op, /* The new opcode */ + int p1, int p2, /* P1 and P2 operands */ + int p3 /* The P3 operand */ +){ + int addr = sqlite3VdbeAddOp(p, op, p1, p2); + if( !p->db->mallocFailed ){ + Op *pOp = &p->aOp[addr]; + pOp->p3.i = p3; + pOp->p3type = P3_INT32; + } + return addr; +} + /* ** Create a new symbolic label for an instruction that has yet to be ** coded. The symbolic label is really just a negative number. The @@ -378,7 +402,7 @@ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){ pOut->opcode = pIn->opcode; pOut->p1 = pIn->p1; pOut->p2 = p2<0 ? addr + ADDR(p2) : p2; - pOut->p3 = pIn->p3; + pOut->p3.p = pIn->p3; pOut->p3type = pIn->p3 ? P3_STATIC : P3_NOTUSED; #ifdef SQLITE_DEBUG if( sqlite3_vdbe_addop_trace ){ @@ -477,7 +501,7 @@ void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){ if( p && p->aOp ){ VdbeOp *pOp = &p->aOp[addr]; while( N-- ){ - freeP3(pOp->p3type, pOp->p3); + freeP3(pOp->p3type, pOp->p3.p); memset(pOp, 0, sizeof(pOp[0])); pOp->opcode = OP_Noop; pOp++; @@ -524,10 +548,10 @@ void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){ if( addr<0 ) return; } pOp = &p->aOp[addr]; - freeP3(pOp->p3type, pOp->p3); - pOp->p3 = 0; + freeP3(pOp->p3type, pOp->p3.p); + pOp->p3.p = 0; if( zP3==0 ){ - pOp->p3 = 0; + pOp->p3.p = 0; pOp->p3type = P3_NOTUSED; }else if( n==P3_KEYINFO ){ KeyInfo *pKeyInfo; @@ -536,7 +560,7 @@ void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){ nField = ((KeyInfo*)zP3)->nField; nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]) + nField; pKeyInfo = sqlite3_malloc( nByte ); - pOp->p3 = (char*)pKeyInfo; + pOp->p3.p = (char*)pKeyInfo; if( pKeyInfo ){ unsigned char *aSortOrder; memcpy(pKeyInfo, zP3, nByte); @@ -551,29 +575,28 @@ void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){ pOp->p3type = P3_NOTUSED; } }else if( n==P3_KEYINFO_HANDOFF ){ - pOp->p3 = (char*)zP3; + pOp->p3.p = (char*)zP3; pOp->p3type = P3_KEYINFO; }else if( n<0 ){ - pOp->p3 = (char*)zP3; + pOp->p3.p = (char*)zP3; pOp->p3type = n; }else{ if( n==0 ) n = strlen(zP3); - pOp->p3 = sqlite3DbStrNDup(p->db, zP3, n); + pOp->p3.p = sqlite3DbStrNDup(p->db, zP3, n); pOp->p3type = P3_DYNAMIC; } } #ifndef NDEBUG /* -** Replace the P3 field of the most recently coded instruction with -** comment text. +** Change the comment on the the most recently coded instruction. */ void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){ va_list ap; assert( p->nOp>0 || p->aOp==0 ); - assert( p->aOp==0 || p->aOp[p->nOp-1].p3==0 || p->db->mallocFailed ); + assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed ); va_start(ap, zFormat); - sqlite3VdbeChangeP3(p, -1, sqlite3VMPrintf(p->db, zFormat, ap), P3_DYNAMIC); + p->aOp[p->nOp-1].zComment = sqlite3VMPrintf(p->db, zFormat, ap); va_end(ap); } #endif @@ -594,12 +617,13 @@ VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){ ** Use zTemp for any required temporary buffer space. */ static char *displayP3(Op *pOp, char *zTemp, int nTemp){ - char *zP3; + char *zP3 = zTemp; + int nP3; assert( nTemp>=20 ); switch( pOp->p3type ){ case P3_KEYINFO: { int i, j; - KeyInfo *pKeyInfo = (KeyInfo*)pOp->p3; + KeyInfo *pKeyInfo = (KeyInfo*)pOp->p3.p; sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField); i = strlen(zTemp); for(j=0; jnField; j++){ @@ -624,47 +648,63 @@ static char *displayP3(Op *pOp, char *zTemp, int nTemp){ zTemp[i++] = ')'; zTemp[i] = 0; assert( ip3; + CollSeq *pColl = (CollSeq*)pOp->p3.p; sqlite3_snprintf(nTemp, zTemp, "collseq(%.20s)", pColl->zName); - zP3 = zTemp; break; } case P3_FUNCDEF: { - FuncDef *pDef = (FuncDef*)pOp->p3; + FuncDef *pDef = (FuncDef*)pOp->p3.p; sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg); - zP3 = zTemp; break; } case P3_INT64: { - sqlite3_snprintf(nTemp, zTemp, "%lld", *(sqlite3_int64*)pOp->p3); - zP3 = zTemp; + sqlite3_snprintf(nTemp, zTemp, "%lld", *(sqlite3_int64*)pOp->p3.p); + break; + } + case P3_INT32: { + sqlite3_snprintf(nTemp, zTemp, "%d", pOp->p3.i); break; } case P3_REAL: { - sqlite3_snprintf(nTemp, zTemp, "%.16g", *(double*)pOp->p3); - zP3 = zTemp; + sqlite3_snprintf(nTemp, zTemp, "%.16g", *(double*)pOp->p3.p); + break; + } + case P3_MEM: { + Mem *pMem = (Mem*)pOp->p3.p; + if( pMem->flags & MEM_Str ){ + zP3 = pMem->z; + }else if( pMem->flags & MEM_Int ){ + sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i); + }else if( pMem->flags & MEM_Real ){ + sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->r); + }else if( pMem->flags & MEM_Null ){ + sqlite3_snprintf(nTemp, zTemp, "NULL"); + } break; } #ifndef SQLITE_OMIT_VIRTUALTABLE case P3_VTAB: { - sqlite3_vtab *pVtab = (sqlite3_vtab*)pOp->p3; + sqlite3_vtab *pVtab = (sqlite3_vtab*)pOp->p3.p; sqlite3_snprintf(nTemp, zTemp, "vtab:%p:%p", pVtab, pVtab->pModule); - zP3 = zTemp; break; } #endif default: { - zP3 = pOp->p3; + zP3 = pOp->p3.p; if( zP3==0 || pOp->opcode==OP_Noop ){ - zP3 = ""; + zP3 = zTemp; + zTemp[0] = 0; } } } assert( zP3!=0 ); + if( pOp->zComment && zP3==zTemp && (nP3 = strlen(zP3))0 ? " " : "", pOp->zComment); + } return zP3; } #endif @@ -737,10 +777,10 @@ int sqlite3VdbeList( ** the stack, they may become dynamic if the user calls ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. */ - if( p->pTos==&p->aStack[4] ){ - releaseMemArray(p->aStack, 5); + if( p->pResultSet ){ + releaseMemArray(p->pResultSet, 5); + p->pResultSet = 0; } - p->resOnStack = 0; do{ i = p->pc++; @@ -754,7 +794,7 @@ int sqlite3VdbeList( sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(p->rc), (char*)0); }else{ Op *pOp = &p->aOp[i]; - Mem *pMem = p->aStack; + Mem *pMem = p->pResultSet = p->aStack; pMem->flags = MEM_Int; pMem->type = SQLITE_INTEGER; pMem->u.i = i; /* Program counter */ @@ -778,7 +818,7 @@ int sqlite3VdbeList( pMem->type = SQLITE_INTEGER; pMem++; - pMem->flags = MEM_Ephem|MEM_Str|MEM_Term; /* P3 */ + pMem->flags = MEM_Ephem|MEM_Str|MEM_Term; /* P3 */ pMem->z = displayP3(pOp, pMem->zShort, sizeof(pMem->zShort)); assert( pMem->z!=0 ); pMem->n = strlen(pMem->z); @@ -788,7 +828,6 @@ int sqlite3VdbeList( p->nResColumn = 5 - 2*(p->explain-1); p->pTos = pMem; p->rc = SQLITE_OK; - p->resOnStack = 1; rc = SQLITE_ROW; } return rc; @@ -804,8 +843,8 @@ void sqlite3VdbePrintSql(Vdbe *p){ VdbeOp *pOp; if( nOp<1 ) return; pOp = &p->aOp[nOp-1]; - if( pOp->opcode==OP_Noop && pOp->p3!=0 ){ - const char *z = pOp->p3; + if( pOp->opcode==OP_Noop && pOp->p3.p!=0 ){ + const char *z = pOp->p3.p; while( isspace(*(u8*)z) ) z++; printf("SQL: [%s]\n", z); } @@ -822,10 +861,10 @@ void sqlite3VdbeIOTraceSql(Vdbe *p){ if( sqlite3_io_trace==0 ) return; if( nOp<1 ) return; pOp = &p->aOp[nOp-1]; - if( pOp->opcode==OP_Noop && pOp->p3!=0 ){ + if( pOp->opcode==OP_Noop && pOp->p3.p!=0 ){ int i, j; char z[1000]; - sqlite3_snprintf(sizeof(z), z, "%s", pOp->p3); + sqlite3_snprintf(sizeof(z), z, "%s", pOp->p3.p); for(i=0; isspace((unsigned char)z[i]); i++){} for(j=0; z[i]; i++){ if( isspace((unsigned char)z[i]) ){ @@ -1024,7 +1063,7 @@ static void Cleanup(Vdbe *p){ p->contextStackTop = 0; sqlite3_free(p->zErrMsg); p->zErrMsg = 0; - p->resOnStack = 0; + p->pResultSet = 0; } /* @@ -1685,9 +1724,12 @@ void sqlite3VdbeDelete(Vdbe *p){ p->pNext->pPrev = p->pPrev; } if( p->aOp ){ - for(i=0; inOp; i++){ - Op *pOp = &p->aOp[i]; - freeP3(pOp->p3type, pOp->p3); + Op *pOp = p->aOp; + for(i=0; inOp; i++, pOp++){ + freeP3(pOp->p3type, pOp->p3.p); +#ifdef SQLITE_DEBUG + sqlite3_free(pOp->zComment); +#endif } sqlite3_free(p->aOp); } diff --git a/src/where.c b/src/where.c index 424df979b1..dfe349f7c5 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.266 2007/12/12 17:42:53 danielk1977 Exp $ +** $Id: where.c,v 1.267 2008/01/02 00:34:37 drh Exp $ */ #include "sqliteInt.h" @@ -1744,7 +1744,7 @@ static void codeEqualityTerm( eType = sqlite3FindInIndex(pParse, pX, 1); iTab = pX->iTable; sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0); - VdbeComment((v, "# %.*s", pX->span.n, pX->span.z)); + VdbeComment((v, "%.*s", pX->span.n, pX->span.z)); if( pLevel->nIn==0 ){ pLevel->nxt = sqlite3VdbeMakeLabel(v); } @@ -2212,7 +2212,7 @@ WhereInfo *sqlite3WhereBegin( KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx); assert( pIx->pSchema==pTab->pSchema ); sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); - VdbeComment((v, "# %s", pIx->zName)); + VdbeComment((v, "%s", pIx->zName)); sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIx->tnum, (char*)pKey, P3_KEYINFO_HANDOFF); sqlite3VdbeAddOp(v, OP_SetNumColumns, iIdxCur, pIx->nColumn+1); @@ -2263,7 +2263,7 @@ WhereInfo *sqlite3WhereBegin( if( !pParse->nMem ) pParse->nMem++; pLevel->iLeftJoin = pParse->nMem++; sqlite3VdbeAddOp(v, OP_MemInt, 0, pLevel->iLeftJoin); - VdbeComment((v, "# init LEFT JOIN no-match flag")); + VdbeComment((v, "init LEFT JOIN no-match flag")); } #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -2606,7 +2606,7 @@ WhereInfo *sqlite3WhereBegin( if( pLevel->iLeftJoin ){ pLevel->top = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp(v, OP_MemInt, 1, pLevel->iLeftJoin); - VdbeComment((v, "# record LEFT JOIN hit")); + VdbeComment((v, "record LEFT JOIN hit")); for(pTerm=wc.a, j=0; jflags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( (pTerm->prereqAll & notReady)!=0 ) continue;