/ Check-in [5f8d2468]
Login

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 Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

    39     39   **
    40     40   ** Various scripts scan this source file in order to generate HTML
    41     41   ** documentation, headers files, or other derived files.  The formatting
    42     42   ** of the code in this file is, therefore, important.  See other comments
    43     43   ** in this file for details.  If in doubt, do not deviate from existing
    44     44   ** commenting and indentation practices when changing or adding code.
    45     45   **
    46         -** $Id: vdbe.c,v 1.409 2004/08/21 17:54:45 drh Exp $
           46  +** $Id: vdbe.c,v 1.410 2004/08/28 18:17:48 drh Exp $
    47     47   */
    48     48   #include "sqliteInt.h"
    49     49   #include "os.h"
    50     50   #include <ctype.h>
    51     51   #include "vdbeInt.h"
    52     52   
    53     53   /*
................................................................................
   788    788   ** sqlite3_bind() API.
   789    789   */
   790    790   case OP_Variable: {
   791    791     int j = pOp->p1 - 1;
   792    792     assert( j>=0 && j<p->nVar );
   793    793   
   794    794     pTos++;
   795         -  memcpy(pTos, &p->aVar[j], sizeof(*pTos)-NBFS);
   796         -  pTos->xDel = 0;
   797         -  if( pTos->flags&(MEM_Str|MEM_Blob) ){
   798         -    pTos->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Short);
   799         -    pTos->flags |= MEM_Static;
   800         -  }
          795  +  sqlite3VdbeMemShallowCopy(pTos, &p->aVar[j], MEM_Static);
   801    796     break;
   802    797   }
   803    798   
   804    799   /* Opcode: Pop P1 * *
   805    800   **
   806    801   ** P1 elements are popped off of the top of stack and discarded.
   807    802   */
................................................................................
   827    822   **
   828    823   ** Also see the Pull instruction.
   829    824   */
   830    825   case OP_Dup: {
   831    826     Mem *pFrom = &pTos[-pOp->p1];
   832    827     assert( pFrom<=pTos && pFrom>=p->aStack );
   833    828     pTos++;
   834         -  memcpy(pTos, pFrom, sizeof(*pFrom)-NBFS);
   835         -  pTos->xDel = 0;
   836         -  if( pTos->flags & (MEM_Str|MEM_Blob) ){
   837         -    if( pOp->p2 && (pTos->flags & (MEM_Dyn|MEM_Ephem)) ){
   838         -      pTos->flags &= ~MEM_Dyn;
   839         -      pTos->flags |= MEM_Ephem;
   840         -    }else if( pTos->flags & MEM_Short ){
   841         -      memcpy(pTos->zShort, pFrom->zShort, pTos->n+2);
   842         -      pTos->z = pTos->zShort;
   843         -    }else if( (pTos->flags & MEM_Static)==0 ){
   844         -      pTos->z = sqliteMallocRaw(pFrom->n+2);
   845         -      if( sqlite3_malloc_failed ) goto no_mem;
   846         -      memcpy(pTos->z, pFrom->z, pFrom->n);
   847         -      memcpy(&pTos->z[pTos->n], "\0", 2);
   848         -      pTos->flags &= ~(MEM_Static|MEM_Ephem|MEM_Short);
   849         -      pTos->flags |= MEM_Dyn|MEM_Term;
   850         -    }
          829  +  sqlite3VdbeMemShallowCopy(pTos, pFrom, MEM_Ephem);
          830  +  if( pOp->p2 ){
          831  +    Deephemeralize(pTos);
   851    832     }
   852    833     break;
   853    834   }
   854    835   
   855    836   /* Opcode: Pull P1 * *
   856    837   **
   857    838   ** The P1-th element is removed from its current location on 
................................................................................
   894    875   ** stack (P1==0 is the top of the stack) with the value
   895    876   ** of the top of the stack.  Then pop the top of the stack.
   896    877   */
   897    878   case OP_Push: {
   898    879     Mem *pTo = &pTos[-pOp->p1];
   899    880   
   900    881     assert( pTo>=p->aStack );
   901         -  Deephemeralize(pTos);
   902         -  Release(pTo);
   903         -  *pTo = *pTos;
   904         -  if( pTo->flags & MEM_Short ){
   905         -    assert( pTo->z==pTos->zShort );
   906         -    pTo->z = pTo->zShort;
   907         -  }
          882  +  sqlite3VdbeMemMove(pTo, pTos);
   908    883     pTos--;
   909    884     break;
   910    885   }
   911    886   
   912    887   /* Opcode: Callback P1 * *
   913    888   **
   914    889   ** Pop P1 values off the stack and form them into an array.  Then
................................................................................
  1236   1211     if( ctx.pVdbeFunc ){
  1237   1212       sqlite3VdbeDeleteAuxData(ctx.pVdbeFunc, pOp->p2);
  1238   1213       pOp->p3 = (char *)ctx.pVdbeFunc;
  1239   1214       pOp->p3type = P3_VDBEFUNC;
  1240   1215     }
  1241   1216   
  1242   1217     /* Copy the result of the function to the top of the stack */
  1243         -  pTos++;
  1244   1218     sqlite3VdbeChangeEncoding(&ctx.s, db->enc);
  1245         -  *pTos = ctx.s;
  1246         -  if( pTos->flags & MEM_Short ){
  1247         -    pTos->z = pTos->zShort;
  1248         -  }
         1219  +  pTos++;
         1220  +  pTos->flags = 0;
         1221  +  sqlite3VdbeMemMove(pTos, &ctx.s);
         1222  +
  1249   1223     /* If the function returned an error, throw an exception */
  1250   1224     if( ctx.isError ){
  1251   1225       if( !(pTos->flags&MEM_Str) ){
  1252   1226         sqlite3SetString(&p->zErrMsg, "user function error", (char*)0);
  1253   1227       }else{
  1254   1228         sqlite3SetString(&p->zErrMsg, sqlite3_value_text(pTos), (char*)0);
  1255   1229         sqlite3VdbeChangeEncoding(pTos, db->enc);
................................................................................
  1769   1743     int i;             /* Loop counter */
  1770   1744     char *zData;       /* Part of the record being decoded */
  1771   1745     Mem sMem;          /* For storing the record being decoded */
  1772   1746   
  1773   1747     sMem.flags = 0;
  1774   1748     assert( p1<p->nCursor );
  1775   1749     pTos++;
         1750  +  pTos->flags = MEM_Null;
  1776   1751   
  1777   1752     /* This block sets the variable payloadSize to be the total number of
  1778   1753     ** bytes in the record.
  1779   1754     **
  1780   1755     ** zRec is set to be the complete text of the record if it is available.
  1781   1756     ** The complete record text is always available for pseudo-tables and
  1782   1757     ** when we are decoded a record from the stack.  If the record is stored
................................................................................
  1933   1908         pC->aOffset = aOffset;
  1934   1909         pC->cacheValid = 1;
  1935   1910       }
  1936   1911     }
  1937   1912   
  1938   1913     /* Get the column information.
  1939   1914     */
         1915  +  if( rc!=SQLITE_OK ){
         1916  +    goto abort_due_to_error;
         1917  +  }
  1940   1918     if( zRec ){
  1941   1919       zData = &zRec[aOffset[p2]];
  1942   1920     }else{
  1943   1921       len = sqlite3VdbeSerialTypeLen(aType[p2]);
  1944   1922       sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->keyAsData, &sMem);
  1945   1923       zData = sMem.z;
  1946   1924     }
  1947   1925     sqlite3VdbeSerialGet(zData, aType[p2], pTos);
  1948         -  if( sqlite3VdbeMemMakeWriteable(pTos)==SQLITE_NOMEM ){
  1949         -    goto no_mem;
  1950         -  }
  1951   1926     pTos->enc = db->enc;
  1952         -  if( rc!=SQLITE_OK ){
  1953         -    goto abort_due_to_error;
         1927  +
         1928  +  /* If we dynamically allocated space to hold the data (in the
         1929  +  ** sqlite3VdbeMemFromBtree() call above) then transfer control of that
         1930  +  ** dynamically allocated space over to the pTos structure rather.
         1931  +  ** This prevents a memory copy.
         1932  +  */
         1933  +  if( (sMem.flags & MEM_Dyn)!=0 ){
         1934  +    assert( pTos->flags & MEM_Ephem );
         1935  +    assert( pTos->flags & (MEM_Str|MEM_Blob) );
         1936  +    assert( pTos->z==sMem.z );
         1937  +    assert( sMem.flags & MEM_Term );
         1938  +    pTos->flags &= ~MEM_Ephem;
         1939  +    pTos->flags |= MEM_Dyn|MEM_Term;
  1954   1940     }
  1955         -  Release(&sMem);
         1941  +
         1942  +  /* pTos->z might be pointing to sMem.zShort[].  Fix that so that we
         1943  +  ** can abandon sMem */
         1944  +  rc = sqlite3VdbeMemMakeWriteable(pTos);
  1956   1945   
  1957   1946     /* Release the aType[] memory if we are not dealing with cursor */
  1958   1947     if( !pC ){
  1959   1948       sqliteFree(aType);
  1960   1949     }
  1961   1950     break;
  1962   1951   }
................................................................................
  3246   3235     Cursor *pC;
  3247   3236   
  3248   3237     assert( i>=0 && i<p->nCursor );
  3249   3238     assert( p->apCsr[i]!=0 );
  3250   3239     assert( p->apCsr[i]->keyAsData );
  3251   3240     assert( !p->apCsr[i]->pseudoTable );
  3252   3241     pTos++;
         3242  +  pTos->flags = MEM_Null;
  3253   3243     if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
  3254   3244       i64 amt;
  3255   3245       char *z;
  3256   3246   
  3257   3247       sqlite3VdbeCursorMoveto(pC);
  3258   3248       assert( pC->intKey==0 );
  3259   3249       sqlite3BtreeKeySize(pCrsr, &amt);
................................................................................
  3502   3492     int i = pOp->p1;
  3503   3493     BtCursor *pCrsr;
  3504   3494     Cursor *pC;
  3505   3495   
  3506   3496     assert( i>=0 && i<p->nCursor );
  3507   3497     assert( p->apCsr[i]!=0 );
  3508   3498     pTos++;
         3499  +  pTos->flags = MEM_Null;
  3509   3500     if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
  3510   3501       i64 rowid;
  3511   3502   
  3512   3503       assert( pC->deferredMoveto==0 );
  3513   3504       assert( pC->intKey==0 );
  3514   3505       if( pC->nullRow ){
  3515   3506         pTos->flags = MEM_Null;
................................................................................
  3517   3508         rc = sqlite3VdbeIdxRowid(pCrsr, &rowid);
  3518   3509         if( rc!=SQLITE_OK ){
  3519   3510           goto abort_due_to_error;
  3520   3511         }
  3521   3512         pTos->flags = MEM_Int;
  3522   3513         pTos->i = rowid;
  3523   3514       }
  3524         -  }else{
  3525         -    pTos->flags = MEM_Null;
  3526   3515     }
  3527   3516     break;
  3528   3517   }
  3529   3518   
  3530   3519   /* Opcode: IdxGT P1 P2 *
  3531   3520   **
  3532   3521   ** The top of the stack is an index entry that omits the ROWID.  Compare
................................................................................
  4015   4004     pSorter->pNext = p->pSort;
  4016   4005     p->pSort = pSorter;
  4017   4006     assert( pTos->flags & MEM_Dyn );
  4018   4007     pSorter->nKey = pTos->n;
  4019   4008     pSorter->zKey = pTos->z;
  4020   4009     pSorter->data.flags = MEM_Null;
  4021   4010     rc = sqlite3VdbeMemMove(&pSorter->data, pNos);
  4022         -  if( rc!=SQLITE_OK ) goto abort_due_to_error;
  4023         -  Deephemeralize(&pSorter->data);
  4024   4011     pTos -= 2;
  4025   4012     break;
  4026   4013   }
  4027   4014   
  4028   4015   /* Opcode: Sort * * P3
  4029   4016   **
  4030   4017   ** Sort all elements on the sorter.  The algorithm is a
................................................................................
  4076   4063     Sorter *pSorter = p->pSort;
  4077   4064     CHECK_FOR_INTERRUPT;
  4078   4065     if( pSorter!=0 ){
  4079   4066       p->pSort = pSorter->pNext;
  4080   4067       pTos++;
  4081   4068       pTos->flags = MEM_Null;
  4082   4069       rc = sqlite3VdbeMemMove(pTos, &pSorter->data);
  4083         -    assert( rc==SQLITE_OK );
  4084   4070       sqliteFree(pSorter->zKey);
  4085   4071       sqliteFree(pSorter);
  4086   4072     }else{
  4087   4073       pc = pOp->p2 - 1;
  4088   4074     }
  4089   4075     break;
  4090   4076   }
................................................................................
  4105   4091   ** for all memory locations between 0 and P1 inclusive.
  4106   4092   **
  4107   4093   ** After the data is stored in the memory location, the
  4108   4094   ** stack is popped once if P2 is 1.  If P2 is zero, then
  4109   4095   ** the original data remains on the stack.
  4110   4096   */
  4111   4097   case OP_MemStore: {
  4112         -  int i = pOp->p1;
  4113         -  Mem *pMem;
  4114   4098     assert( pTos>=p->aStack );
  4115         -  assert( i<p->nMem );
  4116         -  Deephemeralize(pTos);
  4117         -  pMem = &p->aMem[i];
  4118         -  Release(pMem);
  4119         -  *pMem = *pTos;
  4120         -  pTos->flags = MEM_Null;
  4121         -  if( pMem->flags & MEM_Short ){
  4122         -    pMem->z = pMem->zShort;
  4123         -  }
         4099  +  assert( pOp->p1>=0 && pOp->p1<p->nMem );
         4100  +  rc = sqlite3VdbeMemMove(&p->aMem[pOp->p1], pTos);
  4124   4101     pTos--;
  4125   4102   
  4126   4103     /* If P2 is 0 then fall thru to the next opcode, OP_MemLoad, that will
  4127   4104     ** restore the top of the stack to its original value.
  4128   4105     */
  4129   4106     if( pOp->p2 ){
  4130   4107       break;
................................................................................
  4139   4116   ** location is subsequently changed (using OP_MemStore) then the
  4140   4117   ** value pushed onto the stack will change too.
  4141   4118   */
  4142   4119   case OP_MemLoad: {
  4143   4120     int i = pOp->p1;
  4144   4121     assert( i>=0 && i<p->nMem );
  4145   4122     pTos++;
  4146         -  memcpy(pTos, &p->aMem[i], sizeof(pTos[0])-NBFS);;
  4147         -  pTos->xDel = 0;
  4148         -  if( pTos->flags & (MEM_Str|MEM_Blob) ){
  4149         -    pTos->flags |= MEM_Ephem;
  4150         -    pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
  4151         -  }
         4123  +  sqlite3VdbeMemShallowCopy(pTos, &p->aMem[i], MEM_Ephem);
  4152   4124     break;
  4153   4125   }
  4154   4126   
  4155   4127   /* Opcode: MemIncr P1 P2 *
  4156   4128   **
  4157   4129   ** Increment the integer valued memory cell P1 by 1.  If P2 is not zero
  4158   4130   ** and the result after the increment is greater than zero, then jump
................................................................................
  4318   4290   **
  4319   4291   ** Move the top of the stack into the P2-th field of the current
  4320   4292   ** aggregate.  String values are duplicated into new memory.
  4321   4293   */
  4322   4294   case OP_AggSet: {
  4323   4295     AggElem *pFocus;
  4324   4296     int i = pOp->p2;
  4325         -  Mem *pMem;
  4326   4297     rc = AggInFocus(&p->agg, &pFocus);
  4327   4298     if( rc!=SQLITE_OK ) goto abort_due_to_error;
  4328   4299     assert( pTos>=p->aStack );
  4329   4300     if( pFocus==0 ) goto no_mem;
  4330   4301     assert( i>=0 && i<p->agg.nMem );
  4331         -  Deephemeralize(pTos);
  4332         -  pMem = &pFocus->aMem[i];
  4333         -  Release(pMem);
  4334         -  *pMem = *pTos;
  4335         -  pTos->flags = MEM_Null;
  4336         -  if( pMem->flags & MEM_Short ){
  4337         -    pMem->z = pMem->zShort;
  4338         -  }
         4302  +  rc = sqlite3VdbeMemMove(&pFocus->aMem[i], pTos);
  4339   4303     pTos--;
  4340   4304     break;
  4341   4305   }
  4342   4306   
  4343   4307   /* Opcode: AggGet * P2 *
  4344   4308   **
  4345   4309   ** Push a new entry onto the stack which is a copy of the P2-th field
  4346   4310   ** of the current aggregate.  Strings are not duplicated so
  4347   4311   ** string values will be ephemeral.
  4348   4312   */
  4349   4313   case OP_AggGet: {
  4350   4314     AggElem *pFocus;
  4351         -  Mem *pMem;
  4352   4315     int i = pOp->p2;
  4353   4316     rc = AggInFocus(&p->agg, &pFocus);
  4354   4317     if( rc!=SQLITE_OK ) goto abort_due_to_error;
  4355   4318     if( pFocus==0 ) goto no_mem;
  4356   4319     assert( i>=0 && i<p->agg.nMem );
  4357   4320     pTos++;
  4358         -  pMem = &pFocus->aMem[i];
  4359         -  *pTos = *pMem;
  4360         -  pTos->xDel = 0;
  4361         -  if( pTos->flags & (MEM_Str|MEM_Blob) ){
  4362         -    pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
  4363         -    pTos->flags |= MEM_Ephem;
  4364         -  }
         4321  +  sqlite3VdbeMemShallowCopy(pTos, &pFocus->aMem[i], MEM_Ephem);
         4322  +  assert( (pTos->flags & MEM_Str)==0 || pTos->enc==db->enc );
         4323  +#if 0
  4365   4324     if( pTos->flags&MEM_Str ){
  4366   4325       sqlite3VdbeChangeEncoding(pTos, db->enc);
  4367   4326     }
         4327  +#endif
  4368   4328     break;
  4369   4329   }
  4370   4330   
  4371   4331   /* Opcode: AggNext * P2 *
  4372   4332   **
  4373   4333   ** Make the next aggregate value the current aggregate.  The prior
  4374   4334   ** aggregate is deleted.  If all aggregate values have been consumed,

Changes to src/vdbeInt.h.

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

Changes to src/vdbemem.c.

   295    295     sqlite3VdbeMemRelease(pMem);
   296    296     pMem->r = val;
   297    297     pMem->flags = MEM_Real;
   298    298     pMem->type = SQLITE_FLOAT;
   299    299   }
   300    300   
   301    301   /*
   302         -** Copy the contents of memory cell pFrom into pTo.
          302  +** Make an shallow copy of pFrom into pTo.  Prior contents of
          303  +** pTo are overwritten.  The pFrom->z field is not duplicated.  If
          304  +** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
          305  +** and flags gets srcType (either MEM_Ephem or MEM_Static).
   303    306   */
   304         -int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
   305         -  int rc;
   306         -  sqlite3VdbeMemRelease(pTo);
          307  +void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
   307    308     memcpy(pTo, pFrom, sizeof(*pFrom)-sizeof(pFrom->zShort));
   308    309     pTo->xDel = 0;
   309    310     if( pTo->flags & (MEM_Str|MEM_Blob) ){
   310         -    pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
   311         -    pTo->flags |= MEM_Ephem;
          311  +    pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short|MEM_Ephem);
          312  +    assert( srcType==MEM_Ephem || srcType==MEM_Static );
          313  +    pTo->flags |= srcType;
          314  +  }
          315  +}
          316  +
          317  +/*
          318  +** Make a full copy of pFrom into pTo.  Prior contents of pTo are
          319  +** freed before the copy is made.
          320  +*/
          321  +int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
          322  +  int rc;
          323  +  if( pTo->flags & MEM_Dyn ){
          324  +    sqlite3VdbeMemRelease(pTo);
          325  +  }
          326  +  sqlite3VdbeMemShallowCopy(pTo, pFrom, MEM_Ephem);
          327  +  if( pTo->flags & MEM_Ephem ){
   312    328       rc = sqlite3VdbeMemMakeWriteable(pTo);
   313    329     }else{
   314    330       rc = SQLITE_OK;
   315    331     }
   316    332     return rc;
   317    333   }
   318    334   
   319    335   /*
   320    336   ** Transfer the contents of pFrom to pTo. Any existing value in pTo is
   321         -** deleted. pFrom contains an SQL NULL when this routine returns.
          337  +** freed. If pFrom contains ephemeral data, a copy is made.
          338  +**
          339  +** pFrom contains an SQL NULL when this routine returns.  SQLITE_NOMEM
          340  +** might be returned if pFrom held ephemeral data and we were unable
          341  +** to allocate enough space to make a copy.
   322    342   */
   323    343   int sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
          344  +  int rc;
          345  +  if( pTo->flags & MEM_Dyn ){
          346  +    sqlite3VdbeMemRelease(pTo);
          347  +  }
   324    348     memcpy(pTo, pFrom, sizeof(Mem));
   325    349     if( pFrom->flags & MEM_Short ){
   326    350       pTo->z = pTo->zShort;
   327    351     }
   328    352     pFrom->flags = MEM_Null;
   329    353     pFrom->xDel = 0;
   330         -  return SQLITE_OK;
          354  +  if( pTo->flags & MEM_Ephem ){
          355  +    rc = sqlite3VdbeMemMakeWriteable(pTo);
          356  +  }else{
          357  +    rc = SQLITE_OK;
          358  +  }
          359  +  return rc;
   331    360   }
   332    361   
   333    362   /*
   334    363   ** Change the value of a Mem to be a string or a BLOB.
   335    364   */
   336    365   int sqlite3VdbeMemSetStr(
   337    366     Mem *pMem,          /* Memory cell to set to string value */