]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the OP_Undef and OP_IsUndef opcodes. With these, use the first register
authordrh <drh@noemail.net>
Fri, 7 Feb 2014 13:20:31 +0000 (13:20 +0000)
committerdrh <drh@noemail.net>
Fri, 7 Feb 2014 13:20:31 +0000 (13:20 +0000)
in the result register range as the flag to indicate EOF on an INSERT from
a SELECT, rather than allocating a separate boolean register for that task.

FossilOrigin-Name: 6fb7448550f28a3c93053e125faeaf11de1011d0

manifest
manifest.uuid
src/insert.c
src/vdbe.c
src/vdbeInt.h
src/vdbeaux.c
src/vdbemem.c

index 5537506c47f7fd474fdebbc76ee98ec0a17c29a2..9feb2fda5b1cd301dc6d7a586cac3863af4b10d3 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-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
@@ -183,7 +183,7 @@ F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486
 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
@@ -280,13 +280,13 @@ F src/update.c a7df6fffce6bfedc578fda6136dd33e34a63f8ee
 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
@@ -1152,7 +1152,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891
 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
index affff2d9c4775eeb5820c712ff776a68d8bf6fe7..a1ffd679c60a0e46c7a71b10330a26a69659e5f9 100644 (file)
@@ -1 +1 @@
-be24fbc22106e508975e316abe0471edd3833291
\ No newline at end of file
+6fb7448550f28a3c93053e125faeaf11de1011d0
\ No newline at end of file
index a2366360c71e7186d1269bd67793d64dfa763de0..edf277876fa53b2b13cb801fb3924534809f6020 100644 (file)
@@ -349,17 +349,13 @@ void sqlite3AutoincrementEnd(Parse *pParse){
 **                       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.
 **
@@ -370,7 +366,6 @@ void sqlite3AutoincrementEnd(Parse *pParse){
 ** reg[pDest->iSdst+pDest->nSdst-1]:
 **
 **         X <- A
-**         EOF <- 0
 **         goto B
 **      A: setup for the SELECT
 **         loop rows in the SELECT
@@ -378,7 +373,7 @@ void sqlite3AutoincrementEnd(Parse *pParse){
 **           yield X
 **         end loop
 **         cleanup after the SELECT
-**         EOF <- 1
+**         R <- undefined (signals EOF)
 **         yield X
 **         halt-error
 **      B:
@@ -387,7 +382,7 @@ void sqlite3AutoincrementEnd(Parse *pParse){
 **
 **         [ 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
@@ -396,28 +391,24 @@ void sqlite3AutoincrementEnd(Parse *pParse){
 */
 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: */
@@ -488,7 +479,6 @@ static int xferOptimization(
 ** 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
@@ -497,12 +487,12 @@ static int xferOptimization(
 **           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
@@ -513,7 +503,6 @@ static int xferOptimization(
 ** 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
@@ -522,12 +511,12 @@ static int xferOptimization(
 **           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
@@ -576,7 +565,6 @@ void sqlite3Insert(
   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
@@ -689,7 +677,6 @@ void sqlite3Insert(
     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;
@@ -715,7 +702,7 @@ void sqlite3Insert(
       **
       **      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: ...
@@ -730,7 +717,7 @@ void sqlite3Insert(
       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);
@@ -860,13 +847,13 @@ void sqlite3Insert(
     ** 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,
index 5816c4a79713ec26b323e1f5b74a60cc9c6b6a65..ab025ac48da07203b33b083e8fcf1db17c3e2b7b 100644 (file)
@@ -393,7 +393,7 @@ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
 ** 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");
@@ -702,7 +702,6 @@ check_for_interrupt:
 }
 
 /* Opcode:  Gosub P1 P2 * * *
-** Synopsis:  r[P1]=pc; pc=P2
 **
 ** Write the current address onto register P1
 ** and then jump to address P2.
@@ -720,7 +719,6 @@ case OP_Gosub: {            /* jump */
 }
 
 /* Opcode:  Return P1 * * * *
-** Synopsis:  pc=r[P1]+1
 **
 ** Jump to the next instruction after the address in register P1.
 */
@@ -732,7 +730,6 @@ case OP_Return: {           /* in1 */
 }
 
 /* Opcode:  Yield P1 * * * *
-** Synopsis: swap(pc,r[P1])
 **
 ** Swap the program counter with the value in register P1.
 */
@@ -974,7 +971,7 @@ case OP_Null: {           /* out2-prerelease */
 }
 
 
-/* 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
@@ -988,6 +985,21 @@ case OP_Blob: {                /* out2-prerelease */
   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)
 **
@@ -2142,6 +2154,19 @@ case OP_IfNot: {            /* jump, in1 */
   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
 **
@@ -5191,7 +5216,7 @@ case OP_Program: {        /* jump */
 
     pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem];
     for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){
-      pMem->flags = MEM_Invalid;
+      pMem->flags = MEM_Undefined;
       pMem->db = db;
     }
   }else{
index c4fa26cc058a26796ad81669634cd791b6679ad6..4da24b2374cf4534ad120fb8a67e5f25e4173ee5 100644 (file)
@@ -198,7 +198,7 @@ struct Mem {
 #define MEM_Blob      0x0010   /* Value is a BLOB */
 #define MEM_RowSet    0x0020   /* Value is a RowSet object */
 #define MEM_Frame     0x0040   /* Value is a VdbeFrame object */
-#define MEM_Invalid   0x0080   /* Value is undefined */
+#define MEM_Undefined 0x0080   /* Value is undefined */
 #define MEM_Cleared   0x0100   /* NULL set by OP_Null, not from data */
 #define MEM_TypeMask  0x01ff   /* Mask of type bits */
 
@@ -230,7 +230,7 @@ struct Mem {
 ** is for use inside assert() statements only.
 */
 #ifdef SQLITE_DEBUG
-#define memIsValid(M)  ((M)->flags & MEM_Invalid)==0
+#define memIsValid(M)  ((M)->flags & MEM_Undefined)==0
 #endif
 
 /*
index 69611622af8a11daa853f2e32fa54f3c91d86f6d..59b766a79cd7d7c4e0541c235d555cce92568afe 100644 (file)
@@ -1234,7 +1234,7 @@ static void releaseMemArray(Mem *p, int N){
         p->zMalloc = 0;
       }
 
-      p->flags = MEM_Invalid;
+      p->flags = MEM_Undefined;
     }
     db->mallocFailed = malloc_failed;
   }
@@ -1702,7 +1702,7 @@ void sqlite3VdbeMakeReady(
     p->aMem--;                      /* aMem[] goes from 1..nMem */
     p->nMem = nMem;                 /*       not from 0..nMem-1 */
     for(n=1; n<=nMem; n++){
-      p->aMem[n].flags = MEM_Invalid;
+      p->aMem[n].flags = MEM_Undefined;
       p->aMem[n].db = db;
     }
   }
@@ -1814,7 +1814,7 @@ static void Cleanup(Vdbe *p){
   int i;
   if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
   if( p->aMem ){
-    for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Invalid );
+    for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
   }
 #endif
 
index 9a621d1f735dcc8b1a8e2b9a616c31c3c3c63489..982a44537dd73bc2c8d99277bd615eef265e3493 100644 (file)
@@ -587,7 +587,7 @@ void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
   Mem *pX;
   for(i=1, pX=&pVdbe->aMem[1]; i<=pVdbe->nMem; i++, pX++){
     if( pX->pScopyFrom==pMem ){
-      pX->flags |= MEM_Invalid;
+      pX->flags |= MEM_Undefined;
       pX->pScopyFrom = 0;
     }
   }