/ Check-in [6fb74485]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add the OP_Undef and OP_IsUndef opcodes. With these, use the first register 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.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | coroutine-refactor
Files: files | file ages | folders
SHA1:6fb7448550f28a3c93053e125faeaf11de1011d0
User & Date: drh 2014-02-07 13:20:31
Context
2014-02-07
18:27
Get rid of the OP_Undef and OP_IsUndef opcodes in favor of higher-level OP_InitCoroutine and OP_EndCoroutine. check-in: 1ec0e9dd user: drh tags: coroutine-refactor
13:20
Add the OP_Undef and OP_IsUndef opcodes. With these, use the first register 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. check-in: 6fb74485 user: drh tags: coroutine-refactor
03:28
More comment updates. No changes to code. check-in: be24fbc2 user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/insert.c.

   345    345   **
   346    346   ** Registers are allocated as follows:
   347    347   **
   348    348   **   pDest->iSDParm      The register holding the next entry-point of the
   349    349   **                       co-routine.  Run the co-routine to its next breakpoint
   350    350   **                       by calling "OP_Yield $X" where $X is pDest->iSDParm.
   351    351   **
   352         -**   pDest->iSDParm+1    The register holding the "completed" flag for the
   353         -**                       co-routine. This register is 0 if the previous Yield
   354         -**                       generated a new result row, or 1 if the subquery
   355         -**                       has completed.  If the Yield is called again
   356         -**                       after this register becomes 1, then the VDBE will
   357         -**                       halt with an SQLITE_INTERNAL error.
   358         -**
   359    352   **   pDest->iSdst        First result register.
   360    353   **
   361    354   **   pDest->nSdst        Number of result registers.
          355  +**
          356  +** At EOF the first result register will be marked as "undefined" so that
          357  +** the caller can know when to stop reading results.
   362    358   **
   363    359   ** This routine handles all of the register allocation and fills in the
   364    360   ** pDest structure appropriately.
   365    361   **
   366    362   ** Here is a schematic of the generated code assuming that X is the 
   367    363   ** co-routine entry-point register reg[pDest->iSDParm], that EOF is the
   368    364   ** completed flag reg[pDest->iSDParm+1], and R and S are the range of
   369    365   ** registers that hold the result set, reg[pDest->iSdst] through
   370    366   ** reg[pDest->iSdst+pDest->nSdst-1]:
   371    367   **
   372    368   **         X <- A
   373         -**         EOF <- 0
   374    369   **         goto B
   375    370   **      A: setup for the SELECT
   376    371   **         loop rows in the SELECT
   377    372   **           load results into registers R..S
   378    373   **           yield X
   379    374   **         end loop
   380    375   **         cleanup after the SELECT
   381         -**         EOF <- 1
          376  +**         R <- undefined (signals EOF)
   382    377   **         yield X
   383    378   **         halt-error
   384    379   **      B:
   385    380   **
   386    381   ** To use this subroutine, the caller generates code as follows:
   387    382   **
   388    383   **         [ Co-routine generated by this subroutine, shown above ]
   389    384   **      S: yield X
   390         -**         if EOF goto E
          385  +**         if R==undefined goto E
   391    386   **         if skip this row, goto C
   392    387   **         if terminate loop, goto E
   393    388   **         deal with this row
   394    389   **      C: goto S
   395    390   **      E:
   396    391   */
   397    392   int sqlite3CodeCoroutine(Parse *pParse, Select *pSelect, SelectDest *pDest){
   398    393     int regYield;       /* Register holding co-routine entry-point */
   399         -  int regEof;         /* Register holding co-routine completion flag */
   400    394     int addrTop;        /* Top of the co-routine */
   401    395     int j1;             /* Jump instruction */
   402    396     int rc;             /* Result code */
   403    397     Vdbe *v;            /* VDBE under construction */
   404    398   
   405    399     regYield = ++pParse->nMem;
   406         -  regEof = ++pParse->nMem;
   407    400     v = sqlite3GetVdbe(pParse);
   408    401     addrTop = sqlite3VdbeCurrentAddr(v);
   409         -  sqlite3VdbeAddOp2(v, OP_Integer, addrTop+2, regYield); /* X <- A */
          402  +  sqlite3VdbeAddOp2(v, OP_Integer, addrTop+1, regYield); /* X <- A */
   410    403     VdbeComment((v, "Co-routine entry point"));
   411         -  sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof);           /* EOF <- 0 */
   412         -  VdbeComment((v, "Co-routine completion flag"));
   413    404     sqlite3SelectDestInit(pDest, SRT_Coroutine, regYield);
   414    405     j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
   415    406     rc = sqlite3Select(pParse, pSelect, pDest);
   416    407     assert( pParse->nErr==0 || rc );
   417    408     if( pParse->db->mallocFailed && rc==SQLITE_OK ) rc = SQLITE_NOMEM;
   418    409     if( rc ) return rc;
   419         -  sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof);            /* EOF <- 1 */
   420         -  sqlite3VdbeAddOp1(v, OP_Yield, regYield);   /* yield X */
          410  +  sqlite3VdbeAddOp1(v, OP_Undef, pDest->iSdst);     /* Signal EOF */
          411  +  sqlite3VdbeAddOp1(v, OP_Yield, regYield);         /* yield X */
   421    412     sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort);
   422    413     VdbeComment((v, "End of coroutine"));
   423    414     sqlite3VdbeJumpHere(v, j1);                             /* label B: */
   424    415     return rc;
   425    416   }
   426    417   
   427    418   
................................................................................
   484    475   **           close cursors
   485    476   **         end foreach
   486    477   **
   487    478   ** The 3rd template is for when the second template does not apply
   488    479   ** and the SELECT clause does not read from <table> at any time.
   489    480   ** The generated code follows this template:
   490    481   **
   491         -**         EOF <- 0
   492    482   **         X <- A
   493    483   **         goto B
   494    484   **      A: setup for the SELECT
   495    485   **         loop over the rows in the SELECT
   496    486   **           load values into registers R..R+n
   497    487   **           yield X
   498    488   **         end loop
   499    489   **         cleanup after the SELECT
   500         -**         EOF <- 1
          490  +**         R <- undefined (signals EOF)
   501    491   **         yield X
   502    492   **         goto A
   503    493   **      B: open write cursor to <table> and its indices
   504    494   **      C: yield X
   505         -**         if EOF goto D
          495  +**         if R=undefined goto D
   506    496   **         insert the select result into <table> from R..R+n
   507    497   **         goto C
   508    498   **      D: cleanup
   509    499   **
   510    500   ** The 4th template is used if the insert statement takes its
   511    501   ** values from a SELECT but the data is being inserted into a table
   512    502   ** that is also read as part of the SELECT.  In the third form,
   513    503   ** we have to use a intermediate table to store the results of
   514    504   ** the select.  The template is like this:
   515    505   **
   516         -**         EOF <- 0
   517    506   **         X <- A
   518    507   **         goto B
   519    508   **      A: setup for the SELECT
   520    509   **         loop over the tables in the SELECT
   521    510   **           load value into register R..R+n
   522    511   **           yield X
   523    512   **         end loop
   524    513   **         cleanup after the SELECT
   525         -**         EOF <- 1
          514  +**         R <- undefined (signals EOF)
   526    515   **         yield X
   527    516   **         halt-error
   528    517   **      B: open temp table
   529    518   **      L: yield X
   530         -**         if EOF goto M
          519  +**         if R=undefined goto M
   531    520   **         insert row from R..R+n into temp table
   532    521   **         goto L
   533    522   **      M: open write cursor to <table> and its indices
   534    523   **         rewind temp table
   535    524   **      C: loop over rows of intermediate table
   536    525   **           transfer values form intermediate table into <table>
   537    526   **         end loop
................................................................................
   572    561     /* Register allocations */
   573    562     int regFromSelect = 0;/* Base register for data coming from SELECT */
   574    563     int regAutoinc = 0;   /* Register holding the AUTOINCREMENT counter */
   575    564     int regRowCount = 0;  /* Memory cell used for the row counter */
   576    565     int regIns;           /* Block of regs holding rowid+data being inserted */
   577    566     int regRowid;         /* registers holding insert rowid */
   578    567     int regData;          /* register holding first column to insert */
   579         -  int regEof = 0;       /* Register recording end of SELECT data */
   580    568     int *aRegIdx = 0;     /* One register allocated to each index */
   581    569   
   582    570   #ifndef SQLITE_OMIT_TRIGGER
   583    571     int isView;                 /* True if attempting to insert into a view */
   584    572     Trigger *pTrigger;          /* List of triggers on pTab, if required */
   585    573     int tmask;                  /* Mask of trigger times */
   586    574   #endif
................................................................................
   685    673     ** co-routine is the common header to the 3rd and 4th templates.
   686    674     */
   687    675     if( pSelect ){
   688    676       /* Data is coming from a SELECT.  Generate a co-routine to run the SELECT */
   689    677       int rc = sqlite3CodeCoroutine(pParse, pSelect, &dest);
   690    678       if( rc ) goto insert_cleanup;
   691    679   
   692         -    regEof = dest.iSDParm + 1;
   693    680       regFromSelect = dest.iSdst;
   694    681       assert( pSelect->pEList );
   695    682       nColumn = pSelect->pEList->nExpr;
   696    683       assert( dest.nSdst==nColumn );
   697    684   
   698    685       /* Set useTempTable to TRUE if the result of the SELECT statement
   699    686       ** should be written into a temporary table (template 4).  Set to
................................................................................
   711    698       if( useTempTable ){
   712    699         /* Invoke the coroutine to extract information from the SELECT
   713    700         ** and add it to a transient table srcTab.  The code generated
   714    701         ** here is from the 4th template:
   715    702         **
   716    703         **      B: open temp table
   717    704         **      L: yield X
   718         -      **         if EOF goto M
          705  +      **         if R=undefined goto M
   719    706         **         insert row from R..R+n into temp table
   720    707         **         goto L
   721    708         **      M: ...
   722    709         */
   723    710         int regRec;          /* Register to hold packed record */
   724    711         int regTempRowid;    /* Register to hold temp table ROWID */
   725    712         int addrTop;         /* Label "L" */
................................................................................
   726    713         int addrIf;          /* Address of jump to M */
   727    714   
   728    715         srcTab = pParse->nTab++;
   729    716         regRec = sqlite3GetTempReg(pParse);
   730    717         regTempRowid = sqlite3GetTempReg(pParse);
   731    718         sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn);
   732    719         addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
   733         -      addrIf = sqlite3VdbeAddOp1(v, OP_If, regEof);
          720  +      addrIf = sqlite3VdbeAddOp1(v, OP_IsUndef, regFromSelect);
   734    721         sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec);
   735    722         sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid);
   736    723         sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid);
   737    724         sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop);
   738    725         sqlite3VdbeJumpHere(v, addrIf);
   739    726         sqlite3ReleaseTempReg(pParse, regRec);
   740    727         sqlite3ReleaseTempReg(pParse, regTempRowid);
................................................................................
   856    843       addrInsTop = sqlite3VdbeAddOp1(v, OP_Rewind, srcTab);
   857    844       addrCont = sqlite3VdbeCurrentAddr(v);
   858    845     }else if( pSelect ){
   859    846       /* This block codes the top of loop only.  The complete loop is the
   860    847       ** following pseudocode (template 3):
   861    848       **
   862    849       **      C: yield X
   863         -    **         if EOF goto D
          850  +    **         if R=undefined goto D
   864    851       **         insert the select result into <table> from R..R+n
   865    852       **         goto C
   866    853       **      D: ...
   867    854       */
   868    855       addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
   869         -    addrInsTop = sqlite3VdbeAddOp1(v, OP_If, regEof);
          856  +    addrInsTop = sqlite3VdbeAddOp1(v, OP_IsUndef, dest.iSdst);
   870    857     }
   871    858   
   872    859     /* Allocate registers for holding the rowid of the new row,
   873    860     ** the content of the new row, and the assemblied row record.
   874    861     */
   875    862     regRowid = regIns = pParse->nMem+1;
   876    863     pParse->nMem += pTab->nCol + 1;

Changes to src/vdbe.c.

   389    389   #endif
   390    390   
   391    391   #ifdef SQLITE_DEBUG
   392    392   /*
   393    393   ** Print the value of a register for tracing purposes:
   394    394   */
   395    395   static void memTracePrint(Mem *p){
   396         -  if( p->flags & MEM_Invalid ){
          396  +  if( p->flags & MEM_Undefined ){
   397    397       printf(" undefined");
   398    398     }else if( p->flags & MEM_Null ){
   399    399       printf(" NULL");
   400    400     }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
   401    401       printf(" si:%lld", p->u.i);
   402    402     }else if( p->flags & MEM_Int ){
   403    403       printf(" i:%lld", p->u.i);
................................................................................
   698    698     }
   699    699   #endif
   700    700     
   701    701     break;
   702    702   }
   703    703   
   704    704   /* Opcode:  Gosub P1 P2 * * *
   705         -** Synopsis:  r[P1]=pc; pc=P2
   706    705   **
   707    706   ** Write the current address onto register P1
   708    707   ** and then jump to address P2.
   709    708   */
   710    709   case OP_Gosub: {            /* jump */
   711    710     assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
   712    711     pIn1 = &aMem[pOp->p1];
................................................................................
   716    715     pIn1->u.i = pc;
   717    716     REGISTER_TRACE(pOp->p1, pIn1);
   718    717     pc = pOp->p2 - 1;
   719    718     break;
   720    719   }
   721    720   
   722    721   /* Opcode:  Return P1 * * * *
   723         -** Synopsis:  pc=r[P1]+1
   724    722   **
   725    723   ** Jump to the next instruction after the address in register P1.
   726    724   */
   727    725   case OP_Return: {           /* in1 */
   728    726     pIn1 = &aMem[pOp->p1];
   729    727     assert( pIn1->flags & MEM_Int );
   730    728     pc = (int)pIn1->u.i;
   731    729     break;
   732    730   }
   733    731   
   734    732   /* Opcode:  Yield P1 * * * *
   735         -** Synopsis: swap(pc,r[P1])
   736    733   **
   737    734   ** Swap the program counter with the value in register P1.
   738    735   */
   739    736   case OP_Yield: {            /* in1 */
   740    737     int pcDest;
   741    738     pIn1 = &aMem[pOp->p1];
   742    739     assert( (pIn1->flags & MEM_Dyn)==0 );
................................................................................
   970    967       pOut->flags = nullFlag;
   971    968       cnt--;
   972    969     }
   973    970     break;
   974    971   }
   975    972   
   976    973   
   977         -/* Opcode: Blob P1 P2 * P4
          974  +/* Opcode: Blob P1 P2 * P4 *
   978    975   ** Synopsis: r[P2]=P4 (len=P1)
   979    976   **
   980    977   ** P4 points to a blob of data P1 bytes long.  Store this
   981    978   ** blob in register P2.
   982    979   */
   983    980   case OP_Blob: {                /* out2-prerelease */
   984    981     assert( pOp->p1 <= SQLITE_MAX_LENGTH );
   985    982     sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0);
   986    983     pOut->enc = encoding;
   987    984     UPDATE_MAX_BLOBSIZE(pOut);
   988    985     break;
   989    986   }
          987  +
          988  +/* Opcode: Undef P1 * * * *
          989  +** Synopsis: r[P1]=undef
          990  +**
          991  +** Mark register P1 as undefined.
          992  +*/
          993  +case OP_Undef: {
          994  +  assert( pOp->p1>0 );
          995  +  assert( pOp->p1<=(p->nMem-p->nCursor) );
          996  +  pOut = &aMem[pOp->p1];
          997  +  memAboutToChange(p, pOut);
          998  +  VdbeMemRelease(pOut);
          999  +  pOut->flags = MEM_Undefined;
         1000  +  break;
         1001  +}
   990   1002   
   991   1003   /* Opcode: Variable P1 P2 * P4 *
   992   1004   ** Synopsis: r[P2]=parameter(P1,P4)
   993   1005   **
   994   1006   ** Transfer the values of bound parameter P1 into register P2
   995   1007   **
   996   1008   ** If the parameter is named, then its name appears in P4.
................................................................................
  2137   2149       if( pOp->opcode==OP_IfNot ) c = !c;
  2138   2150     }
  2139   2151     if( c ){
  2140   2152       pc = pOp->p2-1;
  2141   2153     }
  2142   2154     break;
  2143   2155   }
         2156  +
         2157  +/* Opcode: IsUndef P1 P2 * * *
         2158  +** Synopsis:  if r[P1]==undefined goto P2
         2159  +**
         2160  +** Jump to P2 if the value in register P1 is undefined
         2161  +*/
         2162  +case OP_IsUndef: {            /* jump */
         2163  +  pIn1 = &aMem[pOp->p1];
         2164  +  if( (pIn1->flags & MEM_Undefined)!=0 ){
         2165  +    pc = pOp->p2 - 1;
         2166  +  }
         2167  +  break;
         2168  +}
  2144   2169   
  2145   2170   /* Opcode: IsNull P1 P2 * * *
  2146   2171   ** Synopsis:  if r[P1]==NULL goto P2
  2147   2172   **
  2148   2173   ** Jump to P2 if the value in register P1 is NULL.
  2149   2174   */
  2150   2175   case OP_IsNull: {            /* same as TK_ISNULL, jump, in1 */
................................................................................
  5187   5212       pFrame->nOp = p->nOp;
  5188   5213       pFrame->token = pProgram->token;
  5189   5214       pFrame->aOnceFlag = p->aOnceFlag;
  5190   5215       pFrame->nOnceFlag = p->nOnceFlag;
  5191   5216   
  5192   5217       pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem];
  5193   5218       for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){
  5194         -      pMem->flags = MEM_Invalid;
         5219  +      pMem->flags = MEM_Undefined;
  5195   5220         pMem->db = db;
  5196   5221       }
  5197   5222     }else{
  5198   5223       pFrame = pRt->u.pFrame;
  5199   5224       assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem );
  5200   5225       assert( pProgram->nCsr==pFrame->nChildCsr );
  5201   5226       assert( pc==pFrame->pc );

Changes to src/vdbeInt.h.

   194    194   #define MEM_Null      0x0001   /* Value is NULL */
   195    195   #define MEM_Str       0x0002   /* Value is a string */
   196    196   #define MEM_Int       0x0004   /* Value is an integer */
   197    197   #define MEM_Real      0x0008   /* Value is a real number */
   198    198   #define MEM_Blob      0x0010   /* Value is a BLOB */
   199    199   #define MEM_RowSet    0x0020   /* Value is a RowSet object */
   200    200   #define MEM_Frame     0x0040   /* Value is a VdbeFrame object */
   201         -#define MEM_Invalid   0x0080   /* Value is undefined */
          201  +#define MEM_Undefined 0x0080   /* Value is undefined */
   202    202   #define MEM_Cleared   0x0100   /* NULL set by OP_Null, not from data */
   203    203   #define MEM_TypeMask  0x01ff   /* Mask of type bits */
   204    204   
   205    205   
   206    206   /* Whenever Mem contains a valid string or blob representation, one of
   207    207   ** the following flags must be set to determine the memory management
   208    208   ** policy for Mem.z.  The MEM_Term flag tells us whether or not the
................................................................................
   226    226      ((p)->flags = ((p)->flags&~(MEM_TypeMask|MEM_Zero))|f)
   227    227   
   228    228   /*
   229    229   ** Return true if a memory cell is not marked as invalid.  This macro
   230    230   ** is for use inside assert() statements only.
   231    231   */
   232    232   #ifdef SQLITE_DEBUG
   233         -#define memIsValid(M)  ((M)->flags & MEM_Invalid)==0
          233  +#define memIsValid(M)  ((M)->flags & MEM_Undefined)==0
   234    234   #endif
   235    235   
   236    236   /*
   237    237   ** Each auxilliary data pointer stored by a user defined function 
   238    238   ** implementation calling sqlite3_set_auxdata() is stored in an instance
   239    239   ** of this structure. All such structures associated with a single VM
   240    240   ** are stored in a linked list headed at Vdbe.pAuxData. All are destroyed

Changes to src/vdbeaux.c.

  1230   1230         if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){
  1231   1231           sqlite3VdbeMemRelease(p);
  1232   1232         }else if( p->zMalloc ){
  1233   1233           sqlite3DbFree(db, p->zMalloc);
  1234   1234           p->zMalloc = 0;
  1235   1235         }
  1236   1236   
  1237         -      p->flags = MEM_Invalid;
         1237  +      p->flags = MEM_Undefined;
  1238   1238       }
  1239   1239       db->mallocFailed = malloc_failed;
  1240   1240     }
  1241   1241   }
  1242   1242   
  1243   1243   /*
  1244   1244   ** Delete a VdbeFrame object and its contents. VdbeFrame objects are
................................................................................
  1698   1698       memcpy(p->azVar, pParse->azVar, p->nzVar*sizeof(p->azVar[0]));
  1699   1699       memset(pParse->azVar, 0, pParse->nzVar*sizeof(pParse->azVar[0]));
  1700   1700     }
  1701   1701     if( p->aMem ){
  1702   1702       p->aMem--;                      /* aMem[] goes from 1..nMem */
  1703   1703       p->nMem = nMem;                 /*       not from 0..nMem-1 */
  1704   1704       for(n=1; n<=nMem; n++){
  1705         -      p->aMem[n].flags = MEM_Invalid;
         1705  +      p->aMem[n].flags = MEM_Undefined;
  1706   1706         p->aMem[n].db = db;
  1707   1707       }
  1708   1708     }
  1709   1709     p->explain = pParse->explain;
  1710   1710     sqlite3VdbeRewind(p);
  1711   1711   }
  1712   1712   
................................................................................
  1810   1810   
  1811   1811   #ifdef SQLITE_DEBUG
  1812   1812     /* Execute assert() statements to ensure that the Vdbe.apCsr[] and 
  1813   1813     ** Vdbe.aMem[] arrays have already been cleaned up.  */
  1814   1814     int i;
  1815   1815     if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
  1816   1816     if( p->aMem ){
  1817         -    for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Invalid );
         1817  +    for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
  1818   1818     }
  1819   1819   #endif
  1820   1820   
  1821   1821     sqlite3DbFree(db, p->zErrMsg);
  1822   1822     p->zErrMsg = 0;
  1823   1823     p->pResultSet = 0;
  1824   1824   }

Changes to src/vdbemem.c.

   583    583   ** copies are not misused.
   584    584   */
   585    585   void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
   586    586     int i;
   587    587     Mem *pX;
   588    588     for(i=1, pX=&pVdbe->aMem[1]; i<=pVdbe->nMem; i++, pX++){
   589    589       if( pX->pScopyFrom==pMem ){
   590         -      pX->flags |= MEM_Invalid;
          590  +      pX->flags |= MEM_Undefined;
   591    591         pX->pScopyFrom = 0;
   592    592       }
   593    593     }
   594    594     pMem->pScopyFrom = 0;
   595    595   }
   596    596   #endif /* SQLITE_DEBUG */
   597    597