SQLite4
Check-in [610033d7f5]
Not logged in

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

Overview
Comment:Fix compiler warnings.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 610033d7f5832626b274a04eff4521111d214cad
User & Date: drh 2013-07-22 19:49:58
Context
2013-07-22
20:12
Add two new value-encoding header codes to represent REAL-IN-KEY and NONREAL-IN-KEY. This is an incompatible file format change. check-in: b7ac369ba7 user: drh tags: trunk
19:49
Fix compiler warnings. check-in: 610033d7f5 user: drh tags: trunk
18:38
Add the COVERING clause to CREATE INDEX statements. Does not work yet, this commit just adds parser support. check-in: 1710627ec6 user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/analyze.c.

445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
  int regTabname = iMem++;     /* Register containing table name */
  int regIdxname = iMem++;     /* Register containing index name */
  int regStat1 = iMem++;       /* The stat column of sqlite_stat1 */
#ifdef SQLITE4_ENABLE_STAT3
  int regNumEq = regStat1;     /* Number of instances.  Same as regStat1 */
  int regNumLt = iMem++;       /* Number of keys less than regSample */
  int regNumDLt = iMem++;      /* Number of distinct keys less than regSample */
#endif
  int regSample = iMem++;      /* The next sample value */
#ifdef SQLITE4_ENABLE_STAT3
  int regAccum = iMem++;       /* Register to hold Stat3Accum object */
  int regLoop = iMem++;        /* Loop counter */
  int regCount = iMem++;       /* Number of rows in the table or index */
  int regTemp1 = iMem++;       /* Intermediate register */
  int regTemp2 = iMem++;       /* Intermediate register */
  int regNewSample = iMem++;
  int once = 1;                /* One-time initialization */







<

<







445
446
447
448
449
450
451

452

453
454
455
456
457
458
459
  int regTabname = iMem++;     /* Register containing table name */
  int regIdxname = iMem++;     /* Register containing index name */
  int regStat1 = iMem++;       /* The stat column of sqlite_stat1 */
#ifdef SQLITE4_ENABLE_STAT3
  int regNumEq = regStat1;     /* Number of instances.  Same as regStat1 */
  int regNumLt = iMem++;       /* Number of keys less than regSample */
  int regNumDLt = iMem++;      /* Number of distinct keys less than regSample */

  int regSample = iMem++;      /* The next sample value */

  int regAccum = iMem++;       /* Register to hold Stat3Accum object */
  int regLoop = iMem++;        /* Loop counter */
  int regCount = iMem++;       /* Number of rows in the table or index */
  int regTemp1 = iMem++;       /* Intermediate register */
  int regTemp2 = iMem++;       /* Intermediate register */
  int regNewSample = iMem++;
  int once = 1;                /* One-time initialization */

Changes to src/env.c.

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
**
** This routine is not threadsafe.  It should be called from a single
** thread to initialized the library in a multi-threaded system.  Other
** threads should avoid using the sqlite4_env object until after it has
** completely initialized.
*/
int sqlite4_initialize(sqlite4_env *pEnv){
  MUTEX_LOGIC( sqlite4_mutex *pMaster; )       /* The main static mutex */
  int rc;                                      /* Result code */

  if( pEnv==0 ) pEnv = &sqlite4DefaultEnv;

  /* If SQLite is already completely initialized, then this call
  ** to sqlite4_initialize() should be a no-op.  But the initialization
  ** must be complete.  So isInit must not be set until the very end







<







85
86
87
88
89
90
91

92
93
94
95
96
97
98
**
** This routine is not threadsafe.  It should be called from a single
** thread to initialized the library in a multi-threaded system.  Other
** threads should avoid using the sqlite4_env object until after it has
** completely initialized.
*/
int sqlite4_initialize(sqlite4_env *pEnv){

  int rc;                                      /* Result code */

  if( pEnv==0 ) pEnv = &sqlite4DefaultEnv;

  /* If SQLite is already completely initialized, then this call
  ** to sqlite4_initialize() should be a no-op.  But the initialization
  ** must be complete.  So isInit must not be set until the very end

Changes to src/lsm_ckpt.c.

1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
....
1232
1233
1234
1235
1236
1237
1238
1239
}

/*
** Set the output variable to the number of KB of data written into the
** database file since the most recent checkpoint.
*/
int lsmCheckpointSize(lsm_db *db, int *pnKB){
  ShmHeader *pShm = db->pShmhdr;
  int rc = LSM_OK;
  u32 nSynced;

  /* Set nSynced to the number of pages that had been written when the 
  ** database was last checkpointed. */
  rc = lsmCheckpointSynced(db, 0, 0, &nSynced);

................................................................................
    u32 nPgsz = db->pShmhdr->aSnap1[CKPT_HDR_PGSZ];
    u32 nWrite = db->pShmhdr->aSnap1[CKPT_HDR_NWRITE];
    *pnKB = (int)(( ((i64)(nWrite - nSynced) * nPgsz) + 1023) / 1024);
  }

  return rc;
}








<







 







<
1216
1217
1218
1219
1220
1221
1222

1223
1224
1225
1226
1227
1228
1229
....
1231
1232
1233
1234
1235
1236
1237

}

/*
** Set the output variable to the number of KB of data written into the
** database file since the most recent checkpoint.
*/
int lsmCheckpointSize(lsm_db *db, int *pnKB){

  int rc = LSM_OK;
  u32 nSynced;

  /* Set nSynced to the number of pages that had been written when the 
  ** database was last checkpointed. */
  rc = lsmCheckpointSynced(db, 0, 0, &nSynced);

................................................................................
    u32 nPgsz = db->pShmhdr->aSnap1[CKPT_HDR_PGSZ];
    u32 nWrite = db->pShmhdr->aSnap1[CKPT_HDR_NWRITE];
    *pnKB = (int)(( ((i64)(nWrite - nSynced) * nPgsz) + 1023) / 1024);
  }

  return rc;
}

Changes to src/lsm_file.c.

2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
    const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
    int nSz = pFS->nPagesize;
    u8 *aBuf = 0;
    u8 *aData = 0;

    for(i=0; rc==LSM_OK && i<nPagePerBlock; i++){
      i64 iOff = iFromOff + i*nSz;
      Page *pPg;

      /* Set aData to point to a buffer containing the from page */
      if( (iOff+nSz)<=pFS->nMapLimit ){
        u8 *aMap = (u8 *)(pFS->pMap);
        aData = &aMap[iOff];
      }else{
        if( aBuf==0 ){







<







2381
2382
2383
2384
2385
2386
2387

2388
2389
2390
2391
2392
2393
2394
    const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
    int nSz = pFS->nPagesize;
    u8 *aBuf = 0;
    u8 *aData = 0;

    for(i=0; rc==LSM_OK && i<nPagePerBlock; i++){
      i64 iOff = iFromOff + i*nSz;


      /* Set aData to point to a buffer containing the from page */
      if( (iOff+nSz)<=pFS->nMapLimit ){
        u8 *aMap = (u8 *)(pFS->pMap);
        aData = &aMap[iOff];
      }else{
        if( aBuf==0 ){

Changes to src/lsm_sorted.c.

2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
....
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
....
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
....
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
....
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
    pCsr->nPtr = iPtr;
  }
}

static int multiCursorAddAll(MultiCursor *pCsr, Snapshot *pSnap){
  Level *pLvl;
  int nPtr = 0;
  int iPtr = 0;
  int rc = LSM_OK;

  for(pLvl=pSnap->pLevel; pLvl; pLvl=pLvl->pNext){
    /* If the LEVEL_INCOMPLETE flag is set, then this function is being
    ** called (indirectly) from within a sortedNewToplevel() call to
    ** construct pLvl. In this case ignore pLvl - this cursor is going to
    ** be used to retrieve a freelist entry from the LSM, and the partially
................................................................................
*/
static int mergeWorkerPushHierarchy(
  MergeWorker *pMW,               /* Merge worker object */
  int iTopic,                     /* Topic value for this key */
  void *pKey,                     /* Pointer to key buffer */
  int nKey                        /* Size of pKey buffer in bytes */
){
  lsm_db *pDb = pMW->pDb;         /* Database handle */
  int rc = LSM_OK;                /* Return Code */
  int iLevel;                     /* Level of b-tree hierachy to write to */
  int nData;                      /* Size of aData[] in bytes */
  u8 *aData;                      /* Page data for level iLevel */
  int iOff;                       /* Offset on b-tree page to write record to */
  int nRec;                       /* Initial number of records on b-tree page */
  Pgno iPtr;                      /* Pointer value to accompany pKey/nKey */

  assert( pMW->aSave[0].bStore==0 );
  assert( pMW->aSave[1].bStore==0 );
  rc = mergeWorkerBtreeIndirect(pMW);

  /* Obtain the absolute pointer value to store along with the key in the
................................................................................
static int mergeWorkerNextPage(
  MergeWorker *pMW,               /* Merge worker object to append page to */
  Pgno iFPtr                      /* Pointer value for footer of new page */
){
  int rc = LSM_OK;                /* Return code */
  Page *pNext = 0;                /* New page appended to run */
  lsm_db *pDb = pMW->pDb;         /* Database handle */
  Segment *pSeg;                  /* Run to append to */

  rc = lsmFsSortedAppend(pDb->pFS, pDb->pWorker, pMW->pLevel, 0, &pNext);
  assert( rc || pMW->pLevel->lhs.iFirst>0 || pMW->pDb->compress.xCompress );

  if( rc==LSM_OK ){
    u8 *aData;                    /* Data buffer belonging to page pNext */
    int nData;                    /* Size of aData[] in bytes */
................................................................................
/*
** Free all resources allocated by mergeWorkerInit().
*/
static void mergeWorkerShutdown(MergeWorker *pMW, int *pRc){
  int i;                          /* Iterator variable */
  int rc = *pRc;
  MultiCursor *pCsr = pMW->pCsr;
  Hierarchy *p = &pMW->hier;

  /* Unless the merge has finished, save the cursor position in the
  ** Merge.aInput[] array. See function mergeWorkerInit() for the 
  ** code to restore a cursor position based on aInput[].  */
  if( rc==LSM_OK && pCsr && lsmMCursorValid(pCsr) ){
    Merge *pMerge = pMW->pLevel->pMerge;
    int bBtree = (pCsr->pBtCsr!=0);
................................................................................

static int mergeWorkerStep(MergeWorker *pMW){
  lsm_db *pDb = pMW->pDb;       /* Database handle */
  MultiCursor *pCsr;            /* Cursor to read input data from */
  int rc = LSM_OK;              /* Return code */
  int eType;                    /* SORTED_SEPARATOR, WRITE or DELETE */
  void *pKey; int nKey;         /* Key */
  Segment *pSeg;                /* Output segment */
  Pgno iPtr;
  int iVal;

  pCsr = pMW->pCsr;
  pSeg = &pMW->pLevel->lhs;

  /* Pull the next record out of the source cursor. */
  lsmMCursorKey(pCsr, &pKey, &nKey);
  eType = pCsr->eType;

  if( eType & LSM_SYSTEMKEY ){
    int i;
    i = 1;
  }

  /* Figure out if the output record may have a different pointer value
  ** than the previous. This is the case if the current key is identical to
  ** a key that appears in the lowest level run being merged. If so, set 
  ** iPtr to the absolute pointer value. If not, leave iPtr set to zero, 
  ** indicating that the output pointer value should be a copy of the pointer 
  ** value written with the previous key.  */
  iPtr = (pCsr->pPrevMergePtr ? *pCsr->pPrevMergePtr : 0);







<







 







<

<
<
<
<
<







 







<







 







<







 







<




<





<
<
<
<
<







2371
2372
2373
2374
2375
2376
2377

2378
2379
2380
2381
2382
2383
2384
....
3683
3684
3685
3686
3687
3688
3689

3690





3691
3692
3693
3694
3695
3696
3697
....
3816
3817
3818
3819
3820
3821
3822

3823
3824
3825
3826
3827
3828
3829
....
4046
4047
4048
4049
4050
4051
4052

4053
4054
4055
4056
4057
4058
4059
....
4181
4182
4183
4184
4185
4186
4187

4188
4189
4190
4191

4192
4193
4194
4195
4196





4197
4198
4199
4200
4201
4202
4203
    pCsr->nPtr = iPtr;
  }
}

static int multiCursorAddAll(MultiCursor *pCsr, Snapshot *pSnap){
  Level *pLvl;
  int nPtr = 0;

  int rc = LSM_OK;

  for(pLvl=pSnap->pLevel; pLvl; pLvl=pLvl->pNext){
    /* If the LEVEL_INCOMPLETE flag is set, then this function is being
    ** called (indirectly) from within a sortedNewToplevel() call to
    ** construct pLvl. In this case ignore pLvl - this cursor is going to
    ** be used to retrieve a freelist entry from the LSM, and the partially
................................................................................
*/
static int mergeWorkerPushHierarchy(
  MergeWorker *pMW,               /* Merge worker object */
  int iTopic,                     /* Topic value for this key */
  void *pKey,                     /* Pointer to key buffer */
  int nKey                        /* Size of pKey buffer in bytes */
){

  int rc = LSM_OK;                /* Return Code */





  Pgno iPtr;                      /* Pointer value to accompany pKey/nKey */

  assert( pMW->aSave[0].bStore==0 );
  assert( pMW->aSave[1].bStore==0 );
  rc = mergeWorkerBtreeIndirect(pMW);

  /* Obtain the absolute pointer value to store along with the key in the
................................................................................
static int mergeWorkerNextPage(
  MergeWorker *pMW,               /* Merge worker object to append page to */
  Pgno iFPtr                      /* Pointer value for footer of new page */
){
  int rc = LSM_OK;                /* Return code */
  Page *pNext = 0;                /* New page appended to run */
  lsm_db *pDb = pMW->pDb;         /* Database handle */


  rc = lsmFsSortedAppend(pDb->pFS, pDb->pWorker, pMW->pLevel, 0, &pNext);
  assert( rc || pMW->pLevel->lhs.iFirst>0 || pMW->pDb->compress.xCompress );

  if( rc==LSM_OK ){
    u8 *aData;                    /* Data buffer belonging to page pNext */
    int nData;                    /* Size of aData[] in bytes */
................................................................................
/*
** Free all resources allocated by mergeWorkerInit().
*/
static void mergeWorkerShutdown(MergeWorker *pMW, int *pRc){
  int i;                          /* Iterator variable */
  int rc = *pRc;
  MultiCursor *pCsr = pMW->pCsr;


  /* Unless the merge has finished, save the cursor position in the
  ** Merge.aInput[] array. See function mergeWorkerInit() for the 
  ** code to restore a cursor position based on aInput[].  */
  if( rc==LSM_OK && pCsr && lsmMCursorValid(pCsr) ){
    Merge *pMerge = pMW->pLevel->pMerge;
    int bBtree = (pCsr->pBtCsr!=0);
................................................................................

static int mergeWorkerStep(MergeWorker *pMW){
  lsm_db *pDb = pMW->pDb;       /* Database handle */
  MultiCursor *pCsr;            /* Cursor to read input data from */
  int rc = LSM_OK;              /* Return code */
  int eType;                    /* SORTED_SEPARATOR, WRITE or DELETE */
  void *pKey; int nKey;         /* Key */

  Pgno iPtr;
  int iVal;

  pCsr = pMW->pCsr;


  /* Pull the next record out of the source cursor. */
  lsmMCursorKey(pCsr, &pKey, &nKey);
  eType = pCsr->eType;






  /* Figure out if the output record may have a different pointer value
  ** than the previous. This is the case if the current key is identical to
  ** a key that appears in the lowest level run being merged. If so, set 
  ** iPtr to the absolute pointer value. If not, leave iPtr set to zero, 
  ** indicating that the output pointer value should be a copy of the pointer 
  ** value written with the previous key.  */
  iPtr = (pCsr->pPrevMergePtr ? *pCsr->pPrevMergePtr : 0);

Changes to src/lsm_tree.c.

326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
...
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
....
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
....
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
....
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
....
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
....
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
static void assertIsWorkingChild(
  lsm_db *db, 
  TreeNode *pNode, 
  TreeNode *pParent, 
  int iCell
){
  TreeNode *p;
  int rc = LSM_OK;
  u32 iPtr = getChildPtr(pParent, WORKING_VERSION, iCell);
  p = treeShmptr(db, iPtr);
  assert( p==pNode );
}
#else
# define assertIsWorkingChild(w,x,y,z)
#endif
................................................................................
*/
static TreeKey *csrGetKey(TreeCursor *pCsr, TreeBlob *pBlob, int *pRc){
  TreeKey *pRet;
  lsm_db *pDb = pCsr->pDb;
  u32 iPtr = pCsr->apTreeNode[pCsr->iNode]->aiKeyPtr[pCsr->aiCell[pCsr->iNode]];

  assert( iPtr );
  pRet = treeShmptrUnsafe(pDb, iPtr);
  if( !(pRet->flags & LSM_CONTIGUOUS) ){
    pRet = treeShmkey(pDb, iPtr, TKV_LOADVAL, pBlob, pRc);
  }

  return pRet;
}

................................................................................
** If either of the conditions are untrue, LSM_CORRUPT is returned. Or, if
** an error is encountered before the checks are completed, another LSM error
** code (i.e. LSM_IOERR or LSM_NOMEM) may be returned.
*/
static int treeCheckLinkedList(lsm_db *db){
  int rc = LSM_OK;
  int nVisit = 0;
  u32 iShmid;
  ShmChunk *p;

  p = treeShmChunkRc(db, db->treehdr.iFirst, &rc);
  iShmid = p->iShmid;
  while( rc==LSM_OK && p ){
    if( p->iNext ){
      if( p->iNext>=db->treehdr.nChunk ){
        rc = LSM_CORRUPT_BKPT;
      }else{
        ShmChunk *pNext = treeShmChunkRc(db, p->iNext, &rc);
        if( rc==LSM_OK ){
................................................................................
      pCsr->iNode--;
      treeUpdatePtr(db, pCsr, iNew);
    }
  }
}

static int treeNextIsEndDelete(lsm_db *db, TreeCursor *pCsr){
  TreeNode *pNode;
  int iNode = pCsr->iNode;
  int iCell = pCsr->aiCell[iNode]+1;

  /* Cursor currently points to a leaf node. */
  assert( pCsr->iNode==(db->treehdr.root.nHeight-1) );

  while( iNode>=0 ){
................................................................................
    iCell = pCsr->aiCell[iNode];
  }

  return 0;
}

static int treePrevIsStartDelete(lsm_db *db, TreeCursor *pCsr){
  TreeNode *pNode;
  int iNode = pCsr->iNode;

  /* Cursor currently points to a leaf node. */
  assert( pCsr->iNode==(db->treehdr.root.nHeight-1) );

  while( iNode>=0 ){
    TreeNode *pNode = pCsr->apTreeNode[iNode];
................................................................................
      pNode = (TreeNode *)treeShmptrUnsafe(pDb, iNodePtr);
      iNode++;
      pCsr->apTreeNode[iNode] = pNode;

      /* Compare (pKey/nKey) with the key in the middle slot of B-tree node
      ** pNode. The middle slot is never empty. If the comparison is a match,
      ** then the search is finished. Break out of the loop. */
      pTreeKey = treeShmptrUnsafe(pDb, pNode->aiKeyPtr[1]);
      if( !(pTreeKey->flags & LSM_CONTIGUOUS) ){
        pTreeKey = treeShmkey(pDb, pNode->aiKeyPtr[1], TKV_LOADKEY, &b, &rc);
        if( rc!=LSM_OK ) break;
      }
      res = treeKeycmp((void *)&pTreeKey[1], pTreeKey->nKey, pKey, nKey);
      if( res==0 ){
        pCsr->aiCell[iNode] = 1;
................................................................................

      /* Based on the results of the previous comparison, compare (pKey/nKey)
      ** to either the left or right key of the B-tree node, if such a key
      ** exists. */
      iTest = (res>0 ? 0 : 2);
      iTreeKey = pNode->aiKeyPtr[iTest];
      if( iTreeKey ){
        pTreeKey = treeShmptrUnsafe(pDb, iTreeKey);
        if( !(pTreeKey->flags & LSM_CONTIGUOUS) ){
          pTreeKey = treeShmkey(pDb, iTreeKey, TKV_LOADKEY, &b, &rc);
          if( rc ) break;
        }
        res = treeKeycmp((void *)&pTreeKey[1], pTreeKey->nKey, pKey, nKey);
        if( res==0 ){
          pCsr->aiCell[iNode] = iTest;







<







 







|







 







<



<







 







<







 







<







 







|







 







|







326
327
328
329
330
331
332

333
334
335
336
337
338
339
...
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
....
1184
1185
1186
1187
1188
1189
1190

1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
....
1391
1392
1393
1394
1395
1396
1397

1398
1399
1400
1401
1402
1403
1404
....
1413
1414
1415
1416
1417
1418
1419

1420
1421
1422
1423
1424
1425
1426
....
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
....
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
static void assertIsWorkingChild(
  lsm_db *db, 
  TreeNode *pNode, 
  TreeNode *pParent, 
  int iCell
){
  TreeNode *p;

  u32 iPtr = getChildPtr(pParent, WORKING_VERSION, iCell);
  p = treeShmptr(db, iPtr);
  assert( p==pNode );
}
#else
# define assertIsWorkingChild(w,x,y,z)
#endif
................................................................................
*/
static TreeKey *csrGetKey(TreeCursor *pCsr, TreeBlob *pBlob, int *pRc){
  TreeKey *pRet;
  lsm_db *pDb = pCsr->pDb;
  u32 iPtr = pCsr->apTreeNode[pCsr->iNode]->aiKeyPtr[pCsr->aiCell[pCsr->iNode]];

  assert( iPtr );
  pRet = (TreeKey*)treeShmptrUnsafe(pDb, iPtr);
  if( !(pRet->flags & LSM_CONTIGUOUS) ){
    pRet = treeShmkey(pDb, iPtr, TKV_LOADVAL, pBlob, pRc);
  }

  return pRet;
}

................................................................................
** If either of the conditions are untrue, LSM_CORRUPT is returned. Or, if
** an error is encountered before the checks are completed, another LSM error
** code (i.e. LSM_IOERR or LSM_NOMEM) may be returned.
*/
static int treeCheckLinkedList(lsm_db *db){
  int rc = LSM_OK;
  int nVisit = 0;

  ShmChunk *p;

  p = treeShmChunkRc(db, db->treehdr.iFirst, &rc);

  while( rc==LSM_OK && p ){
    if( p->iNext ){
      if( p->iNext>=db->treehdr.nChunk ){
        rc = LSM_CORRUPT_BKPT;
      }else{
        ShmChunk *pNext = treeShmChunkRc(db, p->iNext, &rc);
        if( rc==LSM_OK ){
................................................................................
      pCsr->iNode--;
      treeUpdatePtr(db, pCsr, iNew);
    }
  }
}

static int treeNextIsEndDelete(lsm_db *db, TreeCursor *pCsr){

  int iNode = pCsr->iNode;
  int iCell = pCsr->aiCell[iNode]+1;

  /* Cursor currently points to a leaf node. */
  assert( pCsr->iNode==(db->treehdr.root.nHeight-1) );

  while( iNode>=0 ){
................................................................................
    iCell = pCsr->aiCell[iNode];
  }

  return 0;
}

static int treePrevIsStartDelete(lsm_db *db, TreeCursor *pCsr){

  int iNode = pCsr->iNode;

  /* Cursor currently points to a leaf node. */
  assert( pCsr->iNode==(db->treehdr.root.nHeight-1) );

  while( iNode>=0 ){
    TreeNode *pNode = pCsr->apTreeNode[iNode];
................................................................................
      pNode = (TreeNode *)treeShmptrUnsafe(pDb, iNodePtr);
      iNode++;
      pCsr->apTreeNode[iNode] = pNode;

      /* Compare (pKey/nKey) with the key in the middle slot of B-tree node
      ** pNode. The middle slot is never empty. If the comparison is a match,
      ** then the search is finished. Break out of the loop. */
      pTreeKey = (TreeKey*)treeShmptrUnsafe(pDb, pNode->aiKeyPtr[1]);
      if( !(pTreeKey->flags & LSM_CONTIGUOUS) ){
        pTreeKey = treeShmkey(pDb, pNode->aiKeyPtr[1], TKV_LOADKEY, &b, &rc);
        if( rc!=LSM_OK ) break;
      }
      res = treeKeycmp((void *)&pTreeKey[1], pTreeKey->nKey, pKey, nKey);
      if( res==0 ){
        pCsr->aiCell[iNode] = 1;
................................................................................

      /* Based on the results of the previous comparison, compare (pKey/nKey)
      ** to either the left or right key of the B-tree node, if such a key
      ** exists. */
      iTest = (res>0 ? 0 : 2);
      iTreeKey = pNode->aiKeyPtr[iTest];
      if( iTreeKey ){
        pTreeKey = (TreeKey*)treeShmptrUnsafe(pDb, iTreeKey);
        if( !(pTreeKey->flags & LSM_CONTIGUOUS) ){
          pTreeKey = treeShmkey(pDb, iTreeKey, TKV_LOADKEY, &b, &rc);
          if( rc ) break;
        }
        res = treeKeycmp((void *)&pTreeKey[1], pTreeKey->nKey, pKey, nKey);
        if( res==0 ){
          pCsr->aiCell[iNode] = iTest;

Changes to src/main.c.

693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
*/
void sqlite4_profile(
  sqlite4 *db,
  void *pArg,
  void (*xProfile)(void*,const char*,sqlite4_uint64),
  void (*xDestroy)(void*)
){
  void *pOld;
  sqlite4_mutex_enter(db->mutex);
  if( db->xProfileDestroy ){
    db->xProfileDestroy(db->pProfileArg);
  }
  db->xProfile = xProfile;
  db->xProfileDestroy = xDestroy;
  db->pProfileArg = pArg;
  sqlite4_mutex_leave(db->mutex);
}
#endif /* SQLITE4_OMIT_TRACE */

/*
** This function returns true if main-memory should be used instead of
** a temporary file for transient pager files and statement journals.
** The value returned depends on the value of db->temp_store (runtime
** parameter) and the compile time value of SQLITE4_TEMP_STORE. The
** following table describes the relationship between these two values
** and this functions return value.
**
**   SQLITE4_TEMP_STORE     db->temp_store     Location of temporary database
**   -----------------     --------------     ------------------------------
**   0                     any                file      (return 0)
**   1                     1                  file      (return 0)
**   1                     2                  memory    (return 1)
**   1                     0                  file      (return 0)
**   2                     1                  file      (return 0)
**   2                     2                  memory    (return 1)
**   2                     0                  memory    (return 1)
**   3                     any                memory    (return 1)
*/
int sqlite4TempInMemory(const sqlite4 *db){
#if SQLITE4_TEMP_STORE==1
  return ( db->temp_store==2 );
#endif
#if SQLITE4_TEMP_STORE==2
  return ( db->temp_store!=1 );
#endif
#if SQLITE4_TEMP_STORE==3
  return 1;
#endif
#if SQLITE4_TEMP_STORE<1 || SQLITE4_TEMP_STORE>3
  return 0;
#endif
}

/*
** Return UTF-8 encoded English language explanation of the most recent
** error.
*/
const char *sqlite4_errmsg(sqlite4 *db){
  const char *z;
  if( !db ){







<











<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







693
694
695
696
697
698
699

700
701
702
703
704
705
706
707
708
709
710


































711
712
713
714
715
716
717
*/
void sqlite4_profile(
  sqlite4 *db,
  void *pArg,
  void (*xProfile)(void*,const char*,sqlite4_uint64),
  void (*xDestroy)(void*)
){

  sqlite4_mutex_enter(db->mutex);
  if( db->xProfileDestroy ){
    db->xProfileDestroy(db->pProfileArg);
  }
  db->xProfile = xProfile;
  db->xProfileDestroy = xDestroy;
  db->pProfileArg = pArg;
  sqlite4_mutex_leave(db->mutex);
}
#endif /* SQLITE4_OMIT_TRACE */



































/*
** Return UTF-8 encoded English language explanation of the most recent
** error.
*/
const char *sqlite4_errmsg(sqlite4 *db){
  const char *z;
  if( !db ){

Changes to src/mutex_noop.c.

104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
static int debugMutexEnd(void *p){ UNUSED_PARAMETER(p); return SQLITE4_OK; }

/*
** The sqlite4_mutex_alloc() routine allocates a new
** mutex and returns a pointer to it.  If it returns NULL
** that means that a mutex could not be allocated. 
*/
static sqlite4_mutex *debugMutexAlloc(sqlite4_env *pEnv, int id){

  sqlite4DebugMutex *pNew = 0;
  pNew = sqlite4Malloc(pEnv, sizeof(*pNew));
  if( pNew ){
    pNew->id = id;
    pNew->cnt = 0;
    pNew->pEnv = pEnv;
  }







|
>







104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
static int debugMutexEnd(void *p){ UNUSED_PARAMETER(p); return SQLITE4_OK; }

/*
** The sqlite4_mutex_alloc() routine allocates a new
** mutex and returns a pointer to it.  If it returns NULL
** that means that a mutex could not be allocated. 
*/
static sqlite4_mutex *debugMutexAlloc(void *pX, int id){
  sqlite4_env *pEnv = (sqlite4_env*)pX;
  sqlite4DebugMutex *pNew = 0;
  pNew = sqlite4Malloc(pEnv, sizeof(*pNew));
  if( pNew ){
    pNew->id = id;
    pNew->cnt = 0;
    pNew->pEnv = pEnv;
  }

Changes to src/sqliteInt.h.

298
299
300
301
302
303
304

305
306
307
308
309
310
311
...
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
....
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
....
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
....
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
....
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
....
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
....
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
....
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
#include "hash.h"
#include "parse.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stddef.h>


/*
** If compiling for a processor that lacks floating point support,
** substitute integer for floating-point
*/
#ifdef SQLITE4_OMIT_FLOATING_POINT
# define double sqlite4_int64
................................................................................
typedef struct SrcListItem SrcListItem;
typedef struct StrAccum StrAccum;
typedef struct Table Table;
typedef struct Token Token;
typedef struct Trigger Trigger;
typedef struct TriggerPrg TriggerPrg;
typedef struct TriggerStep TriggerStep;
typedef struct UnpackedRecord UnpackedRecord;
typedef struct VTable VTable;
typedef struct VtabCtx VtabCtx;
typedef struct Walker Walker;
typedef struct WherePlan WherePlan;
typedef struct WhereInfo WhereInfo;
typedef struct WhereLevel WhereLevel;

................................................................................
  u16 nField;         /* Total number of entries in aColl[] */
  u16 nPK;            /* Number of primary key entries at the end of aColl[] */
  u16 nData;          /* Number of columns of data in KV entry value */
  u8 *aSortOrder;     /* Sort order for each column.  May be NULL */
  CollSeq *aColl[1];  /* Collating sequence for each term of the key */
};

/*
** An instance of the following structure holds information about a
** single index record that has already been parsed out into individual
** values.
**
** A record is an object that contains one or more fields of data.
** Records are used to store the content of a table row and to store
** the key of an index.  A blob encoding of a record is created by
** the OP_MakeRecord opcode of the VDBE and is disassembled by the
** OP_Column opcode.
**
** This structure holds a record that has already been disassembled
** into its constituent fields.
*/
struct UnpackedRecord {
  KeyInfo *pKeyInfo;  /* Collation and sort-order information */
  u16 nField;         /* Number of entries in apMem[] */
  u8 flags;           /* Boolean settings.  UNPACKED_... below */
  i64 rowid;          /* Used by UNPACKED_PREFIX_SEARCH */
  Mem *aMem;          /* Values */
};

/*
** Allowed values of UnpackedRecord.flags
*/
#define UNPACKED_INCRKEY       0x01  /* Make this key an epsilon larger */
#define UNPACKED_PREFIX_MATCH  0x02  /* A prefix match is considered OK */
#define UNPACKED_PREFIX_SEARCH 0x04  /* Ignore final (rowid) field */

/*
** Each SQL index is represented in memory by an
** instance of the following structure.
**
** The columns of the table that are to be indexed are described
** by the aiColumn[] field of this structure.  For example, suppose
** we have the following table and index:
................................................................................
** SQLITE4_ENABLE_FTS3 macro.  But to avoid confusion we also all
** the SQLITE4_ENABLE_FTS4 macro to serve as an alisse for SQLITE4_ENABLE_FTS3.
*/
#if defined(SQLITE4_ENABLE_FTS4) && !defined(SQLITE4_ENABLE_FTS3)
# define SQLITE4_ENABLE_FTS3
#endif

/*
** The ctype.h header is needed for non-ASCII systems.  It is also
** needed by FTS3 when FTS3 is included in the amalgamation.
*/
#if !defined(SQLITE4_ASCII) || \
    (defined(SQLITE4_ENABLE_FTS3) && defined(SQLITE4_AMALGAMATION))
# include <ctype.h>
#endif

/*
** The following macros mimic the standard library functions toupper(),
** isspace(), isalnum(), isdigit() and isxdigit(), respectively. The
** sqlite versions only work for ASCII characters, regardless of locale.
*/
#ifdef SQLITE4_ASCII
................................................................................
int sqlite4RunVacuum(char**, sqlite4*);
char *sqlite4NameFromToken(sqlite4*, Token*);
int sqlite4ExprCompare(Expr*, Expr*);
int sqlite4ExprListCompare(ExprList*, ExprList*);
void sqlite4ExprAnalyzeAggregates(NameContext*, Expr*);
void sqlite4ExprAnalyzeAggList(NameContext*,ExprList*);
Vdbe *sqlite4GetVdbe(Parse*);
void sqlite4PrngSaveState(void);
void sqlite4PrngRestoreState(void);
void sqlite4PrngResetState(void);
void sqlite4CodeVerifySchema(Parse*, int);
void sqlite4CodeVerifyNamedSchema(Parse*, const char *zDb);
void sqlite4BeginTransaction(Parse*, int);
void sqlite4EndTransaction(Parse *, int);
void sqlite4Savepoint(Parse*, int, Token*);
void sqlite4CloseSavepoints(sqlite4 *);
int sqlite4ExprIsConstant(Expr*);
................................................................................
void sqlite4Detach(Parse*, Expr*);
int sqlite4FixInit(DbFixer*, Parse*, int, const char*, const Token*);
int sqlite4FixSrcList(DbFixer*, SrcList*);
int sqlite4FixSelect(DbFixer*, Select*);
int sqlite4FixExpr(DbFixer*, Expr*);
int sqlite4FixExprList(DbFixer*, ExprList*);
int sqlite4FixTriggerStep(DbFixer*, TriggerStep*);
int sqlite4AtoF(const char *z, double*, int, u8);
int sqlite4GetInt32(const char *, int*);
int sqlite4Atoi(const char*);
int sqlite4Utf16ByteLen(const void *pData, int nChar);
int sqlite4Utf8CharLen(const char *pData, int nByte);
u32 sqlite4Utf8Read(const char*, const char**);

/*
................................................................................
extern const unsigned char sqlite4OpcodeProperty[];
extern const unsigned char sqlite4UpperToLower[];
extern const unsigned char sqlite4CtypeMap[];
extern const Token sqlite4IntTokens[];
extern struct sqlite4_env sqlite4DefaultEnv;
extern struct KVFactory sqlite4BuiltinFactory;
#endif
void sqlite4RootPageMoved(sqlite4*, int, int, int);
void sqlite4Reindex(Parse*, Token*, Token*);
void sqlite4AlterFunctions(sqlite4_env*);
void sqlite4AlterRenameTable(Parse*, SrcList*, Token*);
int sqlite4GetToken(const unsigned char *, int *);
void sqlite4NestedParse(Parse*, const char*, ...);
void sqlite4ExpirePreparedStatements(sqlite4*);
int sqlite4CodeSubselect(Parse *, Expr *, int, int);
................................................................................
void *sqlite4ParserAlloc(void*(*)(void*,size_t), void*);
void sqlite4ParserFree(void*, void(*)(void*,void*));
void sqlite4Parser(void*, int, Token, Parse*);
#ifdef YYTRACKMAXSTACKDEPTH
  int sqlite4ParserStackPeak(void*);
#endif

void sqlite4AutoLoadExtensions(sqlite4*);
#ifndef SQLITE4_OMIT_LOAD_EXTENSION
  void sqlite4CloseExtensions(sqlite4*);
#else
# define sqlite4CloseExtensions(X)
#endif

#ifdef SQLITE4_TEST
  int sqlite4Utf8To8(char*);
#endif

#ifdef SQLITE4_OMIT_VIRTUALTABLE
#  define sqlite4VtabClear(Y)
#  define sqlite4VtabSync(X,Y) SQLITE4_OK
................................................................................
FuncDef *sqlite4VtabOverloadFunction(sqlite4 *,FuncDef*, int nArg, Expr*);
void sqlite4InvalidFunction(sqlite4_context*,int,sqlite4_value**);
int sqlite4VdbeParameterIndex(Vdbe*, const char*, int);
int sqlite4TransferBindings(sqlite4_stmt *, sqlite4_stmt *);
int sqlite4Reprepare(Vdbe*);
void sqlite4ExprListCheckLength(Parse*, ExprList*, const char*);
CollSeq *sqlite4BinaryCompareCollSeq(Parse *, Expr *, Expr *);
int sqlite4TempInMemory(const sqlite4*);
const char *sqlite4JournalModename(int);
int sqlite4Checkpoint(sqlite4*, int, int, int*, int*);
int sqlite4WalDefaultHook(void*,sqlite4*,const char*,int);

/* Declarations for functions in fkey.c. All of these are replaced by
** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign
** key functionality is available. If OMIT_TRIGGER is defined but
** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In
** this case foreign keys are parsed, but no other functionality is 
** provided (enforcement of FK constraints requires the triggers sub-system).







>







 







<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<







 







<
<
<







 







<







 







<







 







<
<
<
<
<
<
<







 







<
<
<
<







298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
...
608
609
610
611
612
613
614

615
616
617
618
619
620
621
....
1325
1326
1327
1328
1329
1330
1331





























1332
1333
1334
1335
1336
1337
1338
....
2511
2512
2513
2514
2515
2516
2517








2518
2519
2520
2521
2522
2523
2524
....
2775
2776
2777
2778
2779
2780
2781



2782
2783
2784
2785
2786
2787
2788
....
2878
2879
2880
2881
2882
2883
2884

2885
2886
2887
2888
2889
2890
2891
....
2976
2977
2978
2979
2980
2981
2982

2983
2984
2985
2986
2987
2988
2989
....
3036
3037
3038
3039
3040
3041
3042







3043
3044
3045
3046
3047
3048
3049
....
3079
3080
3081
3082
3083
3084
3085




3086
3087
3088
3089
3090
3091
3092
#include "hash.h"
#include "parse.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stddef.h>
#include <ctype.h>    /* FIXME - can we omit this one? */

/*
** If compiling for a processor that lacks floating point support,
** substitute integer for floating-point
*/
#ifdef SQLITE4_OMIT_FLOATING_POINT
# define double sqlite4_int64
................................................................................
typedef struct SrcListItem SrcListItem;
typedef struct StrAccum StrAccum;
typedef struct Table Table;
typedef struct Token Token;
typedef struct Trigger Trigger;
typedef struct TriggerPrg TriggerPrg;
typedef struct TriggerStep TriggerStep;

typedef struct VTable VTable;
typedef struct VtabCtx VtabCtx;
typedef struct Walker Walker;
typedef struct WherePlan WherePlan;
typedef struct WhereInfo WhereInfo;
typedef struct WhereLevel WhereLevel;

................................................................................
  u16 nField;         /* Total number of entries in aColl[] */
  u16 nPK;            /* Number of primary key entries at the end of aColl[] */
  u16 nData;          /* Number of columns of data in KV entry value */
  u8 *aSortOrder;     /* Sort order for each column.  May be NULL */
  CollSeq *aColl[1];  /* Collating sequence for each term of the key */
};






























/*
** Each SQL index is represented in memory by an
** instance of the following structure.
**
** The columns of the table that are to be indexed are described
** by the aiColumn[] field of this structure.  For example, suppose
** we have the following table and index:
................................................................................
** SQLITE4_ENABLE_FTS3 macro.  But to avoid confusion we also all
** the SQLITE4_ENABLE_FTS4 macro to serve as an alisse for SQLITE4_ENABLE_FTS3.
*/
#if defined(SQLITE4_ENABLE_FTS4) && !defined(SQLITE4_ENABLE_FTS3)
# define SQLITE4_ENABLE_FTS3
#endif










/*
** The following macros mimic the standard library functions toupper(),
** isspace(), isalnum(), isdigit() and isxdigit(), respectively. The
** sqlite versions only work for ASCII characters, regardless of locale.
*/
#ifdef SQLITE4_ASCII
................................................................................
int sqlite4RunVacuum(char**, sqlite4*);
char *sqlite4NameFromToken(sqlite4*, Token*);
int sqlite4ExprCompare(Expr*, Expr*);
int sqlite4ExprListCompare(ExprList*, ExprList*);
void sqlite4ExprAnalyzeAggregates(NameContext*, Expr*);
void sqlite4ExprAnalyzeAggList(NameContext*,ExprList*);
Vdbe *sqlite4GetVdbe(Parse*);



void sqlite4CodeVerifySchema(Parse*, int);
void sqlite4CodeVerifyNamedSchema(Parse*, const char *zDb);
void sqlite4BeginTransaction(Parse*, int);
void sqlite4EndTransaction(Parse *, int);
void sqlite4Savepoint(Parse*, int, Token*);
void sqlite4CloseSavepoints(sqlite4 *);
int sqlite4ExprIsConstant(Expr*);
................................................................................
void sqlite4Detach(Parse*, Expr*);
int sqlite4FixInit(DbFixer*, Parse*, int, const char*, const Token*);
int sqlite4FixSrcList(DbFixer*, SrcList*);
int sqlite4FixSelect(DbFixer*, Select*);
int sqlite4FixExpr(DbFixer*, Expr*);
int sqlite4FixExprList(DbFixer*, ExprList*);
int sqlite4FixTriggerStep(DbFixer*, TriggerStep*);

int sqlite4GetInt32(const char *, int*);
int sqlite4Atoi(const char*);
int sqlite4Utf16ByteLen(const void *pData, int nChar);
int sqlite4Utf8CharLen(const char *pData, int nByte);
u32 sqlite4Utf8Read(const char*, const char**);

/*
................................................................................
extern const unsigned char sqlite4OpcodeProperty[];
extern const unsigned char sqlite4UpperToLower[];
extern const unsigned char sqlite4CtypeMap[];
extern const Token sqlite4IntTokens[];
extern struct sqlite4_env sqlite4DefaultEnv;
extern struct KVFactory sqlite4BuiltinFactory;
#endif

void sqlite4Reindex(Parse*, Token*, Token*);
void sqlite4AlterFunctions(sqlite4_env*);
void sqlite4AlterRenameTable(Parse*, SrcList*, Token*);
int sqlite4GetToken(const unsigned char *, int *);
void sqlite4NestedParse(Parse*, const char*, ...);
void sqlite4ExpirePreparedStatements(sqlite4*);
int sqlite4CodeSubselect(Parse *, Expr *, int, int);
................................................................................
void *sqlite4ParserAlloc(void*(*)(void*,size_t), void*);
void sqlite4ParserFree(void*, void(*)(void*,void*));
void sqlite4Parser(void*, int, Token, Parse*);
#ifdef YYTRACKMAXSTACKDEPTH
  int sqlite4ParserStackPeak(void*);
#endif








#ifdef SQLITE4_TEST
  int sqlite4Utf8To8(char*);
#endif

#ifdef SQLITE4_OMIT_VIRTUALTABLE
#  define sqlite4VtabClear(Y)
#  define sqlite4VtabSync(X,Y) SQLITE4_OK
................................................................................
FuncDef *sqlite4VtabOverloadFunction(sqlite4 *,FuncDef*, int nArg, Expr*);
void sqlite4InvalidFunction(sqlite4_context*,int,sqlite4_value**);
int sqlite4VdbeParameterIndex(Vdbe*, const char*, int);
int sqlite4TransferBindings(sqlite4_stmt *, sqlite4_stmt *);
int sqlite4Reprepare(Vdbe*);
void sqlite4ExprListCheckLength(Parse*, ExprList*, const char*);
CollSeq *sqlite4BinaryCompareCollSeq(Parse *, Expr *, Expr *);





/* Declarations for functions in fkey.c. All of these are replaced by
** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign
** key functionality is available. If OMIT_TRIGGER is defined but
** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In
** this case foreign keys are parsed, but no other functionality is 
** provided (enforcement of FK constraints requires the triggers sub-system).

Changes to src/vdbe.h.

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
sqlite4_value *sqlite4VdbeGetValue(Vdbe*, int, u8);
void sqlite4VdbeSetVarmask(Vdbe*, int);
#ifndef SQLITE4_OMIT_TRACE
  char *sqlite4VdbeExpandSql(Vdbe*, const char*);
#endif
sqlite4_value *sqlite4ColumnValue(sqlite4_stmt *pStmt, int iCol);

void sqlite4VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
UnpackedRecord *sqlite4VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);

#ifndef SQLITE4_OMIT_TRIGGER
void sqlite4VdbeLinkSubProgram(Vdbe *, SubProgram *);
#endif


#ifndef NDEBUG
  void sqlite4VdbeComment(Vdbe*, const char*, ...);







<
<
<







213
214
215
216
217
218
219



220
221
222
223
224
225
226
sqlite4_value *sqlite4VdbeGetValue(Vdbe*, int, u8);
void sqlite4VdbeSetVarmask(Vdbe*, int);
#ifndef SQLITE4_OMIT_TRACE
  char *sqlite4VdbeExpandSql(Vdbe*, const char*);
#endif
sqlite4_value *sqlite4ColumnValue(sqlite4_stmt *pStmt, int iCol);




#ifndef SQLITE4_OMIT_TRIGGER
void sqlite4VdbeLinkSubProgram(Vdbe *, SubProgram *);
#endif


#ifndef NDEBUG
  void sqlite4VdbeComment(Vdbe*, const char*, ...);

Changes to src/vdbeInt.h.

340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
** Function prototypes
*/
void sqlite4VdbeFreeCursor(Vdbe *, VdbeCursor*);
void sqliteVdbePopStack(Vdbe*,int);
#if defined(SQLITE4_DEBUG) || defined(VDBE_PROFILE)
void sqlite4VdbePrintOp(FILE*, int, Op*);
#endif
u32 sqlite4VdbeSerialTypeLen(u32);
u32 sqlite4VdbeSerialType(Mem*, int);
u32 sqlite4VdbeSerialPut(unsigned char*, int, Mem*, int);
u32 sqlite4VdbeSerialGet(const unsigned char*, u32, Mem*);
void sqlite4VdbeDeleteAuxData(VdbeFunc*, int);

int sqlite4VdbeCreateDecoder(
  sqlite4 *db,                /* The database connection */
  const unsigned char *aIn,   /* The input data blob */
  int nIn,                    /* Number of bytes in aIn[] */
  int mxCol,                  /* Maximum number of columns in aIn[] */







<
<
<
<







340
341
342
343
344
345
346




347
348
349
350
351
352
353
** Function prototypes
*/
void sqlite4VdbeFreeCursor(Vdbe *, VdbeCursor*);
void sqliteVdbePopStack(Vdbe*,int);
#if defined(SQLITE4_DEBUG) || defined(VDBE_PROFILE)
void sqlite4VdbePrintOp(FILE*, int, Op*);
#endif




void sqlite4VdbeDeleteAuxData(VdbeFunc*, int);

int sqlite4VdbeCreateDecoder(
  sqlite4 *db,                /* The database connection */
  const unsigned char *aIn,   /* The input data blob */
  int nIn,                    /* Number of bytes in aIn[] */
  int mxCol,                  /* Maximum number of columns in aIn[] */

Changes to src/vdbeaux.c.

2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
  return u.r;
}
# define swapMixedEndianFloat(X)  X = floatSwap(X)
#else
# define swapMixedEndianFloat(X)
#endif


/*
** This routine is used to allocate sufficient space for an UnpackedRecord
** structure large enough to be used with sqlite4VdbeRecordUnpack() if
** the first argument is a pointer to KeyInfo structure pKeyInfo.
**
** The space is either allocated using sqlite4DbMallocRaw() or from within
** the unaligned buffer passed via the second and third arguments (presumably
** stack space). If the former, then *ppFree is set to a pointer that should
** be eventually freed by the caller using sqlite4DbFree(). Or, if the 
** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL
** before returning.
**
** If an OOM error occurs, NULL is returned.
*/
UnpackedRecord *sqlite4VdbeAllocUnpackedRecord(
  KeyInfo *pKeyInfo,              /* Description of the record */
  char *pSpace,                   /* Unaligned space available */
  int szSpace,                    /* Size of pSpace[] in bytes */
  char **ppFree                   /* OUT: Caller should free this pointer */
){
  UnpackedRecord *p;              /* Unpacked record to return */
  int nOff;                       /* Increment pSpace by nOff to align it */
  int nByte;                      /* Number of bytes required for *p */

  /* We want to shift the pointer pSpace up such that it is 8-byte aligned.
  ** Thus, we need to calculate a value, nOff, between 0 and 7, to shift 
  ** it by.  If pSpace is already 8-byte aligned, nOff should be zero.
  */
  nOff = (8 - (SQLITE4_PTR_TO_INT(pSpace) & 7)) & 7;
  nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1);
  if( nByte>szSpace+nOff ){
    p = (UnpackedRecord *)sqlite4DbMallocRaw(pKeyInfo->db, nByte);
    *ppFree = (char *)p;
    if( !p ) return 0;
  }else{
    p = (UnpackedRecord*)&pSpace[nOff];
    *ppFree = 0;
  }

  p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
  p->pKeyInfo = pKeyInfo;
  p->nField = pKeyInfo->nField + 1;
  return p;
}


/*
** This routine sets the value to be returned by subsequent calls to
** sqlite4_changes() on the database handle 'db'. 
*/
void sqlite4VdbeSetChanges(sqlite4 *db, int nChange){
  assert( sqlite4_mutex_held(db->mutex) );







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







2190
2191
2192
2193
2194
2195
2196














































2197
2198
2199
2200
2201
2202
2203
  return u.r;
}
# define swapMixedEndianFloat(X)  X = floatSwap(X)
#else
# define swapMixedEndianFloat(X)
#endif
















































/*
** This routine sets the value to be returned by subsequent calls to
** sqlite4_changes() on the database handle 'db'. 
*/
void sqlite4VdbeSetChanges(sqlite4 *db, int nChange){
  assert( sqlite4_mutex_held(db->mutex) );

Changes to src/where.c.

3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
....
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
        }
        /* Loop through table entries that match term pOrTerm. */
        pSubWInfo = sqlite4WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
                        WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
                        WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY, iCovCur);
        assert( pSubWInfo || pParse->nErr || pParse->db->mallocFailed );
        if( pSubWInfo ){
          WhereLoop *pSubLoop;
          explainOneScan(
              pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
          );
          if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
            int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
            sqlite4VdbeAddOp2(v, OP_RowKey, iCur, regKey);
            sqlite4VdbeAddOp4Int(v, OP_RowSetTest, regKeyset,
................................................................................
static int whereLoopAddBtree(
  WhereLoopBuilder *pBuilder, /* WHERE clause information */
  Bitmask mExtra              /* Extra prerequesites for using this table */
){
  WhereInfo *pWInfo;          /* WHERE analysis context */
  Index *pProbe;              /* An index we are evaluating */
  Index *pPk;                 /* Primary key index for table pSrc */
  tRowcnt aiRowEstPk[2];      /* The aiRowEst[] value for the sPk index */
  int aiColumnPk = -1;        /* The aColumn[] value for the sPk index */
  SrcList *pTabList;          /* The FROM clause */
  struct SrcListItem *pSrc;   /* The FROM clause btree term to add */
  WhereLoop *pNew;            /* Template WhereLoop object */
  int rc = SQLITE4_OK;        /* Return code */
  int iSortIdx = 1;           /* Index number */
  int b;                      /* A boolean value */
  WhereCost rSize;            /* number of rows in the table */







<







 







<
<







3876
3877
3878
3879
3880
3881
3882

3883
3884
3885
3886
3887
3888
3889
....
4567
4568
4569
4570
4571
4572
4573


4574
4575
4576
4577
4578
4579
4580
        }
        /* Loop through table entries that match term pOrTerm. */
        pSubWInfo = sqlite4WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
                        WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
                        WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY, iCovCur);
        assert( pSubWInfo || pParse->nErr || pParse->db->mallocFailed );
        if( pSubWInfo ){

          explainOneScan(
              pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
          );
          if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
            int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
            sqlite4VdbeAddOp2(v, OP_RowKey, iCur, regKey);
            sqlite4VdbeAddOp4Int(v, OP_RowSetTest, regKeyset,
................................................................................
static int whereLoopAddBtree(
  WhereLoopBuilder *pBuilder, /* WHERE clause information */
  Bitmask mExtra              /* Extra prerequesites for using this table */
){
  WhereInfo *pWInfo;          /* WHERE analysis context */
  Index *pProbe;              /* An index we are evaluating */
  Index *pPk;                 /* Primary key index for table pSrc */


  SrcList *pTabList;          /* The FROM clause */
  struct SrcListItem *pSrc;   /* The FROM clause btree term to add */
  WhereLoop *pNew;            /* Template WhereLoop object */
  int rc = SQLITE4_OK;        /* Return code */
  int iSortIdx = 1;           /* Index number */
  int b;                      /* A boolean value */
  WhereCost rSize;            /* number of rows in the table */