-C More\scomment\supdates.\s\sNo\schanges\sto\scode.
-D 2014-02-07T03:28:02.783
+C Add\sthe\sOP_Undef\sand\sOP_IsUndef\sopcodes.\s\sWith\sthese,\suse\sthe\sfirst\sregister\nin\sthe\sresult\sregister\srange\sas\sthe\sflag\sto\sindicate\sEOF\son\san\sINSERT\sfrom\na\sSELECT,\srather\sthan\sallocating\sa\sseparate\sboolean\sregister\sfor\sthat\stask.
+D 2014-02-07T13:20:31.855
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
-F src/insert.c a4450f0c46a9f221622e6551ab0953b03c4f8ee8
+F src/insert.c fa98632fbf46e01c7b4d2130558c74b42947f50d
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
F src/util.c 15ac2627f548f5481d0d7e6c4eb67be673027695
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
-F src/vdbe.c 575189caf33bc3f2b9557f420e9b815afcd5ace8
+F src/vdbe.c 8697f15ad86604c5a8d598b1566e1594a7956469
F src/vdbe.h e6c4c610fcabad4fa80ebb1efc6822a9367e2b26
-F src/vdbeInt.h 42db251e9f863401ff847b90d5fe1614c89a6a56
+F src/vdbeInt.h bd6d5e70fe7c80f6aa4c56c34589762b9e933929
F src/vdbeapi.c ce4e68ea4842cc6081046f533d088dcf01d247ad
-F src/vdbeaux.c a3327afa8cfcc5bb3d38f2b2a599bac5fb63c6be
+F src/vdbeaux.c 3fd95b226330e1d50aedb40d750effe726ebb3fb
F src/vdbeblob.c 9542e116c1db5ed813977581d506c176e117c0ec
-F src/vdbemem.c 23cdc14ed43e0aafa57bd72b9bf3d5b1641afa91
+F src/vdbemem.c c0bcc02d6816ab4218ac0f94b63c8ee78a0f739f
F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147
F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
-P 1122b410de68a3c79b4c719a3a4cc4dc6a5bb39d
-R ba81bea358565b1489c187d643f4773f
-U mistachkin
-Z fafd555fb9fada47058f4a33fbcaaf41
+P be24fbc22106e508975e316abe0471edd3833291
+R 7163c03b39a8cc1205867ee33d31d20c
+U drh
+Z 84c60c97897782670b677e52594a24b3
** co-routine. Run the co-routine to its next breakpoint
** by calling "OP_Yield $X" where $X is pDest->iSDParm.
**
-** pDest->iSDParm+1 The register holding the "completed" flag for the
-** co-routine. This register is 0 if the previous Yield
-** generated a new result row, or 1 if the subquery
-** has completed. If the Yield is called again
-** after this register becomes 1, then the VDBE will
-** halt with an SQLITE_INTERNAL error.
-**
** pDest->iSdst First result register.
**
** pDest->nSdst Number of result registers.
**
+** At EOF the first result register will be marked as "undefined" so that
+** the caller can know when to stop reading results.
+**
** This routine handles all of the register allocation and fills in the
** pDest structure appropriately.
**
** reg[pDest->iSdst+pDest->nSdst-1]:
**
** X <- A
-** EOF <- 0
** goto B
** A: setup for the SELECT
** loop rows in the SELECT
** yield X
** end loop
** cleanup after the SELECT
-** EOF <- 1
+** R <- undefined (signals EOF)
** yield X
** halt-error
** B:
**
** [ Co-routine generated by this subroutine, shown above ]
** S: yield X
-** if EOF goto E
+** if R==undefined goto E
** if skip this row, goto C
** if terminate loop, goto E
** deal with this row
*/
int sqlite3CodeCoroutine(Parse *pParse, Select *pSelect, SelectDest *pDest){
int regYield; /* Register holding co-routine entry-point */
- int regEof; /* Register holding co-routine completion flag */
int addrTop; /* Top of the co-routine */
int j1; /* Jump instruction */
int rc; /* Result code */
Vdbe *v; /* VDBE under construction */
regYield = ++pParse->nMem;
- regEof = ++pParse->nMem;
v = sqlite3GetVdbe(pParse);
addrTop = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp2(v, OP_Integer, addrTop+2, regYield); /* X <- A */
+ sqlite3VdbeAddOp2(v, OP_Integer, addrTop+1, regYield); /* X <- A */
VdbeComment((v, "Co-routine entry point"));
- sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof); /* EOF <- 0 */
- VdbeComment((v, "Co-routine completion flag"));
sqlite3SelectDestInit(pDest, SRT_Coroutine, regYield);
j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
rc = sqlite3Select(pParse, pSelect, pDest);
assert( pParse->nErr==0 || rc );
if( pParse->db->mallocFailed && rc==SQLITE_OK ) rc = SQLITE_NOMEM;
if( rc ) return rc;
- sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof); /* EOF <- 1 */
- sqlite3VdbeAddOp1(v, OP_Yield, regYield); /* yield X */
+ sqlite3VdbeAddOp1(v, OP_Undef, pDest->iSdst); /* Signal EOF */
+ sqlite3VdbeAddOp1(v, OP_Yield, regYield); /* yield X */
sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort);
VdbeComment((v, "End of coroutine"));
sqlite3VdbeJumpHere(v, j1); /* label B: */
** and the SELECT clause does not read from <table> at any time.
** The generated code follows this template:
**
-** EOF <- 0
** X <- A
** goto B
** A: setup for the SELECT
** yield X
** end loop
** cleanup after the SELECT
-** EOF <- 1
+** R <- undefined (signals EOF)
** yield X
** goto A
** B: open write cursor to <table> and its indices
** C: yield X
-** if EOF goto D
+** if R=undefined goto D
** insert the select result into <table> from R..R+n
** goto C
** D: cleanup
** 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
** yield X
** end loop
** cleanup after the SELECT
-** EOF <- 1
+** R <- undefined (signals EOF)
** yield X
** halt-error
** B: open temp table
** L: yield X
-** if EOF goto M
+** if R=undefined goto M
** insert row from R..R+n into temp table
** goto L
** M: open write cursor to <table> and its indices
int regIns; /* Block of regs holding rowid+data being inserted */
int regRowid; /* registers holding insert rowid */
int regData; /* register holding first column to insert */
- int regEof = 0; /* Register recording end of SELECT data */
int *aRegIdx = 0; /* One register allocated to each index */
#ifndef SQLITE_OMIT_TRIGGER
int rc = sqlite3CodeCoroutine(pParse, pSelect, &dest);
if( rc ) goto insert_cleanup;
- regEof = dest.iSDParm + 1;
regFromSelect = dest.iSdst;
assert( pSelect->pEList );
nColumn = pSelect->pEList->nExpr;
**
** B: open temp table
** L: yield X
- ** if EOF goto M
+ ** if R=undefined goto M
** insert row from R..R+n into temp table
** goto L
** M: ...
regTempRowid = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn);
addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
- addrIf = sqlite3VdbeAddOp1(v, OP_If, regEof);
+ addrIf = sqlite3VdbeAddOp1(v, OP_IsUndef, regFromSelect);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec);
sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid);
sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid);
** following pseudocode (template 3):
**
** C: yield X
- ** if EOF goto D
+ ** if R=undefined goto D
** insert the select result into <table> from R..R+n
** goto C
** D: ...
*/
addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
- addrInsTop = sqlite3VdbeAddOp1(v, OP_If, regEof);
+ addrInsTop = sqlite3VdbeAddOp1(v, OP_IsUndef, dest.iSdst);
}
/* Allocate registers for holding the rowid of the new row,
** Print the value of a register for tracing purposes:
*/
static void memTracePrint(Mem *p){
- if( p->flags & MEM_Invalid ){
+ if( p->flags & MEM_Undefined ){
printf(" undefined");
}else if( p->flags & MEM_Null ){
printf(" NULL");
}
/* Opcode: Gosub P1 P2 * * *
-** Synopsis: r[P1]=pc; pc=P2
**
** Write the current address onto register P1
** and then jump to address P2.
}
/* Opcode: Return P1 * * * *
-** Synopsis: pc=r[P1]+1
**
** Jump to the next instruction after the address in register P1.
*/
}
/* Opcode: Yield P1 * * * *
-** Synopsis: swap(pc,r[P1])
**
** Swap the program counter with the value in register P1.
*/
}
-/* Opcode: Blob P1 P2 * P4
+/* Opcode: Blob P1 P2 * P4 *
** Synopsis: r[P2]=P4 (len=P1)
**
** P4 points to a blob of data P1 bytes long. Store this
break;
}
+/* Opcode: Undef P1 * * * *
+** Synopsis: r[P1]=undef
+**
+** Mark register P1 as undefined.
+*/
+case OP_Undef: {
+ assert( pOp->p1>0 );
+ assert( pOp->p1<=(p->nMem-p->nCursor) );
+ pOut = &aMem[pOp->p1];
+ memAboutToChange(p, pOut);
+ VdbeMemRelease(pOut);
+ pOut->flags = MEM_Undefined;
+ break;
+}
+
/* Opcode: Variable P1 P2 * P4 *
** Synopsis: r[P2]=parameter(P1,P4)
**
break;
}
+/* Opcode: IsUndef P1 P2 * * *
+** Synopsis: if r[P1]==undefined goto P2
+**
+** Jump to P2 if the value in register P1 is undefined
+*/
+case OP_IsUndef: { /* jump */
+ pIn1 = &aMem[pOp->p1];
+ if( (pIn1->flags & MEM_Undefined)!=0 ){
+ pc = pOp->p2 - 1;
+ }
+ break;
+}
+
/* Opcode: IsNull P1 P2 * * *
** Synopsis: if r[P1]==NULL goto P2
**
pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem];
for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){
- pMem->flags = MEM_Invalid;
+ pMem->flags = MEM_Undefined;
pMem->db = db;
}
}else{