From: drh Date: Fri, 20 Jun 2008 15:24:01 +0000 (+0000) Subject: Change the SRT_Subroutine mode into SRT_Coroutine. Use co-routines in X-Git-Tag: version-3.6.10~922 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e00ee6eb37748891f366c98ac39160a036433070;p=thirdparty%2Fsqlite.git Change the SRT_Subroutine mode into SRT_Coroutine. Use co-routines in the INSERT processing logic. (CVS 5255) FossilOrigin-Name: 6b9d92fc3f265ef75c9182e537812490bb818950 --- diff --git a/manifest b/manifest index 835203e645..89939ec88b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sa\smode\sto\sthe\ssqlite3_test_control()\sinterface\sto\sregister\shooks\scalled\sat\sthe\sbeginning\sand\send\sof\s"benign\smalloc\sfailure"\sblocks.\sThis\sallows\smalloc()\sfailure\stesting\sto\sbe\sdone\susing\spublic\sAPIs\sonly.\s(CVS\s5254) -D 2008-06-20T14:59:51 +C Change\sthe\sSRT_Subroutine\smode\sinto\sSRT_Coroutine.\s\sUse\sco-routines\sin\nthe\sINSERT\sprocessing\slogic.\s(CVS\s5255) +D 2008-06-20T15:24:02 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in ff6f90048555a0088f6a4b7406bed5e55a7c4eff F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -111,7 +111,7 @@ F src/global.c 2304cfa3288763bd2fed10caf8c6fbaa2b383f4e F src/hash.c eb64e48f3781100e5934f759fbe72a63a8fe78cb F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53 F src/hwtime.h 745961687a65ef8918cd551c02e5ccb4b8e772de -F src/insert.c c2ead6c36566de8e3f130e7ab1431723a269d5d7 +F src/insert.c 93231fd0199f044bcefda3d857420f4d377e4056 F src/journal.c cffd2cd214e58c0e99c3ff632b3bee6c7cbb260e F src/legacy.c 3626c71fb70912abec9a4312beba753a9ce800df F src/loadext.c 40024a0f476c1279494876b9a002001b29e5d3e3 @@ -141,11 +141,11 @@ F src/pragma.c 70e7c865dce85fdf9df81848af2169009a56ed08 F src/prepare.c 3c19149e75fbf3b08471a389f064da7302cad9c5 F src/printf.c 8b063da9dcde26b7c500a01444b718d86f21bc6e F src/random.c 5c754319d38abdd6acd74601ee0105504adc508a -F src/select.c 669687459e7d0193c89de06c5dbed55b4a41191c +F src/select.c 672a4812f7bf889176b52d3257bf21d2c08009f1 F src/shell.c a12ea645271b7876c8f080146f48e20b00d367ec F src/sqlite.h.in 4c41b702bf6a105a485dfb61065f941c8cb0357d F src/sqlite3ext.h f162a72daef5ebf8b211fe8c0ec96e85d22fbf9b -F src/sqliteInt.h c1ef17f6f9dd356af922bc28647109c97a860976 +F src/sqliteInt.h 005b2f0aa10acd20435b46d4a9f84e20855c6f35 F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8 F src/status.c 6cb10377992505bd69f1ca1d75c1240a65f25a58 F src/table.c 1fa8f8113ac9cbc09ae4801c6d2a7f0af82c5822 @@ -182,7 +182,7 @@ F src/update.c 2d7143b9014e955509cc4f323f9a9584fb898f34 F src/utf.c 8c94fa10efc78c2568d08d436acc59df4df7191b F src/util.c 920d6d5dfdf25f7b85d2093705d8716f9b387e3b F src/vacuum.c 14eb21b480924d87e791cd8ab6fb35ac563243ef -F src/vdbe.c 7f80262db08ceac0abce2b93034c97aab66b71bc +F src/vdbe.c d4b0efeedb4bfb088931addf926e99f4977346c9 F src/vdbe.h 1e3722d471739c2b213c6283b60373290e52f7ea F src/vdbeInt.h de321b2c02593e1420106634ed1f5a7d77ad35a7 F src/vdbeapi.c a7c6b8db324cf7eccff32de871dea36aa305c994 @@ -600,7 +600,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P 4ae21e3419ad7e69dd735ca45fdc5a2de93d1840 -R d06fe14f86e9e4eba8e97f2719ced042 -U danielk1977 -Z 42b4e7b0df5b9e47be1696346ec789df +P 56c8af1452dfdc8da858a2411bd6f3663a8a9326 +R 6f87c80d4f9e9e0ffaab864f69d1e048 +U drh +Z d407ea393f3d0c3bac61db977c722528 diff --git a/manifest.uuid b/manifest.uuid index d41af96b35..56acee8b61 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -56c8af1452dfdc8da858a2411bd6f3663a8a9326 \ No newline at end of file +6b9d92fc3f265ef75c9182e537812490bb818950 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 42ce65f854..856228352f 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.240 2008/06/06 15:04:37 drh Exp $ +** $Id: insert.c,v 1.241 2008/06/20 15:24:02 drh Exp $ */ #include "sqliteInt.h" @@ -269,7 +269,8 @@ static int xferOptimization( ** ** The code generated follows one of four templates. For a simple ** select with data coming from a VALUES clause, the code executes -** once straight down through. The template looks like this: +** once straight down through. Pseudo-code follows (we call this +** the "1st template"): ** ** open write cursor to and its indices ** puts VALUES clause expressions onto the stack @@ -287,7 +288,7 @@ static int xferOptimization( ** schemas, including all the same indices, then a special optimization ** is invoked that copies raw records from over to . ** See the xferOptimization() function for the implementation of this -** template. This is the second template. +** template. This is the 2nd template. ** ** open a write cursor to
** open read cursor on @@ -300,45 +301,58 @@ static int xferOptimization( ** close cursors ** end foreach ** -** The third template is for when the second template does not apply +** The 3rd template is for when the second template does not apply ** and the SELECT clause does not read from
at any time. ** The generated code follows this template: ** +** EOF <- 0 +** X <- A ** goto B ** A: setup for the SELECT ** loop over the rows in the SELECT -** gosub C +** load values into registers R..R+n +** yield X ** end loop ** cleanup after the SELECT -** goto D -** B: open write cursor to
and its indices +** EOF <- 1 +** yield X ** goto A -** C: insert the select result into
-** return +** B: open write cursor to
and its indices +** C: yield X +** if EOF goto D +** insert the select result into
from R..R+n +** goto C ** D: cleanup ** -** The fourth template is used if the insert statement takes its +** The 4th template is used if the insert statement takes its ** values from a SELECT but the data is being inserted into a table ** that is also read as part of the SELECT. In the third form, ** we have to use a intermediate table to store the results of ** the select. The template is like this: ** +** EOF <- 0 +** X <- A ** goto B ** A: setup for the SELECT ** loop over the tables in the SELECT -** gosub C +** load value into register R..R+n +** yield X ** end loop ** cleanup after the SELECT -** goto D -** C: insert the select result into the intermediate table -** return -** B: open a cursor to an intermediate table -** goto A -** D: open write cursor to
and its indices -** loop over the intermediate table +** EOF <- 1 +** yield X +** halt-error +** B: open temp table +** L: yield X +** if EOF goto M +** insert row from R..R+n into temp table +** goto L +** M: open write cursor to
and its indices +** rewind temp table +** C: loop over rows of intermediate table ** transfer values form intermediate table into
-** end the loop -** cleanup +** end loop +** D: cleanup */ void sqlite3Insert( Parse *pParse, /* Parser context */ @@ -362,10 +376,9 @@ void sqlite3Insert( int endOfLoop; /* Label for the end of the insertion loop */ int useTempTable = 0; /* Store SELECT results in intermediate table */ int srcTab = 0; /* Data comes from this temporary cursor if >=0 */ - int iCont=0,iBreak=0; /* Beginning and end of the loop over srcTab */ - int iSelectLoop = 0; /* Address of code that implements the SELECT */ - int iCleanup = 0; /* Address of the cleanup code */ - int iInsertBlock = 0; /* Address of the subroutine used to insert data */ + int addrInsTop = 0; /* Jump to label "D" */ + int addrCont = 0; /* Top of insert loop. Label "C" in templates 3 and 4 */ + int addrSelect = 0; /* Address of coroutine that implements the SELECT */ SelectDest dest; /* Destination for SELECT on rhs of INSERT */ int newIdx = -1; /* Cursor for the NEW pseudo-table */ int iDb; /* Index of database holding TABLE */ @@ -380,6 +393,7 @@ void sqlite3Insert( int regRowid; /* registers holding insert rowid */ int regData; /* register holding first column to insert */ int regRecord; /* Holds the assemblied row record */ + int regEof; /* Register recording end of SELECT data */ int *aRegIdx = 0; /* One register allocated to each index */ @@ -461,6 +475,8 @@ void sqlite3Insert( ** ** Then special optimizations can be applied that make the transfer ** very fast and which reduce fragmentation of indices. + ** + ** This is the 2nd template. */ if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){ assert( !triggers_exist ); @@ -475,75 +491,104 @@ void sqlite3Insert( regAutoinc = autoIncBegin(pParse, iDb, pTab); /* Figure out how many columns of data are supplied. If the data - ** is coming from a SELECT statement, then this step also generates - ** all the code to implement the SELECT statement and invoke a subroutine - ** to process each row of the result. (Template 2.) If the SELECT - ** statement uses the the table that is being inserted into, then the - ** subroutine is also coded here. That subroutine stores the SELECT - ** results in a temporary table. (Template 3.) + ** is coming from a SELECT statement, then generate a co-routine that + ** produces a single row of the SELECT on each invocation. The + ** co-routine is the common header to the 3rd and 4th templates. */ if( pSelect ){ /* Data is coming from a SELECT. Generate code to implement that SELECT + ** as a co-routine. The code is common to both the 3rd and 4th + ** templates: + ** + ** EOF <- 0 + ** X <- A + ** goto B + ** A: setup for the SELECT + ** loop over the tables in the SELECT + ** load value into register R..R+n + ** yield X + ** end loop + ** cleanup after the SELECT + ** EOF <- 1 + ** yield X + ** halt-error + ** + ** On each invocation of the co-routine, it puts a single row of the + ** SELECT result into registers dest.iMem...dest.iMem+dest.nMem-1. + ** (These output registers are allocated by sqlite3Select().) When + ** the SELECT completes, it sets the EOF flag stored in regEof. */ - int rc, iInitCode; - - iInitCode = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); - iSelectLoop = sqlite3VdbeCurrentAddr(v); - iInsertBlock = sqlite3VdbeMakeLabel(v); - sqlite3SelectDestInit(&dest, SRT_Subroutine, iInsertBlock); - dest.regReturn = ++pParse->nMem; + int rc, j1; + + regEof = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof); /* EOF <- 0 */ + VdbeComment((v, "SELECT eof flag")); + sqlite3SelectDestInit(&dest, SRT_Coroutine, 0); + dest.regCoroutine = ++pParse->nMem; + addrSelect = sqlite3VdbeCurrentAddr(v)+2; + sqlite3VdbeAddOp2(v, OP_Integer, addrSelect-1, dest.regCoroutine); + j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); + VdbeComment((v, "Jump over SELECT coroutine")); /* Resolve the expressions in the SELECT statement and execute it. */ rc = sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0); if( rc || pParse->nErr || db->mallocFailed ){ goto insert_cleanup; } + sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof); /* EOF <- 1 */ + sqlite3VdbeAddOp1(v, OP_Yield, dest.regCoroutine); /* yield X */ + sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort); + VdbeComment((v, "End of SELECT coroutine")); + sqlite3VdbeJumpHere(v, j1); /* label B: */ regFromSelect = dest.iMem; - iCleanup = sqlite3VdbeMakeLabel(v); - sqlite3VdbeAddOp2(v, OP_Goto, 0, iCleanup); assert( pSelect->pEList ); nColumn = pSelect->pEList->nExpr; + assert( dest.nMem==nColumn ); /* Set useTempTable to TRUE if the result of the SELECT statement - ** should be written into a temporary table. Set to FALSE if each - ** row of the SELECT can be written directly into the result table. + ** should be written into a temporary table (template 4). Set to + ** FALSE if each* row of the SELECT can be written directly into + ** the destination table (template 3). ** ** A temp table must be used if the table being updated is also one ** of the tables being read by the SELECT statement. Also use a ** temp table in the case of row triggers. */ - if( triggers_exist || readsTable(v, iSelectLoop, iDb, pTab) ){ + if( triggers_exist || readsTable(v, addrSelect, iDb, pTab) ){ useTempTable = 1; } if( useTempTable ){ - /* Generate the subroutine that SELECT calls to process each row of - ** the result. Store the result in a temporary table + /* Invoke the coroutine to extract information from the SELECT + ** and add it to a transient table srcTab. The code generated + ** here is from the 4th template: + ** + ** B: open temp table + ** L: yield X + ** if EOF goto M + ** insert row from R..R+n into temp table + ** goto L + ** M: ... */ - int regRec, regRowid; + int regRec; /* Register to hold packed record */ + int regRowid; /* Register to hold temp table ROWID */ + int addrTop; /* Label "L" */ + int addrIf; /* Address of jump to M */ srcTab = pParse->nTab++; regRec = sqlite3GetTempReg(pParse); regRowid = sqlite3GetTempReg(pParse); - sqlite3VdbeResolveLabel(v, iInsertBlock); + sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn); + addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.regCoroutine); + addrIf = sqlite3VdbeAddOp1(v, OP_If, regEof); sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec); sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regRowid); - sqlite3VdbeAddOp1(v, OP_Return, dest.regReturn); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop); + sqlite3VdbeJumpHere(v, addrIf); sqlite3ReleaseTempReg(pParse, regRec); sqlite3ReleaseTempReg(pParse, regRowid); - - /* The following code runs first because the GOTO at the very top - ** of the program jumps to it. Create the temporary table, then jump - ** back up and execute the SELECT code above. - */ - sqlite3VdbeJumpHere(v, iInitCode); - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn); - sqlite3VdbeAddOp2(v, OP_Goto, 0, iSelectLoop); - sqlite3VdbeResolveLabel(v, iCleanup); - }else{ - sqlite3VdbeJumpHere(v, iInitCode); } }else{ /* This is the case if the data for the INSERT is coming from a VALUES @@ -657,18 +702,31 @@ void sqlite3Insert( } } - /* If the data source is a temporary table, then we have to create - ** a loop because there might be multiple rows of data. If the data - ** source is a subroutine call from the SELECT statement, then we need - ** to launch the SELECT statement processing. - */ + /* This is the top of the main insertion loop */ if( useTempTable ){ - iBreak = sqlite3VdbeMakeLabel(v); - sqlite3VdbeAddOp2(v, OP_Rewind, srcTab, iBreak); - iCont = sqlite3VdbeCurrentAddr(v); + /* This block codes the top of loop only. The complete loop is the + ** following pseudocode (template 4): + ** + ** rewind temp table + ** C: loop over rows of intermediate table + ** transfer values form intermediate table into
+ ** end loop + ** D: ... + */ + addrInsTop = sqlite3VdbeAddOp1(v, OP_Rewind, srcTab); + addrCont = sqlite3VdbeCurrentAddr(v); }else if( pSelect ){ - sqlite3VdbeAddOp2(v, OP_Goto, 0, iSelectLoop); - sqlite3VdbeResolveLabel(v, iInsertBlock); + /* This block codes the top of loop only. The complete loop is the + ** following pseudocode (template 3): + ** + ** C: yield X + ** if EOF goto D + ** insert the select result into
from R..R+n + ** goto C + ** D: ... + */ + addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.regCoroutine); + addrInsTop = sqlite3VdbeAddOp1(v, OP_If, regEof); } /* Allocate registers for holding the rowid of the new row, @@ -893,16 +951,17 @@ void sqlite3Insert( } } - /* The bottom of the loop, if the data source is a SELECT statement + /* The bottom of the main insertion loop, if the data source + ** is a SELECT statement. */ sqlite3VdbeResolveLabel(v, endOfLoop); if( useTempTable ){ - sqlite3VdbeAddOp2(v, OP_Next, srcTab, iCont); - sqlite3VdbeResolveLabel(v, iBreak); + sqlite3VdbeAddOp2(v, OP_Next, srcTab, addrCont); + sqlite3VdbeJumpHere(v, addrInsTop); sqlite3VdbeAddOp1(v, OP_Close, srcTab); }else if( pSelect ){ - sqlite3VdbeAddOp1(v, OP_Return, dest.regReturn); - sqlite3VdbeResolveLabel(v, iCleanup); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrCont); + sqlite3VdbeJumpHere(v, addrInsTop); } if( !IsVirtual(pTab) && !isView ){ diff --git a/src/select.c b/src/select.c index 70f37dc290..f66214de0b 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.430 2008/06/06 15:04:37 drh Exp $ +** $Id: select.c,v 1.431 2008/06/20 15:24:02 drh Exp $ */ #include "sqliteInt.h" @@ -39,7 +39,7 @@ static void clearSelect(Select *p){ void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){ pDest->eDest = eDest; pDest->iParm = iParm; - pDest->regReturn = 0; + pDest->regCoroutine = 0; pDest->affinity = 0; pDest->iMem = 0; pDest->nMem = 0; @@ -704,15 +704,15 @@ static void selectInnerLoop( ** case of a subroutine, the subroutine itself is responsible for ** popping the data from the stack. */ - case SRT_Subroutine: + case SRT_Coroutine: case SRT_Callback: { if( pOrderBy ){ int r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); pushOntoSorter(pParse, pOrderBy, p, r1); sqlite3ReleaseTempReg(pParse, r1); - }else if( eDest==SRT_Subroutine ){ - sqlite3VdbeAddOp2(v, OP_Gosub, pDest->regReturn, iParm); + }else if( eDest==SRT_Coroutine ){ + sqlite3VdbeAddOp1(v, OP_Yield, pDest->regCoroutine); }else{ sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn); sqlite3ExprCacheAffinityChange(pParse, regResult, nColumn); @@ -810,7 +810,7 @@ static void generateSortTail( int regRowid; iTab = pOrderBy->iECursor; - if( eDest==SRT_Callback || eDest==SRT_Subroutine ){ + if( eDest==SRT_Callback || eDest==SRT_Coroutine ){ pseudoTab = pParse->nTab++; sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, nColumn); sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, eDest==SRT_Callback); @@ -847,7 +847,7 @@ static void generateSortTail( } #endif case SRT_Callback: - case SRT_Subroutine: { + case SRT_Coroutine: { int i; sqlite3VdbeAddOp2(v, OP_Integer, 1, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, pseudoTab, regRow, regRowid); @@ -858,8 +858,8 @@ static void generateSortTail( if( eDest==SRT_Callback ){ sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn); sqlite3ExprCacheAffinityChange(pParse, pDest->iMem, nColumn); - }else{ - sqlite3VdbeAddOp2(v, OP_Gosub, pDest->regReturn, iParm); + }else if( eDest==SRT_Coroutine ){ + sqlite3VdbeAddOp1(v, OP_Yield, pDest->regCoroutine); } break; } @@ -883,7 +883,7 @@ static void generateSortTail( sqlite3VdbeResolveLabel(v, cont); sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); sqlite3VdbeResolveLabel(v, brk); - if( eDest==SRT_Callback || eDest==SRT_Subroutine ){ + if( eDest==SRT_Callback || eDest==SRT_Coroutine ){ sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0); } @@ -2992,9 +2992,8 @@ void sqlite3SelectMask(Parse *pParse, Select *p, u32 mask){ ** the result there. The cursor is left open after ** returning. ** -** SRT_Subroutine For each row returned, push the results onto the -** vdbe stack and call the subroutine (via OP_Gosub) -** at address pDest->iParm. +** SRT_Coroutine Invoke a co-routine to compute a single row of +** the result ** ** SRT_Exists Store a 1 in memory cell pDest->iParm if the result ** set is not empty. @@ -3486,7 +3485,7 @@ int sqlite3Select( } /* Generate code that runs whenever the GROUP BY changes. - ** Change in the GROUP BY are detected by the previous code + ** Changes in the GROUP BY are detected by the previous code ** block. If there were no changes, this block is skipped. ** ** This code copies current group by terms in b0,b1,b2,... diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 682bcacedf..d91383d4b8 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.720 2008/06/20 14:59:51 danielk1977 Exp $ +** @(#) $Id: sqliteInt.h,v 1.721 2008/06/20 15:24:02 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -1438,7 +1438,7 @@ struct Select { #define SRT_Set 7 /* Store non-null results as keys in an index */ #define SRT_Table 8 /* Store result as data with an automatic rowid */ #define SRT_EphemTab 9 /* Create transient tab and store like SRT_Table */ -#define SRT_Subroutine 10 /* Call a subroutine to handle results */ +#define SRT_Coroutine 10 /* Generate a single row of result */ /* ** A structure used to customize the behaviour of sqlite3Select(). See @@ -1449,9 +1449,10 @@ struct SelectDest { u8 eDest; /* How to dispose of the results */ u8 affinity; /* Affinity used when eDest==SRT_Set */ int iParm; /* A parameter used by the eDest disposal method */ - int regReturn; /* Return address register for SRT_Subroutine */ + int regCoroutine; /* Program counter register for SRT_Coroutine */ int iMem; /* Base register where results are written */ int nMem; /* Number of registers allocated */ + int eofMem; /* Register holding EOF flag */ }; /* diff --git a/src/vdbe.c b/src/vdbe.c index 75af3f3f95..2c0d12a70a 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.750 2008/06/20 14:59:51 danielk1977 Exp $ +** $Id: vdbe.c,v 1.751 2008/06/20 15:24:02 drh Exp $ */ #include "sqliteInt.h" #include @@ -785,6 +785,25 @@ case OP_Return: { /* in1 */ break; } +/* Opcode: Yield P1 * * * * +** +** Swap the program counter with the value in register P1. +*/ +case OP_Yield: { + int pcDest; + assert( pOp->p1>0 ); + assert( pOp->p1<=p->nMem ); + pIn1 = &p->aMem[pOp->p1]; + assert( (pIn1->flags & MEM_Dyn)==0 ); + pIn1->flags = MEM_Int; + pcDest = pIn1->u.i; + pIn1->u.i = pc; + REGISTER_TRACE(pOp->p1, pIn1); + pc = pcDest; + break; +} + + /* Opcode: Halt P1 P2 * P4 * ** ** Exit immediately. All open cursors, Fifos, etc are closed