/ Check-in [562da534]
Login

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

Overview
Comment:Take care to track ephemeral strings in the VDBE and make copies of ephemeral strings that need to be preserved. Ticket #177. (CVS 769)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:562da534bbb605a8ce15824135b012ef2d86bbeb
User & Date: drh 2002-10-22 15:04:34
Context
2002-10-22
23:38
Correctly handle column names and string constants in parentheses. Fix for ticket #179. (CVS 770) check-in: 3b68aa25 user: drh tags: trunk
15:04
Take care to track ephemeral strings in the VDBE and make copies of ephemeral strings that need to be preserved. Ticket #177. (CVS 769) check-in: 562da534 user: drh tags: trunk
2002-10-20
18:19
Rework the changes for ticket #176 (check-ins (760) and (761)) to be more consistent with the rest of the source code. (CVS 768) check-in: f50a177b user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
...
148
149
150
151
152
153
154
155
156

157
158
159
160
161
162
163
...
793
794
795
796
797
798
799

























800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
....
1573
1574
1575
1576
1577
1578
1579
1580

1581
1582

1583
1584
1585
1586
1587
1588
1589
1590

1591
1592
1593
1594
1595
1596
1597
1598
....
1609
1610
1611
1612
1613
1614
1615

1616

1617

1618
1619
1620
1621
1622
1623
1624

1625
1626
1627
1628
1629
1630
1631
....
1640
1641
1642
1643
1644
1645
1646

1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
....
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
....
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
....
4766
4767
4768
4769
4770
4771
4772

4773
4774
4775
4776
4777
4778
4779
....
4787
4788
4789
4790
4791
4792
4793

4794
4795
4796
4797
4798
4799

4800
4801



4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
....
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
....
4984
4985
4986
4987
4988
4989
4990

4991
4992
4993
4994
4995
4996
4997
....
5017
5018
5019
5020
5021
5022
5023

5024
5025
5026
5027
5028
5029
5030
....
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
....
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
....
5230
5231
5232
5233
5234
5235
5236

5237
5238




5239
5240
5241
5242
5243
5244
5245
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** 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.180 2002/10/19 20:16:38 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The makefile scans this source file and creates the following
** array of string constants which are the names of all VDBE opcodes.
................................................................................
/*
** Allowed values for Stack.flags
*/
#define STK_Null      0x0001   /* Value is NULL */
#define STK_Str       0x0002   /* Value is a string */
#define STK_Int       0x0004   /* Value is an integer */
#define STK_Real      0x0008   /* Value is a real number */
#define STK_Dyn       0x0010   /* Need to call sqliteFree() on zStack[*] */
#define STK_Static    0x0020   /* zStack[] points to a static string */


/* The following STK_ value appears only in AggElem.aMem.s.flag fields.
** It indicates that the corresponding AggElem.aMem.z points to a
** aggregate function context that needs to be finalized.
*/
#define STK_AggCtx    0x0040   /* zStack[] points to an agg function context */

................................................................................
    pStack->z[0] = 0;
  }
  *pzStack = pStack->z;
  pStack->n = strlen(*pzStack)+1;
  pStack->flags = STK_Str;
  return 0;
}


























/*
** Release the memory associated with the given stack level
*/
#define Release(P,I)  if((P)->aStack[I].flags&STK_Dyn){ hardRelease(P,I); }
static void hardRelease(Vdbe *p, int i){
  sqliteFree(p->zStack[i]);
  p->zStack[i] = 0;
  p->aStack[i].flags &= ~(STK_Str|STK_Dyn|STK_Static);
}

/*
** Convert the given stack entity into a integer if it isn't one
** already.
**
** Any prior string or real representation is invalidated.  
................................................................................
case OP_Dup: {
  int i = p->tos - pOp->p1;
  int j = ++p->tos;
  VERIFY( if( i<0 ) goto not_enough_stack; )
  VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
  memcpy(&aStack[j], &aStack[i], sizeof(aStack[i])-NBFS);
  if( aStack[j].flags & STK_Str ){
    if( pOp->p2 || (aStack[j].flags & STK_Static)!=0 ){

      zStack[j] = zStack[i];
      aStack[j].flags &= ~STK_Dyn;

    }else if( aStack[i].n<=NBFS ){
      memcpy(aStack[j].z, zStack[i], aStack[j].n);
      zStack[j] = aStack[j].z;
      aStack[j].flags &= ~(STK_Static|STK_Dyn);
    }else{
      zStack[j] = sqliteMalloc( aStack[j].n );
      if( zStack[j]==0 ) goto no_mem;
      memcpy(zStack[j], zStack[i], aStack[j].n);

      aStack[j].flags &= ~STK_Static;
    }
  }
  break;
}

/* Opcode: Pull P1 * *
**
................................................................................
  int to = p->tos;
  int i;
  Stack ts;
  char *tz;
  VERIFY( if( from<0 ) goto not_enough_stack; )
  ts = aStack[from];
  tz = zStack[from];

  for(i=from; i<to; i++){

    aStack[i] = aStack[i+1];

    if( aStack[i].flags & (STK_Dyn|STK_Static) ){
      zStack[i] = zStack[i+1];
    }else{
      zStack[i] = aStack[i].z;
    }
  }
  aStack[to] = ts;

  if( aStack[to].flags & (STK_Dyn|STK_Static) ){
    zStack[to] = tz;
  }else{
    zStack[to] = aStack[to].z;
  }
  break;
}
................................................................................
  int from = p->tos;
  int to = p->tos - pOp->p1;

  VERIFY( if( to<0 ) goto not_enough_stack; )
  if( aStack[to].flags & STK_Dyn ){
    sqliteFree(zStack[to]);
  }

  aStack[to] = aStack[from];
  if( aStack[to].flags & (STK_Dyn|STK_Static) ){
    zStack[to] = zStack[from];
  }else{
    zStack[to] = aStack[to].z;
  }
  aStack[from].flags &= ~STK_Dyn;
  p->tos--;
  break;
}

/* Opcode: ColumnCount P1 * *
**
** Specify the number of column values that will appear in the
................................................................................
** the key itself.
*/
case OP_IncrKey: {
  int tos = p->tos;

  VERIFY( if( tos<0 ) goto bad_instruction );
  if( Stringify(p, tos) ) goto no_mem;
  if( aStack[tos].flags & STK_Static ){
    /* CANT HAPPEN.  The IncrKey opcode is only applied to keys
    ** generated by MakeKey or MakeIdxKey and the results of those
    ** operands are always dynamic strings.
    */
    goto abort_due_to_error;
  }
  zStack[tos][aStack[tos].n-1]++;
................................................................................

  /* amt and offset now hold the offset to the start of data and the
  ** amount of data.  Go get the data and put it on the stack.
  */
  if( amt==0 ){
    aStack[tos].flags = STK_Null;
  }else if( zRec ){
    aStack[tos].flags = STK_Str | STK_Static;
    aStack[tos].n = amt;
    zStack[tos] = &zRec[offset];
  }else{
    if( amt<=NBFS ){
      aStack[tos].flags = STK_Str;
      zStack[tos] = aStack[tos].z;
      aStack[tos].n = amt;
................................................................................
** the original data remains on the stack.
*/
case OP_MemStore: {
  int i = pOp->p1;
  int tos = p->tos;
  char *zOld;
  Mem *pMem;

  VERIFY( if( tos<0 ) goto not_enough_stack; )
  if( i>=p->nMem ){
    int nOld = p->nMem;
    Mem *aMem;
    p->nMem = i + 5;
    aMem = sqliteRealloc(p->aMem, p->nMem*sizeof(p->aMem[0]));
    if( aMem==0 ) goto no_mem;
................................................................................
    }
    p->aMem = aMem;
    if( nOld<p->nMem ){
      memset(&p->aMem[nOld], 0, sizeof(p->aMem[0])*(p->nMem-nOld));
    }
  }
  pMem = &p->aMem[i];

  if( pMem->s.flags & STK_Dyn ){
    zOld = pMem->z;
  }else{
    zOld = 0;
  }
  pMem->s = aStack[tos];

  if( pMem->s.flags & (STK_Static|STK_Dyn) ){
    if( pOp->p2==0 && (pMem->s.flags & STK_Dyn)!=0 ){



      pMem->z = sqliteMalloc( pMem->s.n );
      if( pMem->z==0 ) goto no_mem;
      memcpy(pMem->z, zStack[tos], pMem->s.n);
    }else{
      pMem->z = zStack[tos];
    }
  }else{
    pMem->z = pMem->s.z;
  }
  if( zOld ) sqliteFree(zOld);
  if( pOp->p2 ){
    zStack[tos] = 0;
................................................................................
  int tos = ++p->tos;
  int i = pOp->p1;
  VERIFY( if( NeedStack(p, tos) ) goto no_mem; )
  VERIFY( if( i<0 || i>=p->nMem ) goto bad_instruction; )
  memcpy(&aStack[tos], &p->aMem[i].s, sizeof(aStack[tos])-NBFS);;
  if( aStack[tos].flags & STK_Str ){
    zStack[tos] = p->aMem[i].z;
    aStack[tos].flags |= STK_Static;
    aStack[tos].flags &= ~STK_Dyn;
  }
  break;
}

/* Opcode: MemIncr P1 P2 *
**
................................................................................
    Mem *pMem = &pFocus->aMem[i];
    char *zOld;
    if( pMem->s.flags & STK_Dyn ){
      zOld = pMem->z;
    }else{
      zOld = 0;
    }

    pMem->s = aStack[tos];
    if( pMem->s.flags & STK_Dyn ){
      pMem->z = zStack[tos];
      zStack[tos] = 0;
      aStack[tos].flags = 0;
    }else if( pMem->s.flags & (STK_Static|STK_AggCtx) ){
      pMem->z = zStack[tos];
................................................................................
  VERIFY( if( NeedStack(p, tos) ) goto no_mem; )
  if( pFocus==0 ) goto no_mem;
  if( VERIFY( i>=0 && ) i<p->agg.nMem ){
    Mem *pMem = &pFocus->aMem[i];
    aStack[tos] = pMem->s;
    zStack[tos] = pMem->z;
    aStack[tos].flags &= ~STK_Dyn;

  }
  break;
}

/* Opcode: AggNext * P2 *
**
** Make the next aggregate value the current aggregate.  The prior
................................................................................
      (*p->agg.apFunc[i]->xFinalize)(&ctx);
      if( freeCtx ){
        sqliteFree( aMem[i].z );
      }
      aMem[i].s = ctx.s;
      aMem[i].z = ctx.z;
      if( (aMem[i].s.flags & STK_Str) &&
              (aMem[i].s.flags & (STK_Dyn|STK_Static))==0 ){
        aMem[i].z = aMem[i].s.z;
      }
      nErr += ctx.isError;
    }
  }
  break;
}
................................................................................
      pc = pOp->p2 - 1;
    }
  }
  tos = ++p->tos;
  VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
  zStack[tos] = sqliteHashKey(pSet->prev);
  aStack[tos].n = sqliteHashKeysize(pSet->prev);
  aStack[tos].flags = STK_Str | STK_Static;
  break;
}

/* An other opcode is illegal...
*/
default: {
  sprintf(zBuf,"%d",pOp->opcode);
................................................................................
          fprintf(p->trace, " r:%g", aStack[i].r);
        }else if( aStack[i].flags & STK_Str ){
          int j, k;
          char zBuf[100];
          zBuf[0] = ' ';
          if( aStack[i].flags & STK_Dyn ){
            zBuf[1] = 'z';

          }else if( aStack[i].flags & STK_Static ){
            zBuf[1] = 't';




          }else{
            zBuf[1] = 's';
          }
          zBuf[2] = '[';
          k = 3;
          for(j=0; j<20 && j<aStack[i].n; j++){
            int c = zStack[i][j];







|







 







|

>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








|







 







|
>


>



|




>
|







 







>

>

>







>







 







>

|




|







 







|







 







|







 







>







 







>
|





>
|
<
>
>
>



|
|







 







|







 







>







 







>







 







|







 







|







 







>


>
>
>
>







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
...
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
....
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
....
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
....
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
....
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
....
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
....
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
....
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837

4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
....
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
....
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
....
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
....
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
....
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
....
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** 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.181 2002/10/22 15:04:34 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The makefile scans this source file and creates the following
** array of string constants which are the names of all VDBE opcodes.
................................................................................
/*
** Allowed values for Stack.flags
*/
#define STK_Null      0x0001   /* Value is NULL */
#define STK_Str       0x0002   /* Value is a string */
#define STK_Int       0x0004   /* Value is an integer */
#define STK_Real      0x0008   /* Value is a real number */
#define STK_Dyn       0x0010   /* Need to call sqliteFree() on zStack[] */
#define STK_Static    0x0020   /* zStack[] points to a static string */
#define STK_Ephem     0x0040   /* zStack[] points to an ephemeral string */

/* The following STK_ value appears only in AggElem.aMem.s.flag fields.
** It indicates that the corresponding AggElem.aMem.z points to a
** aggregate function context that needs to be finalized.
*/
#define STK_AggCtx    0x0040   /* zStack[] points to an agg function context */

................................................................................
    pStack->z[0] = 0;
  }
  *pzStack = pStack->z;
  pStack->n = strlen(*pzStack)+1;
  pStack->flags = STK_Str;
  return 0;
}

/*
** An ephemeral string value (signified by the STK_Ephem flag) contains
** a pointer to a dynamically allocated string where some other entity
** is responsible for deallocating that string.  Because the stack entry
** does not control the string, it might be deleted without the stack
** entry knowing it.
**
** This routine converts an ephemeral string into a dynamically allocated
** string that the stack entry itself controls.  In other words, it
** converts an STK_Ephem string into an STK_Dyn string.
*/
#define Deephemeralize(P,I) \
   if( ((P)->aStack[I].flags&STK_Ephem)!=0 && hardDeephem(P,I) ){ goto no_mem;}
static int hardDeephem(Vdbe *p, int i){
  Stack *pStack = &p->aStack[i];
  char **pzStack = &p->zStack[i];
  char *z;
  assert( (pStack->flags & STK_Ephem)!=0 );
  z = sqliteMalloc( pStack->n );
  if( z==0 ) return 1;
  memcpy(z, *pzStack, pStack->n);
  *pzStack = z;
  return 0;
}

/*
** Release the memory associated with the given stack level
*/
#define Release(P,I)  if((P)->aStack[I].flags&STK_Dyn){ hardRelease(P,I); }
static void hardRelease(Vdbe *p, int i){
  sqliteFree(p->zStack[i]);
  p->zStack[i] = 0;
  p->aStack[i].flags &= ~(STK_Str|STK_Dyn|STK_Static|STK_Ephem);
}

/*
** Convert the given stack entity into a integer if it isn't one
** already.
**
** Any prior string or real representation is invalidated.  
................................................................................
case OP_Dup: {
  int i = p->tos - pOp->p1;
  int j = ++p->tos;
  VERIFY( if( i<0 ) goto not_enough_stack; )
  VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
  memcpy(&aStack[j], &aStack[i], sizeof(aStack[i])-NBFS);
  if( aStack[j].flags & STK_Str ){
    int isStatic = (aStack[j].flags & STK_Static)!=0;
    if( pOp->p2 || isStatic ){
      zStack[j] = zStack[i];
      aStack[j].flags &= ~STK_Dyn;
      if( !isStatic ) aStack[j].flags |= STK_Ephem;
    }else if( aStack[i].n<=NBFS ){
      memcpy(aStack[j].z, zStack[i], aStack[j].n);
      zStack[j] = aStack[j].z;
      aStack[j].flags &= ~(STK_Static|STK_Dyn|STK_Ephem);
    }else{
      zStack[j] = sqliteMalloc( aStack[j].n );
      if( zStack[j]==0 ) goto no_mem;
      memcpy(zStack[j], zStack[i], aStack[j].n);
      aStack[j].flags &= ~(STK_Static|STK_Ephem);
      aStack[j].flags |= STK_Dyn;
    }
  }
  break;
}

/* Opcode: Pull P1 * *
**
................................................................................
  int to = p->tos;
  int i;
  Stack ts;
  char *tz;
  VERIFY( if( from<0 ) goto not_enough_stack; )
  ts = aStack[from];
  tz = zStack[from];
  Deephemeralize(p, to);
  for(i=from; i<to; i++){
    Deephemeralize(p, i);
    aStack[i] = aStack[i+1];
    assert( (aStack[i].flags & STK_Ephem)==0 );
    if( aStack[i].flags & (STK_Dyn|STK_Static) ){
      zStack[i] = zStack[i+1];
    }else{
      zStack[i] = aStack[i].z;
    }
  }
  aStack[to] = ts;
  assert( (aStack[to].flags & STK_Ephem)==0 );
  if( aStack[to].flags & (STK_Dyn|STK_Static) ){
    zStack[to] = tz;
  }else{
    zStack[to] = aStack[to].z;
  }
  break;
}
................................................................................
  int from = p->tos;
  int to = p->tos - pOp->p1;

  VERIFY( if( to<0 ) goto not_enough_stack; )
  if( aStack[to].flags & STK_Dyn ){
    sqliteFree(zStack[to]);
  }
  Deephemeralize(p, from);
  aStack[to] = aStack[from];
  if( aStack[to].flags & (STK_Dyn|STK_Static|STK_Ephem) ){
    zStack[to] = zStack[from];
  }else{
    zStack[to] = aStack[to].z;
  }
  aStack[from].flags = 0;
  p->tos--;
  break;
}

/* Opcode: ColumnCount P1 * *
**
** Specify the number of column values that will appear in the
................................................................................
** the key itself.
*/
case OP_IncrKey: {
  int tos = p->tos;

  VERIFY( if( tos<0 ) goto bad_instruction );
  if( Stringify(p, tos) ) goto no_mem;
  if( aStack[tos].flags & (STK_Static|STK_Ephem) ){
    /* CANT HAPPEN.  The IncrKey opcode is only applied to keys
    ** generated by MakeKey or MakeIdxKey and the results of those
    ** operands are always dynamic strings.
    */
    goto abort_due_to_error;
  }
  zStack[tos][aStack[tos].n-1]++;
................................................................................

  /* amt and offset now hold the offset to the start of data and the
  ** amount of data.  Go get the data and put it on the stack.
  */
  if( amt==0 ){
    aStack[tos].flags = STK_Null;
  }else if( zRec ){
    aStack[tos].flags = STK_Str | STK_Ephem;
    aStack[tos].n = amt;
    zStack[tos] = &zRec[offset];
  }else{
    if( amt<=NBFS ){
      aStack[tos].flags = STK_Str;
      zStack[tos] = aStack[tos].z;
      aStack[tos].n = amt;
................................................................................
** the original data remains on the stack.
*/
case OP_MemStore: {
  int i = pOp->p1;
  int tos = p->tos;
  char *zOld;
  Mem *pMem;
  int flags;
  VERIFY( if( tos<0 ) goto not_enough_stack; )
  if( i>=p->nMem ){
    int nOld = p->nMem;
    Mem *aMem;
    p->nMem = i + 5;
    aMem = sqliteRealloc(p->aMem, p->nMem*sizeof(p->aMem[0]));
    if( aMem==0 ) goto no_mem;
................................................................................
    }
    p->aMem = aMem;
    if( nOld<p->nMem ){
      memset(&p->aMem[nOld], 0, sizeof(p->aMem[0])*(p->nMem-nOld));
    }
  }
  pMem = &p->aMem[i];
  flags = pMem->s.flags;
  if( flags & STK_Dyn ){
    zOld = pMem->z;
  }else{
    zOld = 0;
  }
  pMem->s = aStack[tos];
  flags = pMem->s.flags;
  if( flags & (STK_Static|STK_Dyn|STK_Ephem) ){

    if( (flags & STK_Static)!=0 || (pOp->p2 && (flags & STK_Dyn)!=0) ){
      pMem->z = zStack[tos];
    }else if( flags & STK_Str ){
      pMem->z = sqliteMalloc( pMem->s.n );
      if( pMem->z==0 ) goto no_mem;
      memcpy(pMem->z, zStack[tos], pMem->s.n);
      pMem->s.flags |= STK_Dyn;
      pMem->s.flags &= ~(STK_Static|STK_Ephem);
    }
  }else{
    pMem->z = pMem->s.z;
  }
  if( zOld ) sqliteFree(zOld);
  if( pOp->p2 ){
    zStack[tos] = 0;
................................................................................
  int tos = ++p->tos;
  int i = pOp->p1;
  VERIFY( if( NeedStack(p, tos) ) goto no_mem; )
  VERIFY( if( i<0 || i>=p->nMem ) goto bad_instruction; )
  memcpy(&aStack[tos], &p->aMem[i].s, sizeof(aStack[tos])-NBFS);;
  if( aStack[tos].flags & STK_Str ){
    zStack[tos] = p->aMem[i].z;
    aStack[tos].flags |= STK_Ephem;
    aStack[tos].flags &= ~STK_Dyn;
  }
  break;
}

/* Opcode: MemIncr P1 P2 *
**
................................................................................
    Mem *pMem = &pFocus->aMem[i];
    char *zOld;
    if( pMem->s.flags & STK_Dyn ){
      zOld = pMem->z;
    }else{
      zOld = 0;
    }
    Deephemeralize(p, tos);
    pMem->s = aStack[tos];
    if( pMem->s.flags & STK_Dyn ){
      pMem->z = zStack[tos];
      zStack[tos] = 0;
      aStack[tos].flags = 0;
    }else if( pMem->s.flags & (STK_Static|STK_AggCtx) ){
      pMem->z = zStack[tos];
................................................................................
  VERIFY( if( NeedStack(p, tos) ) goto no_mem; )
  if( pFocus==0 ) goto no_mem;
  if( VERIFY( i>=0 && ) i<p->agg.nMem ){
    Mem *pMem = &pFocus->aMem[i];
    aStack[tos] = pMem->s;
    zStack[tos] = pMem->z;
    aStack[tos].flags &= ~STK_Dyn;
    aStack[tos].flags |= STK_Ephem;
  }
  break;
}

/* Opcode: AggNext * P2 *
**
** Make the next aggregate value the current aggregate.  The prior
................................................................................
      (*p->agg.apFunc[i]->xFinalize)(&ctx);
      if( freeCtx ){
        sqliteFree( aMem[i].z );
      }
      aMem[i].s = ctx.s;
      aMem[i].z = ctx.z;
      if( (aMem[i].s.flags & STK_Str) &&
              (aMem[i].s.flags & (STK_Dyn|STK_Static|STK_Ephem))==0 ){
        aMem[i].z = aMem[i].s.z;
      }
      nErr += ctx.isError;
    }
  }
  break;
}
................................................................................
      pc = pOp->p2 - 1;
    }
  }
  tos = ++p->tos;
  VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
  zStack[tos] = sqliteHashKey(pSet->prev);
  aStack[tos].n = sqliteHashKeysize(pSet->prev);
  aStack[tos].flags = STK_Str | STK_Ephem;
  break;
}

/* An other opcode is illegal...
*/
default: {
  sprintf(zBuf,"%d",pOp->opcode);
................................................................................
          fprintf(p->trace, " r:%g", aStack[i].r);
        }else if( aStack[i].flags & STK_Str ){
          int j, k;
          char zBuf[100];
          zBuf[0] = ' ';
          if( aStack[i].flags & STK_Dyn ){
            zBuf[1] = 'z';
            assert( (aStack[i].flags & (STK_Static|STK_Ephem))==0 );
          }else if( aStack[i].flags & STK_Static ){
            zBuf[1] = 't';
            assert( (aStack[i].flags & (STK_Dyn|STK_Ephem))==0 );
          }else if( aStack[i].flags & STK_Ephem ){
            zBuf[1] = 'e';
            assert( (aStack[i].flags & (STK_Static|STK_Dyn))==0 );
          }else{
            zBuf[1] = 's';
          }
          zBuf[2] = '[';
          k = 3;
          for(j=0; j<20 && j<aStack[i].n; j++){
            int c = zStack[i][j];