/ Check-in [5f8d2468]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Memory handling fixes and optimizations in the VDBE. Ticket #862. (CVS 1909)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 5f8d246852c7cefd5941b8c7bb22177dfc7157c5
User & Date: drh 2004-08-28 18:17:48
Context
2004-08-28
18:21
Add prototype in sqlite3.h for the sqlite3_libversion() function. (CVS 1910) check-in: d50c47b4 user: drh tags: trunk
18:17
Memory handling fixes and optimizations in the VDBE. Ticket #862. (CVS 1909) check-in: 5f8d2468 user: drh tags: trunk
16:19
Add the sqlite3_libversion() API (ticket #834). Fix the build scripts to correctly build the shared libraries with version 8.4 of Tcl. (CVS 1908) check-in: 6db26a19 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
...
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
...
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850

851
852
853
854
855
856
857
...
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
....
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247

1248
1249
1250
1251
1252
1253
1254
1255
....
1769
1770
1771
1772
1773
1774
1775

1776
1777
1778
1779
1780
1781
1782
....
1933
1934
1935
1936
1937
1938
1939



1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950

1951
1952
1953








1954
1955




1956
1957
1958
1959
1960
1961
1962
....
3246
3247
3248
3249
3250
3251
3252

3253
3254
3255
3256
3257
3258
3259
....
3502
3503
3504
3505
3506
3507
3508

3509
3510
3511
3512
3513
3514
3515
....
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
....
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
....
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
....
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123

4124
4125
4126
4127
4128
4129
4130
....
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
....
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367

4368
4369
4370
4371
4372
4373
4374
**
** 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.409 2004/08/21 17:54:45 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
................................................................................
** sqlite3_bind() API.
*/
case OP_Variable: {
  int j = pOp->p1 - 1;
  assert( j>=0 && j<p->nVar );

  pTos++;
  memcpy(pTos, &p->aVar[j], sizeof(*pTos)-NBFS);
  pTos->xDel = 0;
  if( pTos->flags&(MEM_Str|MEM_Blob) ){
    pTos->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Short);
    pTos->flags |= MEM_Static;
  }
  break;
}

/* Opcode: Pop P1 * *
**
** P1 elements are popped off of the top of stack and discarded.
*/
................................................................................
**
** Also see the Pull instruction.
*/
case OP_Dup: {
  Mem *pFrom = &pTos[-pOp->p1];
  assert( pFrom<=pTos && pFrom>=p->aStack );
  pTos++;
  memcpy(pTos, pFrom, sizeof(*pFrom)-NBFS);
  pTos->xDel = 0;
  if( pTos->flags & (MEM_Str|MEM_Blob) ){
    if( pOp->p2 && (pTos->flags & (MEM_Dyn|MEM_Ephem)) ){
      pTos->flags &= ~MEM_Dyn;
      pTos->flags |= MEM_Ephem;
    }else if( pTos->flags & MEM_Short ){
      memcpy(pTos->zShort, pFrom->zShort, pTos->n+2);
      pTos->z = pTos->zShort;
    }else if( (pTos->flags & MEM_Static)==0 ){
      pTos->z = sqliteMallocRaw(pFrom->n+2);
      if( sqlite3_malloc_failed ) goto no_mem;
      memcpy(pTos->z, pFrom->z, pFrom->n);
      memcpy(&pTos->z[pTos->n], "\0", 2);
      pTos->flags &= ~(MEM_Static|MEM_Ephem|MEM_Short);
      pTos->flags |= MEM_Dyn|MEM_Term;
    }

  }
  break;
}

/* Opcode: Pull P1 * *
**
** The P1-th element is removed from its current location on 
................................................................................
** stack (P1==0 is the top of the stack) with the value
** of the top of the stack.  Then pop the top of the stack.
*/
case OP_Push: {
  Mem *pTo = &pTos[-pOp->p1];

  assert( pTo>=p->aStack );
  Deephemeralize(pTos);
  Release(pTo);
  *pTo = *pTos;
  if( pTo->flags & MEM_Short ){
    assert( pTo->z==pTos->zShort );
    pTo->z = pTo->zShort;
  }
  pTos--;
  break;
}

/* Opcode: Callback P1 * *
**
** Pop P1 values off the stack and form them into an array.  Then
................................................................................
  if( ctx.pVdbeFunc ){
    sqlite3VdbeDeleteAuxData(ctx.pVdbeFunc, pOp->p2);
    pOp->p3 = (char *)ctx.pVdbeFunc;
    pOp->p3type = P3_VDBEFUNC;
  }

  /* Copy the result of the function to the top of the stack */
  pTos++;
  sqlite3VdbeChangeEncoding(&ctx.s, db->enc);
  *pTos = ctx.s;
  if( pTos->flags & MEM_Short ){
    pTos->z = pTos->zShort;

  }
  /* If the function returned an error, throw an exception */
  if( ctx.isError ){
    if( !(pTos->flags&MEM_Str) ){
      sqlite3SetString(&p->zErrMsg, "user function error", (char*)0);
    }else{
      sqlite3SetString(&p->zErrMsg, sqlite3_value_text(pTos), (char*)0);
      sqlite3VdbeChangeEncoding(pTos, db->enc);
................................................................................
  int i;             /* Loop counter */
  char *zData;       /* Part of the record being decoded */
  Mem sMem;          /* For storing the record being decoded */

  sMem.flags = 0;
  assert( p1<p->nCursor );
  pTos++;


  /* This block sets the variable payloadSize to be the total number of
  ** bytes in the record.
  **
  ** zRec is set to be the complete text of the record if it is available.
  ** The complete record text is always available for pseudo-tables and
  ** when we are decoded a record from the stack.  If the record is stored
................................................................................
      pC->aOffset = aOffset;
      pC->cacheValid = 1;
    }
  }

  /* Get the column information.
  */



  if( zRec ){
    zData = &zRec[aOffset[p2]];
  }else{
    len = sqlite3VdbeSerialTypeLen(aType[p2]);
    sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->keyAsData, &sMem);
    zData = sMem.z;
  }
  sqlite3VdbeSerialGet(zData, aType[p2], pTos);
  if( sqlite3VdbeMemMakeWriteable(pTos)==SQLITE_NOMEM ){
    goto no_mem;
  }

  pTos->enc = db->enc;
  if( rc!=SQLITE_OK ){
    goto abort_due_to_error;








  }
  Release(&sMem);





  /* Release the aType[] memory if we are not dealing with cursor */
  if( !pC ){
    sqliteFree(aType);
  }
  break;
}
................................................................................
  Cursor *pC;

  assert( i>=0 && i<p->nCursor );
  assert( p->apCsr[i]!=0 );
  assert( p->apCsr[i]->keyAsData );
  assert( !p->apCsr[i]->pseudoTable );
  pTos++;

  if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
    i64 amt;
    char *z;

    sqlite3VdbeCursorMoveto(pC);
    assert( pC->intKey==0 );
    sqlite3BtreeKeySize(pCrsr, &amt);
................................................................................
  int i = pOp->p1;
  BtCursor *pCrsr;
  Cursor *pC;

  assert( i>=0 && i<p->nCursor );
  assert( p->apCsr[i]!=0 );
  pTos++;

  if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
    i64 rowid;

    assert( pC->deferredMoveto==0 );
    assert( pC->intKey==0 );
    if( pC->nullRow ){
      pTos->flags = MEM_Null;
................................................................................
      rc = sqlite3VdbeIdxRowid(pCrsr, &rowid);
      if( rc!=SQLITE_OK ){
        goto abort_due_to_error;
      }
      pTos->flags = MEM_Int;
      pTos->i = rowid;
    }
  }else{
    pTos->flags = MEM_Null;
  }
  break;
}

/* Opcode: IdxGT P1 P2 *
**
** The top of the stack is an index entry that omits the ROWID.  Compare
................................................................................
  pSorter->pNext = p->pSort;
  p->pSort = pSorter;
  assert( pTos->flags & MEM_Dyn );
  pSorter->nKey = pTos->n;
  pSorter->zKey = pTos->z;
  pSorter->data.flags = MEM_Null;
  rc = sqlite3VdbeMemMove(&pSorter->data, pNos);
  if( rc!=SQLITE_OK ) goto abort_due_to_error;
  Deephemeralize(&pSorter->data);
  pTos -= 2;
  break;
}

/* Opcode: Sort * * P3
**
** Sort all elements on the sorter.  The algorithm is a
................................................................................
  Sorter *pSorter = p->pSort;
  CHECK_FOR_INTERRUPT;
  if( pSorter!=0 ){
    p->pSort = pSorter->pNext;
    pTos++;
    pTos->flags = MEM_Null;
    rc = sqlite3VdbeMemMove(pTos, &pSorter->data);
    assert( rc==SQLITE_OK );
    sqliteFree(pSorter->zKey);
    sqliteFree(pSorter);
  }else{
    pc = pOp->p2 - 1;
  }
  break;
}
................................................................................
** for all memory locations between 0 and P1 inclusive.
**
** After the data is stored in the memory location, the
** stack is popped once if P2 is 1.  If P2 is zero, then
** the original data remains on the stack.
*/
case OP_MemStore: {
  int i = pOp->p1;
  Mem *pMem;
  assert( pTos>=p->aStack );
  assert( i<p->nMem );
  Deephemeralize(pTos);
  pMem = &p->aMem[i];
  Release(pMem);
  *pMem = *pTos;
  pTos->flags = MEM_Null;
  if( pMem->flags & MEM_Short ){
    pMem->z = pMem->zShort;
  }

  pTos--;

  /* If P2 is 0 then fall thru to the next opcode, OP_MemLoad, that will
  ** restore the top of the stack to its original value.
  */
  if( pOp->p2 ){
    break;
................................................................................
** location is subsequently changed (using OP_MemStore) then the
** value pushed onto the stack will change too.
*/
case OP_MemLoad: {
  int i = pOp->p1;
  assert( i>=0 && i<p->nMem );
  pTos++;
  memcpy(pTos, &p->aMem[i], sizeof(pTos[0])-NBFS);;
  pTos->xDel = 0;
  if( pTos->flags & (MEM_Str|MEM_Blob) ){
    pTos->flags |= MEM_Ephem;
    pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
  }
  break;
}

/* Opcode: MemIncr P1 P2 *
**
** Increment the integer valued memory cell P1 by 1.  If P2 is not zero
** and the result after the increment is greater than zero, then jump
................................................................................
**
** Move the top of the stack into the P2-th field of the current
** aggregate.  String values are duplicated into new memory.
*/
case OP_AggSet: {
  AggElem *pFocus;
  int i = pOp->p2;
  Mem *pMem;
  rc = AggInFocus(&p->agg, &pFocus);
  if( rc!=SQLITE_OK ) goto abort_due_to_error;
  assert( pTos>=p->aStack );
  if( pFocus==0 ) goto no_mem;
  assert( i>=0 && i<p->agg.nMem );
  Deephemeralize(pTos);
  pMem = &pFocus->aMem[i];
  Release(pMem);
  *pMem = *pTos;
  pTos->flags = MEM_Null;
  if( pMem->flags & MEM_Short ){
    pMem->z = pMem->zShort;
  }
  pTos--;
  break;
}

/* Opcode: AggGet * P2 *
**
** Push a new entry onto the stack which is a copy of the P2-th field
** of the current aggregate.  Strings are not duplicated so
** string values will be ephemeral.
*/
case OP_AggGet: {
  AggElem *pFocus;
  Mem *pMem;
  int i = pOp->p2;
  rc = AggInFocus(&p->agg, &pFocus);
  if( rc!=SQLITE_OK ) goto abort_due_to_error;
  if( pFocus==0 ) goto no_mem;
  assert( i>=0 && i<p->agg.nMem );
  pTos++;
  pMem = &pFocus->aMem[i];
  *pTos = *pMem;
  pTos->xDel = 0;
  if( pTos->flags & (MEM_Str|MEM_Blob) ){
    pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
    pTos->flags |= MEM_Ephem;
  }
  if( pTos->flags&MEM_Str ){
    sqlite3VdbeChangeEncoding(pTos, db->enc);
  }

  break;
}

/* Opcode: AggNext * P2 *
**
** Make the next aggregate value the current aggregate.  The prior
** aggregate is deleted.  If all aggregate values have been consumed,







|







 







|
<
<
<
<
<







 







|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
>







 







|
<
<
<
<
<
<







 







<

|
|
<
>
|







 







>







 







>
>
>








|
<
|
>
|
|
|
>
>
>
>
>
>
>
>

<
>
>
>
>







 







>







 







>







 







<
<







 







<
<







 







<







 







<
<

|
<
<
<
<
<
<
<
<
>







 







|
<
<
<
<
<







 







<





<
|
<
<
<
<
<
<












<






|
|
|
<
<
<
<



>







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
...
788
789
790
791
792
793
794
795





796
797
798
799
800
801
802
...
822
823
824
825
826
827
828
829


830













831
832
833
834
835
836
837
838
...
875
876
877
878
879
880
881
882






883
884
885
886
887
888
889
....
1211
1212
1213
1214
1215
1216
1217

1218
1219
1220

1221
1222
1223
1224
1225
1226
1227
1228
1229
....
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
....
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926

1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940

1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
....
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
....
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
....
3508
3509
3510
3511
3512
3513
3514


3515
3516
3517
3518
3519
3520
3521
....
4004
4005
4006
4007
4008
4009
4010


4011
4012
4013
4014
4015
4016
4017
....
4063
4064
4065
4066
4067
4068
4069

4070
4071
4072
4073
4074
4075
4076
....
4091
4092
4093
4094
4095
4096
4097


4098
4099








4100
4101
4102
4103
4104
4105
4106
4107
....
4116
4117
4118
4119
4120
4121
4122
4123





4124
4125
4126
4127
4128
4129
4130
....
4290
4291
4292
4293
4294
4295
4296

4297
4298
4299
4300
4301

4302






4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314

4315
4316
4317
4318
4319
4320
4321
4322
4323




4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
**
** 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.410 2004/08/28 18:17:48 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
................................................................................
** sqlite3_bind() API.
*/
case OP_Variable: {
  int j = pOp->p1 - 1;
  assert( j>=0 && j<p->nVar );

  pTos++;
  sqlite3VdbeMemShallowCopy(pTos, &p->aVar[j], MEM_Static);





  break;
}

/* Opcode: Pop P1 * *
**
** P1 elements are popped off of the top of stack and discarded.
*/
................................................................................
**
** Also see the Pull instruction.
*/
case OP_Dup: {
  Mem *pFrom = &pTos[-pOp->p1];
  assert( pFrom<=pTos && pFrom>=p->aStack );
  pTos++;
  sqlite3VdbeMemShallowCopy(pTos, pFrom, MEM_Ephem);


  if( pOp->p2 ){













    Deephemeralize(pTos);
  }
  break;
}

/* Opcode: Pull P1 * *
**
** The P1-th element is removed from its current location on 
................................................................................
** stack (P1==0 is the top of the stack) with the value
** of the top of the stack.  Then pop the top of the stack.
*/
case OP_Push: {
  Mem *pTo = &pTos[-pOp->p1];

  assert( pTo>=p->aStack );
  sqlite3VdbeMemMove(pTo, pTos);






  pTos--;
  break;
}

/* Opcode: Callback P1 * *
**
** Pop P1 values off the stack and form them into an array.  Then
................................................................................
  if( ctx.pVdbeFunc ){
    sqlite3VdbeDeleteAuxData(ctx.pVdbeFunc, pOp->p2);
    pOp->p3 = (char *)ctx.pVdbeFunc;
    pOp->p3type = P3_VDBEFUNC;
  }

  /* Copy the result of the function to the top of the stack */

  sqlite3VdbeChangeEncoding(&ctx.s, db->enc);
  pTos++;
  pTos->flags = 0;

  sqlite3VdbeMemMove(pTos, &ctx.s);

  /* If the function returned an error, throw an exception */
  if( ctx.isError ){
    if( !(pTos->flags&MEM_Str) ){
      sqlite3SetString(&p->zErrMsg, "user function error", (char*)0);
    }else{
      sqlite3SetString(&p->zErrMsg, sqlite3_value_text(pTos), (char*)0);
      sqlite3VdbeChangeEncoding(pTos, db->enc);
................................................................................
  int i;             /* Loop counter */
  char *zData;       /* Part of the record being decoded */
  Mem sMem;          /* For storing the record being decoded */

  sMem.flags = 0;
  assert( p1<p->nCursor );
  pTos++;
  pTos->flags = MEM_Null;

  /* This block sets the variable payloadSize to be the total number of
  ** bytes in the record.
  **
  ** zRec is set to be the complete text of the record if it is available.
  ** The complete record text is always available for pseudo-tables and
  ** when we are decoded a record from the stack.  If the record is stored
................................................................................
      pC->aOffset = aOffset;
      pC->cacheValid = 1;
    }
  }

  /* Get the column information.
  */
  if( rc!=SQLITE_OK ){
    goto abort_due_to_error;
  }
  if( zRec ){
    zData = &zRec[aOffset[p2]];
  }else{
    len = sqlite3VdbeSerialTypeLen(aType[p2]);
    sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->keyAsData, &sMem);
    zData = sMem.z;
  }
  sqlite3VdbeSerialGet(zData, aType[p2], pTos);
  pTos->enc = db->enc;


  /* If we dynamically allocated space to hold the data (in the
  ** sqlite3VdbeMemFromBtree() call above) then transfer control of that
  ** dynamically allocated space over to the pTos structure rather.
  ** This prevents a memory copy.
  */
  if( (sMem.flags & MEM_Dyn)!=0 ){
    assert( pTos->flags & MEM_Ephem );
    assert( pTos->flags & (MEM_Str|MEM_Blob) );
    assert( pTos->z==sMem.z );
    assert( sMem.flags & MEM_Term );
    pTos->flags &= ~MEM_Ephem;
    pTos->flags |= MEM_Dyn|MEM_Term;
  }


  /* pTos->z might be pointing to sMem.zShort[].  Fix that so that we
  ** can abandon sMem */
  rc = sqlite3VdbeMemMakeWriteable(pTos);

  /* Release the aType[] memory if we are not dealing with cursor */
  if( !pC ){
    sqliteFree(aType);
  }
  break;
}
................................................................................
  Cursor *pC;

  assert( i>=0 && i<p->nCursor );
  assert( p->apCsr[i]!=0 );
  assert( p->apCsr[i]->keyAsData );
  assert( !p->apCsr[i]->pseudoTable );
  pTos++;
  pTos->flags = MEM_Null;
  if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
    i64 amt;
    char *z;

    sqlite3VdbeCursorMoveto(pC);
    assert( pC->intKey==0 );
    sqlite3BtreeKeySize(pCrsr, &amt);
................................................................................
  int i = pOp->p1;
  BtCursor *pCrsr;
  Cursor *pC;

  assert( i>=0 && i<p->nCursor );
  assert( p->apCsr[i]!=0 );
  pTos++;
  pTos->flags = MEM_Null;
  if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
    i64 rowid;

    assert( pC->deferredMoveto==0 );
    assert( pC->intKey==0 );
    if( pC->nullRow ){
      pTos->flags = MEM_Null;
................................................................................
      rc = sqlite3VdbeIdxRowid(pCrsr, &rowid);
      if( rc!=SQLITE_OK ){
        goto abort_due_to_error;
      }
      pTos->flags = MEM_Int;
      pTos->i = rowid;
    }


  }
  break;
}

/* Opcode: IdxGT P1 P2 *
**
** The top of the stack is an index entry that omits the ROWID.  Compare
................................................................................
  pSorter->pNext = p->pSort;
  p->pSort = pSorter;
  assert( pTos->flags & MEM_Dyn );
  pSorter->nKey = pTos->n;
  pSorter->zKey = pTos->z;
  pSorter->data.flags = MEM_Null;
  rc = sqlite3VdbeMemMove(&pSorter->data, pNos);


  pTos -= 2;
  break;
}

/* Opcode: Sort * * P3
**
** Sort all elements on the sorter.  The algorithm is a
................................................................................
  Sorter *pSorter = p->pSort;
  CHECK_FOR_INTERRUPT;
  if( pSorter!=0 ){
    p->pSort = pSorter->pNext;
    pTos++;
    pTos->flags = MEM_Null;
    rc = sqlite3VdbeMemMove(pTos, &pSorter->data);

    sqliteFree(pSorter->zKey);
    sqliteFree(pSorter);
  }else{
    pc = pOp->p2 - 1;
  }
  break;
}
................................................................................
** for all memory locations between 0 and P1 inclusive.
**
** After the data is stored in the memory location, the
** stack is popped once if P2 is 1.  If P2 is zero, then
** the original data remains on the stack.
*/
case OP_MemStore: {


  assert( pTos>=p->aStack );
  assert( pOp->p1>=0 && pOp->p1<p->nMem );








  rc = sqlite3VdbeMemMove(&p->aMem[pOp->p1], pTos);
  pTos--;

  /* If P2 is 0 then fall thru to the next opcode, OP_MemLoad, that will
  ** restore the top of the stack to its original value.
  */
  if( pOp->p2 ){
    break;
................................................................................
** location is subsequently changed (using OP_MemStore) then the
** value pushed onto the stack will change too.
*/
case OP_MemLoad: {
  int i = pOp->p1;
  assert( i>=0 && i<p->nMem );
  pTos++;
  sqlite3VdbeMemShallowCopy(pTos, &p->aMem[i], MEM_Ephem);





  break;
}

/* Opcode: MemIncr P1 P2 *
**
** Increment the integer valued memory cell P1 by 1.  If P2 is not zero
** and the result after the increment is greater than zero, then jump
................................................................................
**
** Move the top of the stack into the P2-th field of the current
** aggregate.  String values are duplicated into new memory.
*/
case OP_AggSet: {
  AggElem *pFocus;
  int i = pOp->p2;

  rc = AggInFocus(&p->agg, &pFocus);
  if( rc!=SQLITE_OK ) goto abort_due_to_error;
  assert( pTos>=p->aStack );
  if( pFocus==0 ) goto no_mem;
  assert( i>=0 && i<p->agg.nMem );

  rc = sqlite3VdbeMemMove(&pFocus->aMem[i], pTos);






  pTos--;
  break;
}

/* Opcode: AggGet * P2 *
**
** Push a new entry onto the stack which is a copy of the P2-th field
** of the current aggregate.  Strings are not duplicated so
** string values will be ephemeral.
*/
case OP_AggGet: {
  AggElem *pFocus;

  int i = pOp->p2;
  rc = AggInFocus(&p->agg, &pFocus);
  if( rc!=SQLITE_OK ) goto abort_due_to_error;
  if( pFocus==0 ) goto no_mem;
  assert( i>=0 && i<p->agg.nMem );
  pTos++;
  sqlite3VdbeMemShallowCopy(pTos, &pFocus->aMem[i], MEM_Ephem);
  assert( (pTos->flags & MEM_Str)==0 || pTos->enc==db->enc );
#if 0




  if( pTos->flags&MEM_Str ){
    sqlite3VdbeChangeEncoding(pTos, db->enc);
  }
#endif
  break;
}

/* Opcode: AggNext * P2 *
**
** Make the next aggregate value the current aggregate.  The prior
** aggregate is deleted.  If all aggregate values have been consumed,

Changes to src/vdbeInt.h.

377
378
379
380
381
382
383

384
385
386
387
388
389
390
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
int sqlite3VdbeRecordCompare(void*,int,const void*,int, const void*);
int sqlite3VdbeIdxRowidLen(int,const u8*);
int sqlite3VdbeExec(Vdbe*);
int sqlite3VdbeList(Vdbe*);
int sqlite3VdbeChangeEncoding(Mem *, int);
int sqlite3VdbeMemCopy(Mem*, const Mem*);

int sqlite3VdbeMemMove(Mem*, Mem*);
int sqlite3VdbeMemNulTerminate(Mem*);
int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
void sqlite3VdbeMemSetInt64(Mem*, i64);
void sqlite3VdbeMemSetDouble(Mem*, double);
void sqlite3VdbeMemSetNull(Mem*);
int sqlite3VdbeMemMakeWriteable(Mem*);







>







377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
int sqlite3VdbeRecordCompare(void*,int,const void*,int, const void*);
int sqlite3VdbeIdxRowidLen(int,const u8*);
int sqlite3VdbeExec(Vdbe*);
int sqlite3VdbeList(Vdbe*);
int sqlite3VdbeChangeEncoding(Mem *, int);
int sqlite3VdbeMemCopy(Mem*, const Mem*);
void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
int sqlite3VdbeMemMove(Mem*, Mem*);
int sqlite3VdbeMemNulTerminate(Mem*);
int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
void sqlite3VdbeMemSetInt64(Mem*, i64);
void sqlite3VdbeMemSetDouble(Mem*, double);
void sqlite3VdbeMemSetNull(Mem*);
int sqlite3VdbeMemMakeWriteable(Mem*);

Changes to src/vdbemem.c.

295
296
297
298
299
300
301
302
303
304
305
306

307
308
309
310

311














312
313
314
315
316
317
318
319
320


321


322
323




324
325
326
327
328
329



330


331
332
333
334
335
336
337
  sqlite3VdbeMemRelease(pMem);
  pMem->r = val;
  pMem->flags = MEM_Real;
  pMem->type = SQLITE_FLOAT;
}

/*
** Copy the contents of memory cell pFrom into pTo.
*/
int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
  int rc;
  sqlite3VdbeMemRelease(pTo);

  memcpy(pTo, pFrom, sizeof(*pFrom)-sizeof(pFrom->zShort));
  pTo->xDel = 0;
  if( pTo->flags & (MEM_Str|MEM_Blob) ){
    pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);

    pTo->flags |= MEM_Ephem;














    rc = sqlite3VdbeMemMakeWriteable(pTo);
  }else{
    rc = SQLITE_OK;
  }
  return rc;
}

/*
** Transfer the contents of pFrom to pTo. Any existing value in pTo is


** deleted. pFrom contains an SQL NULL when this routine returns.


*/
int sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){




  memcpy(pTo, pFrom, sizeof(Mem));
  if( pFrom->flags & MEM_Short ){
    pTo->z = pTo->zShort;
  }
  pFrom->flags = MEM_Null;
  pFrom->xDel = 0;



  return SQLITE_OK;


}

/*
** Change the value of a Mem to be a string or a BLOB.
*/
int sqlite3VdbeMemSetStr(
  Mem *pMem,          /* Memory cell to set to string value */







|
|
|
|
|
>



|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>









>
>
|
>
>


>
>
>
>






>
>
>
|
>
>







295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
  sqlite3VdbeMemRelease(pMem);
  pMem->r = val;
  pMem->flags = MEM_Real;
  pMem->type = SQLITE_FLOAT;
}

/*
** Make an shallow copy of pFrom into pTo.  Prior contents of
** pTo are overwritten.  The pFrom->z field is not duplicated.  If
** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
** and flags gets srcType (either MEM_Ephem or MEM_Static).
*/
void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
  memcpy(pTo, pFrom, sizeof(*pFrom)-sizeof(pFrom->zShort));
  pTo->xDel = 0;
  if( pTo->flags & (MEM_Str|MEM_Blob) ){
    pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short|MEM_Ephem);
    assert( srcType==MEM_Ephem || srcType==MEM_Static );
    pTo->flags |= srcType;
  }
}

/*
** Make a full copy of pFrom into pTo.  Prior contents of pTo are
** freed before the copy is made.
*/
int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
  int rc;
  if( pTo->flags & MEM_Dyn ){
    sqlite3VdbeMemRelease(pTo);
  }
  sqlite3VdbeMemShallowCopy(pTo, pFrom, MEM_Ephem);
  if( pTo->flags & MEM_Ephem ){
    rc = sqlite3VdbeMemMakeWriteable(pTo);
  }else{
    rc = SQLITE_OK;
  }
  return rc;
}

/*
** Transfer the contents of pFrom to pTo. Any existing value in pTo is
** freed. If pFrom contains ephemeral data, a copy is made.
**
** pFrom contains an SQL NULL when this routine returns.  SQLITE_NOMEM
** might be returned if pFrom held ephemeral data and we were unable
** to allocate enough space to make a copy.
*/
int sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
  int rc;
  if( pTo->flags & MEM_Dyn ){
    sqlite3VdbeMemRelease(pTo);
  }
  memcpy(pTo, pFrom, sizeof(Mem));
  if( pFrom->flags & MEM_Short ){
    pTo->z = pTo->zShort;
  }
  pFrom->flags = MEM_Null;
  pFrom->xDel = 0;
  if( pTo->flags & MEM_Ephem ){
    rc = sqlite3VdbeMemMakeWriteable(pTo);
  }else{
    rc = SQLITE_OK;
  }
  return rc;
}

/*
** Change the value of a Mem to be a string or a BLOB.
*/
int sqlite3VdbeMemSetStr(
  Mem *pMem,          /* Memory cell to set to string value */