SQLite4
Check-in [2d7bf1c174]
Not logged in

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

Overview
Comment:Get the amalgmation build working.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 2d7bf1c174d407d56dba521750c71d46d4a414de
User & Date: drh 2012-06-21 19:13:52
Context
2012-06-22
10:31
The same errors seen in the malloc-refactor branch are also on trunk, so go ahead and merge the malloc-refactor changes back into trunk. The errors were not caused by the refactoring, apparently. check-in: 91ba00572b user: drh tags: trunk
02:37
Begin refactoring the memory allocation logic to always require an environment pointer. This code will compile but does not run. check-in: 196691d50e user: drh tags: malloc-refactor
2012-06-21
20:22
Experimentally try embedding b-tree pages in sorted runs instead of creating an external separators run. This slows down the rate at which blocks can be cycled during incremental merging, but also makes database writes more contiguous. check-in: 97fe6585f1 user: dan tags: embedded-btree
19:13
Get the amalgmation build working. check-in: 2d7bf1c174 user: drh tags: trunk
2012-06-20
18:44
Do not crash if a NULL pointer is passed to lsm_work(). check-in: 9c5b3be405 user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to main.mk.

91
92
93
94
95
96
97


98
99
100
101
102
103
104
...
144
145
146
147
148
149
150


151
152
153
154
155
156
157
158
159
160
161
  $(TOP)/src/hash.c \
  $(TOP)/src/hash.h \
  $(TOP)/src/hwtime.h \
  $(TOP)/src/insert.c \
  $(TOP)/src/kvlsm.c \
  $(TOP)/src/kvmem.c \
  $(TOP)/src/legacy.c \


  $(TOP)/src/lsm_ckpt.c \
  $(TOP)/src/lsm_file.c \
  $(TOP)/src/lsm_log.c \
  $(TOP)/src/lsm_main.c \
  $(TOP)/src/lsm_mem.c \
  $(TOP)/src/lsm_mutex.c \
  $(TOP)/src/lsm_shared.c \
................................................................................
  $(TOP)/src/update.c \
  $(TOP)/src/util.c \
  $(TOP)/src/varint.c \
  $(TOP)/src/vdbe.c \
  $(TOP)/src/vdbe.h \
  $(TOP)/src/vdbeapi.c \
  $(TOP)/src/vdbeaux.c \


  $(TOP)/src/vdbemem.c \
  $(TOP)/src/vdbetrace.c \
  $(TOP)/src/vdbeInt.h \
  $(TOP)/src/vtab.c \
  $(TOP)/src/walker.c \
  $(TOP)/src/where.c

# Source code for extensions
#
SRC += \
  $(TOP)/ext/fts3/fts3.c \







>
>







 







>
>



<







91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
...
146
147
148
149
150
151
152
153
154
155
156
157

158
159
160
161
162
163
164
  $(TOP)/src/hash.c \
  $(TOP)/src/hash.h \
  $(TOP)/src/hwtime.h \
  $(TOP)/src/insert.c \
  $(TOP)/src/kvlsm.c \
  $(TOP)/src/kvmem.c \
  $(TOP)/src/legacy.c \
  $(TOP)/src/lsm.h \
  $(TOP)/src/lsmInt.h \
  $(TOP)/src/lsm_ckpt.c \
  $(TOP)/src/lsm_file.c \
  $(TOP)/src/lsm_log.c \
  $(TOP)/src/lsm_main.c \
  $(TOP)/src/lsm_mem.c \
  $(TOP)/src/lsm_mutex.c \
  $(TOP)/src/lsm_shared.c \
................................................................................
  $(TOP)/src/update.c \
  $(TOP)/src/util.c \
  $(TOP)/src/varint.c \
  $(TOP)/src/vdbe.c \
  $(TOP)/src/vdbe.h \
  $(TOP)/src/vdbeapi.c \
  $(TOP)/src/vdbeaux.c \
  $(TOP)/src/vdbecodec.c \
  $(TOP)/src/vdbecursor.c \
  $(TOP)/src/vdbemem.c \
  $(TOP)/src/vdbetrace.c \
  $(TOP)/src/vdbeInt.h \

  $(TOP)/src/walker.c \
  $(TOP)/src/where.c

# Source code for extensions
#
SRC += \
  $(TOP)/ext/fts3/fts3.c \

Changes to src/ctime.c.

173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
...
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
#endif
#ifdef SQLITE_OMIT_AUTOMATIC_INDEX
  "OMIT_AUTOMATIC_INDEX",
#endif
#ifdef SQLITE_OMIT_AUTORESET
  "OMIT_AUTORESET",
#endif
#ifdef SQLITE_OMIT_AUTOVACUUM
  "OMIT_AUTOVACUUM",
#endif
#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
  "OMIT_BETWEEN_OPTIMIZATION",
#endif
#ifdef SQLITE_OMIT_BLOB_LITERAL
  "OMIT_BLOB_LITERAL",
#endif
#ifdef SQLITE_OMIT_BTREECOUNT
  "OMIT_BTREECOUNT",
#endif
#ifdef SQLITE_OMIT_BUILTIN_TEST
  "OMIT_BUILTIN_TEST",
#endif
#ifdef SQLITE_OMIT_CAST
  "OMIT_CAST",
#endif
#ifdef SQLITE_OMIT_CHECK
................................................................................
#endif
#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
  "OMIT_TRUNCATE_OPTIMIZATION",
#endif
#ifdef SQLITE_OMIT_UTF16
  "OMIT_UTF16",
#endif
#ifdef SQLITE_OMIT_VACUUM
  "OMIT_VACUUM",
#endif
#ifdef SQLITE_OMIT_VIEW
  "OMIT_VIEW",
#endif
#ifdef SQLITE_OMIT_VIRTUALTABLE
  "OMIT_VIRTUALTABLE",
#endif
#ifdef SQLITE_OMIT_WAL
  "OMIT_WAL",
#endif
#ifdef SQLITE_OMIT_WSD
  "OMIT_WSD",
#endif
#ifdef SQLITE_OMIT_XFER_OPT
  "OMIT_XFER_OPT",
#endif
#ifdef SQLITE_PERFORMANCE_TRACE







<
<
<






<
<
<







 







<
<
<






<
<
<







173
174
175
176
177
178
179



180
181
182
183
184
185



186
187
188
189
190
191
192
...
289
290
291
292
293
294
295



296
297
298
299
300
301



302
303
304
305
306
307
308
#endif
#ifdef SQLITE_OMIT_AUTOMATIC_INDEX
  "OMIT_AUTOMATIC_INDEX",
#endif
#ifdef SQLITE_OMIT_AUTORESET
  "OMIT_AUTORESET",
#endif



#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
  "OMIT_BETWEEN_OPTIMIZATION",
#endif
#ifdef SQLITE_OMIT_BLOB_LITERAL
  "OMIT_BLOB_LITERAL",
#endif



#ifdef SQLITE_OMIT_BUILTIN_TEST
  "OMIT_BUILTIN_TEST",
#endif
#ifdef SQLITE_OMIT_CAST
  "OMIT_CAST",
#endif
#ifdef SQLITE_OMIT_CHECK
................................................................................
#endif
#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
  "OMIT_TRUNCATE_OPTIMIZATION",
#endif
#ifdef SQLITE_OMIT_UTF16
  "OMIT_UTF16",
#endif



#ifdef SQLITE_OMIT_VIEW
  "OMIT_VIEW",
#endif
#ifdef SQLITE_OMIT_VIRTUALTABLE
  "OMIT_VIRTUALTABLE",
#endif



#ifdef SQLITE_OMIT_WSD
  "OMIT_WSD",
#endif
#ifdef SQLITE_OMIT_XFER_OPT
  "OMIT_XFER_OPT",
#endif
#ifdef SQLITE_PERFORMANCE_TRACE

Changes to src/kvlsm.c.

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
..
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
..
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
  lsm_cursor *pCsr;               /* LSM cursor holding read-trans open */
};

struct KVLsmCsr {
  KVCursor base;                  /* Base class. Must be first */
  lsm_cursor *pCsr;               /* LSM cursor handle */
};

#define MAX(x,y) (((x)>(y)) ? (x) : (y))
  
/*
** Begin a transaction or subtransaction.
**
** If iLevel==1 then begin an outermost read transaction.
**
** If iLevel==2 then begin an outermost write transaction.
................................................................................
    rc = lsm_csr_open(p->pDb, &p->pCsr);
  }
  if( rc==SQLITE_OK && iLevel>=2 && iLevel>=pKVStore->iTransLevel ){
    rc = lsm_begin(p->pDb, iLevel-1);
  }

  if( rc==SQLITE_OK ){
    pKVStore->iTransLevel = MAX(iLevel, pKVStore->iTransLevel);
  }else if( pKVStore->iTransLevel==0 ){
    lsm_csr_close(p->pCsr);
    p->pCsr = 0;
  }

  return rc;
}
................................................................................
}
static int kvlsmCommitPhaseTwo(KVStore *pKVStore, int iLevel){
  int rc = SQLITE_OK;
  KVLsm *p = (KVLsm *)pKVStore;

  if( pKVStore->iTransLevel>iLevel ){
    if( pKVStore->iTransLevel>=2 ){
      rc = lsm_commit(p->pDb, MAX(0, iLevel-1));
    }
    if( iLevel==0 ){
      lsm_csr_close(p->pCsr);
      p->pCsr = 0;
    }
    if( rc==SQLITE_OK ){
      pKVStore->iTransLevel = iLevel;
................................................................................
*/
static int kvlsmRollback(KVStore *pKVStore, int iLevel){
  int rc = SQLITE_OK;
  KVLsm *p = (KVLsm *)pKVStore;

  if( pKVStore->iTransLevel>=iLevel ){
    if( pKVStore->iTransLevel>=2 ){
      rc = lsm_rollback(p->pDb, MAX(0, iLevel-1));
    }
    if( iLevel==0 ){
      lsm_csr_close(p->pCsr);
      p->pCsr = 0;
    }
    if( rc==SQLITE_OK ){
      pKVStore->iTransLevel = iLevel;







<
<







 







|







 







|







 







|







25
26
27
28
29
30
31


32
33
34
35
36
37
38
..
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
..
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
  lsm_cursor *pCsr;               /* LSM cursor holding read-trans open */
};

struct KVLsmCsr {
  KVCursor base;                  /* Base class. Must be first */
  lsm_cursor *pCsr;               /* LSM cursor handle */
};


  
/*
** Begin a transaction or subtransaction.
**
** If iLevel==1 then begin an outermost read transaction.
**
** If iLevel==2 then begin an outermost write transaction.
................................................................................
    rc = lsm_csr_open(p->pDb, &p->pCsr);
  }
  if( rc==SQLITE_OK && iLevel>=2 && iLevel>=pKVStore->iTransLevel ){
    rc = lsm_begin(p->pDb, iLevel-1);
  }

  if( rc==SQLITE_OK ){
    pKVStore->iTransLevel = SQLITE_MAX(iLevel, pKVStore->iTransLevel);
  }else if( pKVStore->iTransLevel==0 ){
    lsm_csr_close(p->pCsr);
    p->pCsr = 0;
  }

  return rc;
}
................................................................................
}
static int kvlsmCommitPhaseTwo(KVStore *pKVStore, int iLevel){
  int rc = SQLITE_OK;
  KVLsm *p = (KVLsm *)pKVStore;

  if( pKVStore->iTransLevel>iLevel ){
    if( pKVStore->iTransLevel>=2 ){
      rc = lsm_commit(p->pDb, SQLITE_MAX(0, iLevel-1));
    }
    if( iLevel==0 ){
      lsm_csr_close(p->pCsr);
      p->pCsr = 0;
    }
    if( rc==SQLITE_OK ){
      pKVStore->iTransLevel = iLevel;
................................................................................
*/
static int kvlsmRollback(KVStore *pKVStore, int iLevel){
  int rc = SQLITE_OK;
  KVLsm *p = (KVLsm *)pKVStore;

  if( pKVStore->iTransLevel>=iLevel ){
    if( pKVStore->iTransLevel>=2 ){
      rc = lsm_rollback(p->pDb, SQLITE_MAX(0, iLevel-1));
    }
    if( iLevel==0 ){
      lsm_csr_close(p->pCsr);
      p->pCsr = 0;
    }
    if( rc==SQLITE_OK ){
      pKVStore->iTransLevel = iLevel;

Changes to src/lsmInt.h.

585
586
587
588
589
590
591
592
593
594
595

/* 
** Round up a number to the next larger multiple of 8.  This is used
** to force 8-byte alignment on 64-bit architectures.
*/
#define ROUND8(x)     (((x)+7)&~7)

#define MIN(x,y) ((x)>(y) ? (y) : (x))
#define MAX(x,y) ((x)>(y) ? (x) : (y))

#endif







|
|


585
586
587
588
589
590
591
592
593
594
595

/* 
** Round up a number to the next larger multiple of 8.  This is used
** to force 8-byte alignment on 64-bit architectures.
*/
#define ROUND8(x)     (((x)+7)&~7)

#define LSM_MIN(x,y) ((x)>(y) ? (y) : (x))
#define LSM_MAX(x,y) ((x)>(y) ? (x) : (y))

#endif

Changes to src/lsm_ckpt.c.

178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
...
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
  lsm_env *pEnv;
  int nAlloc;
  u32 *aCkpt;
};

static void ckptSetValue(CkptBuffer *p, int iIdx, u32 iVal, int *pRc){
  if( iIdx>=p->nAlloc ){
    int nNew = MAX(8, iIdx*2);
    p->aCkpt = (u32 *)lsmReallocOrFree(p->pEnv, p->aCkpt, nNew*sizeof(u32));
    if( !p->aCkpt ){
      *pRc = LSM_NOMEM_BKPT;
      return;
    }
    p->nAlloc = nNew;
  }
................................................................................
        MetaPage *pPg;
        rc = lsmFsMetaPageGet(pDb->pFS, 0, iPg, &pPg);
        if( rc==LSM_OK ){
          int nCopy;
          int nData;
          u8 *aData = lsmFsMetaPageData(pPg, &nData);

          nCopy = MIN(nRem, nData);
          memcpy(aRem, aData, nCopy);
          aRem += nCopy;
          nRem -= nCopy;
          lsmFsMetaPageRelease(pPg);
        }
        iPg += 2;
      }







|







 







|







178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
...
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
  lsm_env *pEnv;
  int nAlloc;
  u32 *aCkpt;
};

static void ckptSetValue(CkptBuffer *p, int iIdx, u32 iVal, int *pRc){
  if( iIdx>=p->nAlloc ){
    int nNew = LSM_MAX(8, iIdx*2);
    p->aCkpt = (u32 *)lsmReallocOrFree(p->pEnv, p->aCkpt, nNew*sizeof(u32));
    if( !p->aCkpt ){
      *pRc = LSM_NOMEM_BKPT;
      return;
    }
    p->nAlloc = nNew;
  }
................................................................................
        MetaPage *pPg;
        rc = lsmFsMetaPageGet(pDb->pFS, 0, iPg, &pPg);
        if( rc==LSM_OK ){
          int nCopy;
          int nData;
          u8 *aData = lsmFsMetaPageData(pPg, &nData);

          nCopy = LSM_MIN(nRem, nData);
          memcpy(aRem, aData, nCopy);
          aRem += nCopy;
          nRem -= nCopy;
          lsmFsMetaPageRelease(pPg);
        }
        iPg += 2;
      }

Changes to src/lsm_file.c.

209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#define PAGE_FREE  0x00000002     /* Set if Page.aData requires lsmFree() */
#define PAGE_SHORT 0x00000004     /* Set if page is 4 bytes short */

/*
** Number of pgsz byte pages omitted from the start of block 1. The start
** of block 1 contains two 4096 byte meta pages (8192 bytes in total).
*/
#define BLOCK1_HDR_SIZE(pgsz)  MAX(1, 8192/(pgsz))

/*
** Return true if the SortedRun passed as the second argument is a phantom
** run currently being constructed by FileSystem object pFS.
*/
#define isPhantom(pFS, pSorted) ((pSorted) && (pFS)->phantom.pRun==(pSorted))








|







209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#define PAGE_FREE  0x00000002     /* Set if Page.aData requires lsmFree() */
#define PAGE_SHORT 0x00000004     /* Set if page is 4 bytes short */

/*
** Number of pgsz byte pages omitted from the start of block 1. The start
** of block 1 contains two 4096 byte meta pages (8192 bytes in total).
*/
#define BLOCK1_HDR_SIZE(pgsz)  LSM_MAX(1, 8192/(pgsz))

/*
** Return true if the SortedRun passed as the second argument is a phantom
** run currently being constructed by FileSystem object pFS.
*/
#define isPhantom(pFS, pSorted) ((pSorted) && (pFS)->phantom.pRun==(pSorted))

Changes to src/lsm_log.c.

565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
...
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
...
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
...
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
    if( rc!=LSM_OK ) return rc;

    while( nPad ){
      if( nPad==1 ){
        pLog->buf.z[pLog->buf.n++] = LSM_LOG_PAD1;
        nPad = 0;
      }else{
        int n = MIN(200, nPad-2);
        pLog->buf.z[pLog->buf.n++] = LSM_LOG_PAD2;
        pLog->buf.z[pLog->buf.n++] = n;
        nPad -= 2;
        memset(&pLog->buf.z[pLog->buf.n], 0x2B, n);
        pLog->buf.n += n;
        nPad -= n;
      }
................................................................................
void lsmLogTell(
  lsm_db *pDb,                    /* Database handle */
  LogMark *pMark                  /* Populate this object with current offset */
){
  LogWriter *pLog;
  int nCksum;

  if( pDb->bUseLog==0 ) return LSM_OK;
  pLog = pDb->pLogWriter;
  nCksum = pLog->buf.n & 0xFFFFFFF8;
  logUpdateCksum(pLog, nCksum);
  assert( pLog->iCksumBuf==nCksum );
  pMark->nBuf = pLog->buf.n - nCksum;
  memcpy(pMark->aBuf, &pLog->buf.z[nCksum], pMark->nBuf);

................................................................................
*/
void lsmLogSeek(
  lsm_db *pDb,                    /* Database handle */
  LogMark *pMark                  /* Object containing log offset to seek to */
){
  LogWriter *pLog;

  if( pDb->bUseLog==0 ) return LSM_OK;
  pLog = pDb->pLogWriter;

  assert( pMark->iOff<=pLog->iOff+pLog->buf.n );
  if( (pMark->iOff & 0xFFFFFFF8)>=pLog->iOff ){
    pLog->buf.n = pMark->iOff - pLog->iOff;
    pLog->iCksumBuf = (pLog->buf.n & 0xFFFFFFF8);
  }else{
................................................................................

    nAvail = p->buf.n - p->iBuf;
    if( ppBlob && nReq==nBlob && nBlob<=nAvail ){
      *ppBlob = (u8 *)&p->buf.z[p->iBuf];
      p->iBuf += nBlob;
      nReq = 0;
    }else{
      int nCopy = MIN(nAvail, nReq);
      if( nBlob==nReq ){
        if( ppBlob ) *ppBlob = (u8 *)pBuf->z;
        pBuf->n = 0;
      }
      rc = lsmStringBinAppend(pBuf, (u8 *)&p->buf.z[p->iBuf], nCopy);
      nReq -= nCopy;
      p->iBuf += nCopy;







|







 







|







 







|







 







|







565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
...
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
...
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
...
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
    if( rc!=LSM_OK ) return rc;

    while( nPad ){
      if( nPad==1 ){
        pLog->buf.z[pLog->buf.n++] = LSM_LOG_PAD1;
        nPad = 0;
      }else{
        int n = LSM_MIN(200, nPad-2);
        pLog->buf.z[pLog->buf.n++] = LSM_LOG_PAD2;
        pLog->buf.z[pLog->buf.n++] = n;
        nPad -= 2;
        memset(&pLog->buf.z[pLog->buf.n], 0x2B, n);
        pLog->buf.n += n;
        nPad -= n;
      }
................................................................................
void lsmLogTell(
  lsm_db *pDb,                    /* Database handle */
  LogMark *pMark                  /* Populate this object with current offset */
){
  LogWriter *pLog;
  int nCksum;

  if( pDb->bUseLog==0 ) return;
  pLog = pDb->pLogWriter;
  nCksum = pLog->buf.n & 0xFFFFFFF8;
  logUpdateCksum(pLog, nCksum);
  assert( pLog->iCksumBuf==nCksum );
  pMark->nBuf = pLog->buf.n - nCksum;
  memcpy(pMark->aBuf, &pLog->buf.z[nCksum], pMark->nBuf);

................................................................................
*/
void lsmLogSeek(
  lsm_db *pDb,                    /* Database handle */
  LogMark *pMark                  /* Object containing log offset to seek to */
){
  LogWriter *pLog;

  if( pDb->bUseLog==0 ) return;
  pLog = pDb->pLogWriter;

  assert( pMark->iOff<=pLog->iOff+pLog->buf.n );
  if( (pMark->iOff & 0xFFFFFFF8)>=pLog->iOff ){
    pLog->buf.n = pMark->iOff - pLog->iOff;
    pLog->iCksumBuf = (pLog->buf.n & 0xFFFFFFF8);
  }else{
................................................................................

    nAvail = p->buf.n - p->iBuf;
    if( ppBlob && nReq==nBlob && nBlob<=nAvail ){
      *ppBlob = (u8 *)&p->buf.z[p->iBuf];
      p->iBuf += nBlob;
      nReq = 0;
    }else{
      int nCopy = LSM_MIN(nAvail, nReq);
      if( nBlob==nReq ){
        if( ppBlob ) *ppBlob = (u8 *)pBuf->z;
        pBuf->n = 0;
      }
      rc = lsmStringBinAppend(pBuf, (u8 *)&p->buf.z[p->iBuf], nCopy);
      nReq -= nCopy;
      p->iBuf += nCopy;

Changes to src/lsm_main.c.

50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
...
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
...
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
#endif

/*
** The default key-compare function.
*/
static int xCmp(void *p1, int n1, void *p2, int n2){
  int res;
  res = memcmp(p1, p2, MIN(n1, n2));
  if( res==0 ) res = (n1-n2);
  return res;
}

/*
** Allocate a new db handle.
*/
................................................................................

int lsm_commit(lsm_db *pDb, int iLevel){
  int rc = LSM_OK;

  assert_db_state( pDb );

  /* A value less than zero means close the innermost nested transaction. */
  if( iLevel<0 ) iLevel = MAX(0, pDb->nTransOpen - 1);

  if( iLevel<pDb->nTransOpen ){
    if( iLevel==0 ){
      /* Commit the transaction to disk. */
      if( pDb->pTV && lsmTreeSize(pDb->pTV)>pDb->nTreeLimit ){
        rc = lsmFlushToDisk(pDb);
      }
................................................................................

int lsm_rollback(lsm_db *pDb, int iLevel){
  int rc = LSM_OK;
  assert_db_state( pDb );

  if( pDb->nTransOpen ){
    /* A value less than zero means close the innermost nested transaction. */
    if( iLevel<0 ) iLevel = MAX(0, pDb->nTransOpen - 1);

    if( iLevel<=pDb->nTransOpen ){
      TransMark *pMark = &pDb->aTrans[(iLevel==0 ? 0 : iLevel-1)];
      lsmTreeRollback(pDb, &pMark->tree);
      if( iLevel ) lsmLogSeek(pDb, &pMark->log);
      pDb->nTransOpen = iLevel;
    }







|







 







|







 







|







50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
...
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
...
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
#endif

/*
** The default key-compare function.
*/
static int xCmp(void *p1, int n1, void *p2, int n2){
  int res;
  res = memcmp(p1, p2, LSM_MIN(n1, n2));
  if( res==0 ) res = (n1-n2);
  return res;
}

/*
** Allocate a new db handle.
*/
................................................................................

int lsm_commit(lsm_db *pDb, int iLevel){
  int rc = LSM_OK;

  assert_db_state( pDb );

  /* A value less than zero means close the innermost nested transaction. */
  if( iLevel<0 ) iLevel = LSM_MAX(0, pDb->nTransOpen - 1);

  if( iLevel<pDb->nTransOpen ){
    if( iLevel==0 ){
      /* Commit the transaction to disk. */
      if( pDb->pTV && lsmTreeSize(pDb->pTV)>pDb->nTreeLimit ){
        rc = lsmFlushToDisk(pDb);
      }
................................................................................

int lsm_rollback(lsm_db *pDb, int iLevel){
  int rc = LSM_OK;
  assert_db_state( pDb );

  if( pDb->nTransOpen ){
    /* A value less than zero means close the innermost nested transaction. */
    if( iLevel<0 ) iLevel = LSM_MAX(0, pDb->nTransOpen - 1);

    if( iLevel<=pDb->nTransOpen ){
      TransMark *pMark = &pDb->aTrans[(iLevel==0 ? 0 : iLevel-1)];
      lsmTreeRollback(pDb, &pMark->tree);
      if( iLevel ) lsmLogSeek(pDb, &pMark->log);
      pDb->nTransOpen = iLevel;
    }

Changes to src/lsm_mem.c.

124
125
126
127
128
129
130
131
132
133
134
135
136
137
138


/*
** Allocate a new Chunk structure (using lsmMalloc()).
*/
static Chunk * poolChunkNew(lsm_env *pEnv, int nMin){
  Chunk *pChunk;
  int nAlloc = MAX(CHUNKSIZE, nMin + sizeof(Chunk));

  pChunk = (Chunk *)lsmMalloc(pEnv, nAlloc);
  if( pChunk ){
    pChunk->pNext = 0;
    pChunk->iOff = 0;
    pChunk->aData = (u8 *)&pChunk[1];
    pChunk->nData = nAlloc - sizeof(Chunk);







|







124
125
126
127
128
129
130
131
132
133
134
135
136
137
138


/*
** Allocate a new Chunk structure (using lsmMalloc()).
*/
static Chunk * poolChunkNew(lsm_env *pEnv, int nMin){
  Chunk *pChunk;
  int nAlloc = LSM_MAX(CHUNKSIZE, nMin + sizeof(Chunk));

  pChunk = (Chunk *)lsmMalloc(pEnv, nAlloc);
  if( pChunk ){
    pChunk->pNext = 0;
    pChunk->iOff = 0;
    pChunk->aData = (u8 *)&pChunk[1];
    pChunk->nData = nAlloc - sizeof(Chunk);

Changes to src/lsm_shared.c.

802
803
804
805
806
807
808
809
810
811
812
813
814
815
816

    /* Both Database.iCheckpointId and the Database.pClient list are 
    ** protected by the client mutex. So grab it here before determining
    ** the id of the oldest snapshot still potentially in use.  */
    lsmMutexEnter(pDb->pEnv, p->pClientMutex);
    assertSnapshotListOk(p);
    for(pIter=p->pClient; pIter->pSnapshotNext; pIter=pIter->pSnapshotNext);
    iInUse = MIN(pIter->iId, p->iCheckpointId);
    lsmMutexLeave(pDb->pEnv, p->pClientMutex);

    if( iFree<=iInUse ){
      iRet = pFree->aEntry[0].iBlk;
      flRemoveEntry0(pFree);
      assert( iRet!=0 );
      if( pWorker->bRecordDelta ){







|







802
803
804
805
806
807
808
809
810
811
812
813
814
815
816

    /* Both Database.iCheckpointId and the Database.pClient list are 
    ** protected by the client mutex. So grab it here before determining
    ** the id of the oldest snapshot still potentially in use.  */
    lsmMutexEnter(pDb->pEnv, p->pClientMutex);
    assertSnapshotListOk(p);
    for(pIter=p->pClient; pIter->pSnapshotNext; pIter=pIter->pSnapshotNext);
    iInUse = LSM_MIN(pIter->iId, p->iCheckpointId);
    lsmMutexLeave(pDb->pEnv, p->pClientMutex);

    if( iFree<=iInUse ){
      iRet = pFree->aEntry[0].iBlk;
      flRemoveEntry0(pFree);
      assert( iRet!=0 );
      if( pWorker->bRecordDelta ){

Changes to src/lsm_sorted.c.

467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
....
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
....
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
....
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
....
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
....
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
    lsmFsPageRef(pPg);

    while( rc==LSM_OK ){
      Page *pNext;
      int flags;

      /* Copy data from pPg into the output buffer. */
      int nCopy = MIN(nRem, iEnd-i);
      if( nCopy>0 ){
        memcpy(&aDest[nByte-nRem], &aData[i], nCopy);
        nRem -= nCopy;
        i += nCopy;
        assert( nRem==0 || i==iEnd );
      }
      assert( nRem>=0 );
................................................................................
      if( res<=0 ){
        iPtrOut = pPtr->iPtr + pPtr->iPgPtr;
      }

      if( res==0 || iMin==iMax ){
        break;
      }else if( res>0 ){
        iMax = MAX(iTry-1, iMin);
      }else{
        iMin = iTry+1;
      }
    }

    if( rc==LSM_OK ){
      assert( res==0 || (iMin==iMax && iMin>=0 && iMin<pPtr->nCell) );
................................................................................
  }
  return rc;
}

static int keyszToSkip(FileSystem *pFS, int nKey){
  int nPgsz;                /* Nominal database page size */
  nPgsz = lsmFsPageSize(pFS);
  return MIN(((nKey * 4) / nPgsz), 3);
}

/*
** Advance to the next page of an output run being populated by merge-worker
** pMW. If bSep is true, the separators run output is advanced by one page.
** Otherwise, the main run.
**
................................................................................
    int iOff;                     /* Offset in aData[] to write to */

    assert( lsmFsPageWritable(pMW->apPage[bSep]) );
   
    aData = lsmFsPageData(pMW->apPage[bSep], &nData);
    nRec = pageGetNRec(aData, nData);
    iOff = pMerge->aiOutputOff[bSep];
    nCopy = MIN(nRem, SEGMENT_EOF(nData, nRec) - iOff);

    memcpy(&aData[iOff], &aWrite[nWrite-nRem], nCopy);
    nRem -= nCopy;

    if( nRem>0 ){
      rc = mergeWorkerNextPage(pMW, bSep, iFPtr);
    }else{
................................................................................
  assert( lsmFsIntegrityCheck(pDb) );
  assert( pDb->pWorker );

  /* Determine how many units of work to do before returning. One unit of
  ** work is achieved by writing one page (~4KB) of merged data.  */
  nRemaining = nDepth = 0;
  for(pLevel=lsmDbSnapshotLevel(pDb->pWorker); pLevel; pLevel=pLevel->pNext){
    /* nDepth += MAX(1, pLevel->nRight); */
    nDepth += 1;
    /* nDepth += pLevel->nRight; */
  }
  nRemaining = nUnit * nDepth;

  rc = sortedWork(pDb, nRemaining, 0, 0);
  return rc;
................................................................................
  if( iRoot ){
    z2 = lsmMallocPrintf(pEnv, "root=%d", iRoot);
  }else{
    z2 = lsmMallocPrintf(pEnv, "size=%d", nSize);
  }

  nPad = nMin - 2 - strlen(z1) - 1 - strlen(z2);
  nPad = MAX(0, nPad);

  if( iRoot ){
    z = lsmMallocPrintf(pEnv, "/%s %*s%s\\", z1, nPad, "", z2);
  }else{
    z = lsmMallocPrintf(pEnv, "|%s %*s%s|", z1, nPad, "", z2);
  }
  lsmFree(pEnv, z1);







|







 







|







 







|







 







|







 







|







 







|







467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
....
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
....
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
....
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
....
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
....
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
    lsmFsPageRef(pPg);

    while( rc==LSM_OK ){
      Page *pNext;
      int flags;

      /* Copy data from pPg into the output buffer. */
      int nCopy = LSM_MIN(nRem, iEnd-i);
      if( nCopy>0 ){
        memcpy(&aDest[nByte-nRem], &aData[i], nCopy);
        nRem -= nCopy;
        i += nCopy;
        assert( nRem==0 || i==iEnd );
      }
      assert( nRem>=0 );
................................................................................
      if( res<=0 ){
        iPtrOut = pPtr->iPtr + pPtr->iPgPtr;
      }

      if( res==0 || iMin==iMax ){
        break;
      }else if( res>0 ){
        iMax = LSM_MAX(iTry-1, iMin);
      }else{
        iMin = iTry+1;
      }
    }

    if( rc==LSM_OK ){
      assert( res==0 || (iMin==iMax && iMin>=0 && iMin<pPtr->nCell) );
................................................................................
  }
  return rc;
}

static int keyszToSkip(FileSystem *pFS, int nKey){
  int nPgsz;                /* Nominal database page size */
  nPgsz = lsmFsPageSize(pFS);
  return LSM_MIN(((nKey * 4) / nPgsz), 3);
}

/*
** Advance to the next page of an output run being populated by merge-worker
** pMW. If bSep is true, the separators run output is advanced by one page.
** Otherwise, the main run.
**
................................................................................
    int iOff;                     /* Offset in aData[] to write to */

    assert( lsmFsPageWritable(pMW->apPage[bSep]) );
   
    aData = lsmFsPageData(pMW->apPage[bSep], &nData);
    nRec = pageGetNRec(aData, nData);
    iOff = pMerge->aiOutputOff[bSep];
    nCopy = LSM_MIN(nRem, SEGMENT_EOF(nData, nRec) - iOff);

    memcpy(&aData[iOff], &aWrite[nWrite-nRem], nCopy);
    nRem -= nCopy;

    if( nRem>0 ){
      rc = mergeWorkerNextPage(pMW, bSep, iFPtr);
    }else{
................................................................................
  assert( lsmFsIntegrityCheck(pDb) );
  assert( pDb->pWorker );

  /* Determine how many units of work to do before returning. One unit of
  ** work is achieved by writing one page (~4KB) of merged data.  */
  nRemaining = nDepth = 0;
  for(pLevel=lsmDbSnapshotLevel(pDb->pWorker); pLevel; pLevel=pLevel->pNext){
    /* nDepth += LSM_MAX(1, pLevel->nRight); */
    nDepth += 1;
    /* nDepth += pLevel->nRight; */
  }
  nRemaining = nUnit * nDepth;

  rc = sortedWork(pDb, nRemaining, 0, 0);
  return rc;
................................................................................
  if( iRoot ){
    z2 = lsmMallocPrintf(pEnv, "root=%d", iRoot);
  }else{
    z2 = lsmMallocPrintf(pEnv, "size=%d", nSize);
  }

  nPad = nMin - 2 - strlen(z1) - 1 - strlen(z2);
  nPad = LSM_MAX(0, nPad);

  if( iRoot ){
    z = lsmMallocPrintf(pEnv, "/%s %*s%s\\", z1, nPad, "", z2);
  }else{
    z = lsmMallocPrintf(pEnv, "|%s %*s%s|", z1, nPad, "", z2);
  }
  lsmFree(pEnv, z1);

Changes to src/lsm_tree.c.

882
883
884
885
886
887
888
889
890
891
892
893
894
895
896

#ifndef NDEBUG
static int treeCsrCompare(TreeCursor *pCsr, void *pKey, int nKey){
  TreeKey *p;
  int cmp;
  assert( pCsr->iNode>=0 );
  p = pCsr->apTreeNode[pCsr->iNode]->apKey[pCsr->aiCell[pCsr->iNode]];
  cmp = memcmp(p->pKey, pKey, MIN(p->nKey, nKey));
  if( cmp==0 ){
    cmp = p->nKey - nKey;
  }
  return cmp;
}
#endif








|







882
883
884
885
886
887
888
889
890
891
892
893
894
895
896

#ifndef NDEBUG
static int treeCsrCompare(TreeCursor *pCsr, void *pKey, int nKey){
  TreeKey *p;
  int cmp;
  assert( pCsr->iNode>=0 );
  p = pCsr->apTreeNode[pCsr->iNode]->apKey[pCsr->aiCell[pCsr->iNode]];
  cmp = memcmp(p->pKey, pKey, LSM_MIN(p->nKey, nKey));
  if( cmp==0 ){
    cmp = p->nKey - nKey;
  }
  return cmp;
}
#endif

Changes to src/lsm_varint.c.

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
               (0xffffffff & ((z[5]<<24) + (z[6]<<16) + (z[7]<<8) + z[8]));
  return 9;
}

/*
** Write a 32-bit unsigned integer as 4 big-endian bytes.
*/
static void varintWrite32(unsigned char *z, unsigned int y){
  z[0] = (unsigned char)(y>>24);
  z[1] = (unsigned char)(y>>16);
  z[2] = (unsigned char)(y>>8);
  z[3] = (unsigned char)(y);
}

/*
................................................................................
      z[0] = 250;
      z[1] = (unsigned char)(y>>16);
      z[2] = (unsigned char)(y>>8);
      z[3] = (unsigned char)(y);
      return 4;
    }
    z[0] = 251;
    varintWrite32(z+1, y);
    return 5;
  }
  if( w<=255 ){
    z[0] = 252;
    z[1] = (unsigned char)w;
    varintWrite32(z+2, y);
    return 6;
  }
  if( w<=32767 ){
    z[0] = 253;
    z[1] = (unsigned char)(w>>8);
    z[2] = (unsigned char)w;
    varintWrite32(z+3, y);
    return 7;
  }
  if( w<=16777215 ){
    z[0] = 254;
    z[1] = (unsigned char)(w>>16);
    z[2] = (unsigned char)(w>>8);
    z[3] = (unsigned char)w;
    varintWrite32(z+4, y);
    return 8;
  }
  z[0] = 255;
  varintWrite32(z+1, w);
  varintWrite32(z+5, y);
  return 9;
}

/*
** End of SQLite 4 code.
*************************************************************************/








|







 







|





|






|







|



|
|







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
               (0xffffffff & ((z[5]<<24) + (z[6]<<16) + (z[7]<<8) + z[8]));
  return 9;
}

/*
** Write a 32-bit unsigned integer as 4 big-endian bytes.
*/
static void lsmVarintWrite32(unsigned char *z, unsigned int y){
  z[0] = (unsigned char)(y>>24);
  z[1] = (unsigned char)(y>>16);
  z[2] = (unsigned char)(y>>8);
  z[3] = (unsigned char)(y);
}

/*
................................................................................
      z[0] = 250;
      z[1] = (unsigned char)(y>>16);
      z[2] = (unsigned char)(y>>8);
      z[3] = (unsigned char)(y);
      return 4;
    }
    z[0] = 251;
    lsmVarintWrite32(z+1, y);
    return 5;
  }
  if( w<=255 ){
    z[0] = 252;
    z[1] = (unsigned char)w;
    lsmVarintWrite32(z+2, y);
    return 6;
  }
  if( w<=32767 ){
    z[0] = 253;
    z[1] = (unsigned char)(w>>8);
    z[2] = (unsigned char)w;
    lsmVarintWrite32(z+3, y);
    return 7;
  }
  if( w<=16777215 ){
    z[0] = 254;
    z[1] = (unsigned char)(w>>16);
    z[2] = (unsigned char)(w>>8);
    z[3] = (unsigned char)w;
    lsmVarintWrite32(z+4, y);
    return 8;
  }
  z[0] = 255;
  lsmVarintWrite32(z+1, w);
  lsmVarintWrite32(z+5, y);
  return 9;
}

/*
** End of SQLite 4 code.
*************************************************************************/

Changes to src/main.c.

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
*/
const char sqlite4_version[] = SQLITE_VERSION;
#endif

/* IMPLEMENTATION-OF: R-53536-42575 The sqlite4_libversion() function returns
** a pointer to the to the sqlite4_version[] string constant. 
*/
const char *sqlite4_libversion(void){ return sqlite4_version; }

/* IMPLEMENTATION-OF: R-63124-39300 The sqlite4_sourceid() function returns a
** pointer to a string constant whose value is the same as the
** SQLITE_SOURCE_ID C preprocessor macro. 
*/
const char *sqlite4_sourceid(void){ return SQLITE_SOURCE_ID; }








|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
*/
const char sqlite4_version[] = SQLITE_VERSION;
#endif

/* IMPLEMENTATION-OF: R-53536-42575 The sqlite4_libversion() function returns
** a pointer to the to the sqlite4_version[] string constant. 
*/
const char *sqlite4_libversion(void){ return SQLITE_VERSION; }

/* IMPLEMENTATION-OF: R-63124-39300 The sqlite4_sourceid() function returns a
** pointer to a string constant whose value is the same as the
** SQLITE_SOURCE_ID C preprocessor macro. 
*/
const char *sqlite4_sourceid(void){ return SQLITE_SOURCE_ID; }

Changes to src/rowset.c.

161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
  int nAlloc;                     /* Bytes to request from malloc() */
  nAlloc = ROUND8(sizeof(RowSetChunk)) + nByte;
  pNew = (RowSetChunk *)sqlite4DbMallocRaw(p->db, nAlloc);
  return (pNew ? &((u8 *)pNew)[ROUND8(sizeof(RowSetChunk))] : 0);
}

static int rowsetEntryKeyCmp(RowSetEntry *pLeft, const u8 *aKey, int nKey){
  int nCmp = MIN(pLeft->nKey, nKey);
  int res;
  res = memcmp(pLeft->aKey, aKey, nCmp);
  return (res ? res : (pLeft->nKey - nKey));
}

static int rowsetEntryCmp(RowSetEntry *pLeft, RowSetEntry *pRight){
  return rowsetEntryKeyCmp(pLeft, pRight->aKey, pRight->nKey);







|







161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
  int nAlloc;                     /* Bytes to request from malloc() */
  nAlloc = ROUND8(sizeof(RowSetChunk)) + nByte;
  pNew = (RowSetChunk *)sqlite4DbMallocRaw(p->db, nAlloc);
  return (pNew ? &((u8 *)pNew)[ROUND8(sizeof(RowSetChunk))] : 0);
}

static int rowsetEntryKeyCmp(RowSetEntry *pLeft, const u8 *aKey, int nKey){
  int nCmp = SQLITE_MIN(pLeft->nKey, nKey);
  int res;
  res = memcmp(pLeft->aKey, aKey, nCmp);
  return (res ? res : (pLeft->nKey - nKey));
}

static int rowsetEntryCmp(RowSetEntry *pLeft, RowSetEntry *pRight){
  return rowsetEntryKeyCmp(pLeft, pRight->aKey, pRight->nKey);

Changes to src/select.c.

3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
....
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
....
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
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
    return WHERE_ORDERBY_MIN;
  }else if( sqlite4StrICmp(pExpr->u.zToken,"max")==0 ){
    return WHERE_ORDERBY_MAX;
  }
  return WHERE_ORDERBY_NORMAL;
}

/*
** The select statement passed as the first argument is an aggregate query.
** The second argment is the associated aggregate-info object. This 
** function tests if the SELECT is of the form:
**
**   SELECT count(*) FROM <tbl>
**
** where table is a database table, not a sub-select or view. If the query
** does match this pattern, then a pointer to the Table object representing
** <tbl> is returned. Otherwise, 0 is returned.
*/
#ifndef SQLITE_OMIT_BTREECOUNT
static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
  Table *pTab;
  Expr *pExpr;

  assert( !p->pGroupBy );

  if( p->pWhere || p->pEList->nExpr!=1 
   || p->pSrc->nSrc!=1 || p->pSrc->a[0].pSelect
  ){
    return 0;
  }
  pTab = p->pSrc->a[0].pTab;
  pExpr = p->pEList->a[0].pExpr;
  assert( pTab && !pTab->pSelect && pExpr );

  if( IsVirtual(pTab) ) return 0;
  if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
  if( (pAggInfo->aFunc[0].pFunc->flags&SQLITE_FUNC_COUNT)==0 ) return 0;
  if( pExpr->flags&EP_Distinct ) return 0;

  return pTab;
}
#endif

/*
** If the source-list item passed as an argument was augmented with an
** INDEXED BY clause, then try to locate the specified index. If there
** was such a clause and the named index cannot be found, return 
** SQLITE_ERROR and leave an error in pParse. Otherwise, populate 
** pFrom->pIndex and return SQLITE_OK.
*/
................................................................................
  for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
    sqlite4ExprCode(pParse, pC->pExpr, pC->iMem);
  }
  pAggInfo->directMode = 0;
  sqlite4ExprCacheClear(pParse);
}

/*
** Add a single OP_Explain instruction to the VDBE to explain a simple
** count(*) query ("SELECT count(*) FROM pTab").
*/
#ifndef SQLITE_OMIT_BTREECOUNT
#ifndef SQLITE_OMIT_EXPLAIN
static void explainSimpleCount(
  Parse *pParse,                  /* Parse context */
  Table *pTab,                    /* Table being queried */
  Index *pIdx                     /* Index used to optimize scan, or NULL */
){
  if( pParse->explain==2 ){
    char *zEqp = sqlite4MPrintf(pParse->db, "SCAN TABLE %s %s%s(~%d rows)",
        pTab->zName, 
        pIdx ? "USING COVERING INDEX " : "",
        pIdx ? pIdx->zName : "",
        pTab->nRowEst
    );
    sqlite4VdbeAddOp4(
        pParse->pVdbe, OP_Explain, pParse->iSelectId, 0, 0, zEqp, P4_DYNAMIC
    );
  }
}
#else
# define explainSimpleCount(a,b,c)
#endif
#endif  /* ifndef SQLITE_OMIT_BTREECOUNT */

/*
** Generate code for the SELECT statement given in the p argument.  
**
** The results are distributed in various ways depending on the
** contents of the SelectDest structure pointed to by argument pDest
** as follows:
**
................................................................................
      sqlite4VdbeResolveLabel(v, addrReset);
      resetAccumulator(pParse, &sAggInfo);
      sqlite4VdbeAddOp1(v, OP_Return, regReset);
     
    } /* endif pGroupBy.  Begin aggregate queries without GROUP BY: */
    else {
      ExprList *pDel = 0;
#ifndef SQLITE_OMIT_BTREECOUNT
      Table *pTab;
      if( (pTab = isSimpleCount(p, &sAggInfo))!=0 ){
        /* If isSimpleCount() returns a pointer to a Table structure, then
        ** the SQL statement is of the form:
        **
        **   SELECT count(*) FROM <tbl>
        **
        ** where the Table structure returned represents table <tbl>.
        **
        ** This statement is so common that it is optimized specially. The
        ** OP_Count instruction is executed either on the intkey table that
        ** contains the data for table <tbl> or on one of its indexes. It
        ** is better to execute the op on an index, as indexes are almost
        ** always spread across less pages than their corresponding tables.
        */
        const int iDb = sqlite4SchemaToIndex(pParse->db, pTab->pSchema);
        const int iCsr = pParse->nTab++;     /* Cursor to scan b-tree */
        Index *pIdx;                         /* Iterator variable */
        KeyInfo *pKeyInfo = 0;               /* Keyinfo for scanned index */
        Index *pBest = 0;                    /* Best index found so far */
        int iRoot = pTab->tnum;              /* Root page of scanned b-tree */

        sqlite4CodeVerifySchema(pParse, iDb);

        /* Search for the index that has the least amount of columns. If
        ** there is such an index, and it has less columns than the table
        ** does, then we can assume that it consumes less space on disk and
        ** will therefore be cheaper to scan to determine the query result.
        ** In this case set iRoot to the root page number of the index b-tree
        ** and pKeyInfo to the KeyInfo structure required to navigate the
        ** index.
        **
        ** (2011-04-15) Do not do a full scan of an unordered index.
        **
        ** In practice the KeyInfo structure will not be used. It is only 
        ** passed to keep OP_OpenRead happy.
        */
        for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
          if( pIdx->bUnordered==0 && (!pBest || pIdx->nColumn<pBest->nColumn) ){
            pBest = pIdx;
          }
        }
        if( pBest && pBest->nColumn<pTab->nCol ){
          iRoot = pBest->tnum;
          pKeyInfo = sqlite4IndexKeyinfo(pParse, pBest);
        }

        /* Open a read-only cursor, execute the OP_Count, close the cursor. */
        sqlite4VdbeAddOp3(v, OP_OpenRead, iCsr, iRoot, iDb);
        if( pKeyInfo ){
          sqlite4VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO_HANDOFF);
        }
        sqlite4VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem);
        sqlite4VdbeAddOp1(v, OP_Close, iCsr);
        explainSimpleCount(pParse, pTab, pBest);
      }else
#endif /* SQLITE_OMIT_BTREECOUNT */
      {
        /* Check if the query is of one of the following forms:
        **
        **   SELECT min(x) FROM ...
        **   SELECT max(x) FROM ...
        **
        ** If it is, then ask the code in where.c to attempt to sort results







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







 







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







 







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







3122
3123
3124
3125
3126
3127
3128




































3129
3130
3131
3132
3133
3134
3135
....
3630
3631
3632
3633
3634
3635
3636




























3637
3638
3639
3640
3641
3642
3643
....
4285
4286
4287
4288
4289
4290
4291


























































4292
4293
4294
4295
4296
4297
4298
    return WHERE_ORDERBY_MIN;
  }else if( sqlite4StrICmp(pExpr->u.zToken,"max")==0 ){
    return WHERE_ORDERBY_MAX;
  }
  return WHERE_ORDERBY_NORMAL;
}





































/*
** If the source-list item passed as an argument was augmented with an
** INDEXED BY clause, then try to locate the specified index. If there
** was such a clause and the named index cannot be found, return 
** SQLITE_ERROR and leave an error in pParse. Otherwise, populate 
** pFrom->pIndex and return SQLITE_OK.
*/
................................................................................
  for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
    sqlite4ExprCode(pParse, pC->pExpr, pC->iMem);
  }
  pAggInfo->directMode = 0;
  sqlite4ExprCacheClear(pParse);
}





























/*
** Generate code for the SELECT statement given in the p argument.  
**
** The results are distributed in various ways depending on the
** contents of the SelectDest structure pointed to by argument pDest
** as follows:
**
................................................................................
      sqlite4VdbeResolveLabel(v, addrReset);
      resetAccumulator(pParse, &sAggInfo);
      sqlite4VdbeAddOp1(v, OP_Return, regReset);
     
    } /* endif pGroupBy.  Begin aggregate queries without GROUP BY: */
    else {
      ExprList *pDel = 0;


























































      {
        /* Check if the query is of one of the following forms:
        **
        **   SELECT min(x) FROM ...
        **   SELECT max(x) FROM ...
        **
        ** If it is, then ask the code in where.c to attempt to sort results

Changes to src/sqliteInt.h.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
...
509
510
511
512
513
514
515
516

517
518
519
520
521
522
523
*************************************************************************
** Internal interface definitions for SQLite.
**
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*#define SQLITE_OMIT_BTREECOUNT 1*/
#define SQLITE_OMIT_WAL 1
#define SQLITE_OMIT_VACUUM 1
#define SQLITE_OMIT_AUTOVACUUM 1
/*#define SQLITE_OMIT_PAGER_PRAGMAS 1*/
#define SQLITE_OMIT_PROGRESS_CALLBACK 1

/*
** These #defines should enable >2GB file support on POSIX if the
** underlying operating system supports it.  If the OS lacks
** large file support, or if the OS is windows, these should be no-ops.
**
** Ticket #2739:  The _LARGEFILE_SOURCE macro must appear before any
................................................................................

/* 
** Round up a number to the next larger multiple of 8.  This is used
** to force 8-byte alignment on 64-bit architectures.
*/
#define ROUND8(x)     (((x)+7)&~7)

#define MIN(a,b) (((a)<(b)) ? (a) : (b))


/*
** Round down to the nearest multiple of 8
*/
#define ROUNDDOWN8(x) ((x)&~7)

/*







|
|
|
|
|
<







 







|
>







11
12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
...
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
*************************************************************************
** Internal interface definitions for SQLite.
**
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

#define SQLITE_OMIT_ANALYZE 1
#define SQLITE_OMIT_PROGRESS_CALLBACK 1
#define SQLITE_OMIT_VIRTUALTABLE 1
#define SQLITE_OMIT_XFER_OPT 1
#define SQLITE_OMIT_AUTOMATIC_INDEX 1


/*
** These #defines should enable >2GB file support on POSIX if the
** underlying operating system supports it.  If the OS lacks
** large file support, or if the OS is windows, these should be no-ops.
**
** Ticket #2739:  The _LARGEFILE_SOURCE macro must appear before any
................................................................................

/* 
** Round up a number to the next larger multiple of 8.  This is used
** to force 8-byte alignment on 64-bit architectures.
*/
#define ROUND8(x)     (((x)+7)&~7)

#define SQLITE_MIN(a,b) (((a)<(b)) ? (a) : (b))
#define SQLITE_MAX(a,b) (((a)>(b)) ? (a) : (b))

/*
** Round down to the nearest multiple of 8
*/
#define ROUNDDOWN8(x) ((x)&~7)

/*

Changes to src/vdbetrace.c.

117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
      assert( idx>0 && idx<=p->nVar );
      pVar = &p->aVar[idx-1];
      if( pVar->flags & MEM_Null ){
        sqlite4StrAccumAppend(&out, "NULL", 4);
      }else if( pVar->flags & MEM_Int ){
        sqlite4XPrintf(&out, "%lld", pVar->u.i);
      }else if( pVar->flags & MEM_Real ){
        sqlite4XPrintf(&out, "%!.15g", pVar->r);
      }else if( pVar->flags & MEM_Str ){
#ifndef SQLITE_OMIT_UTF16
        u8 enc = ENC(db);
        if( enc!=SQLITE_UTF8 ){
          Mem utf8;
          memset(&utf8, 0, sizeof(utf8));
          utf8.db = db;







|







117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
      assert( idx>0 && idx<=p->nVar );
      pVar = &p->aVar[idx-1];
      if( pVar->flags & MEM_Null ){
        sqlite4StrAccumAppend(&out, "NULL", 4);
      }else if( pVar->flags & MEM_Int ){
        sqlite4XPrintf(&out, "%lld", pVar->u.i);
      }else if( pVar->flags & MEM_Real ){
        sqlite4XPrintf(&out, "%!.16g", pVar->r);
      }else if( pVar->flags & MEM_Str ){
#ifndef SQLITE_OMIT_UTF16
        u8 enc = ENC(db);
        if( enc!=SQLITE_UTF8 ){
          Mem utf8;
          memset(&utf8, 0, sizeof(utf8));
          utf8.db = db;

Changes to tool/mksqlite4c.tcl.

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102


103
104
105
106
107
108
109
110
111
112
113
114
115
116

117
118
119
120
121
122
123
...
223
224
225
226
227
228
229
230
231

232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247

248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263




264
265
266
267


268
269
270
271
272
273
274
275
276
277
278
279
280
...
282
283
284
285
286
287
288
289
290
291
292
293
294
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
}

# These are the header files used by SQLite.  The first time any of these 
# files are seen in a #include statement in the C code, include the complete
# text of the file in-line.  The file only needs to be included once.
#
foreach hdr {
   btree.h
   btreeInt.h
   fts3.h
   fts3Int.h
   fts3_hash.h
   fts3_tokenizer.h
   hash.h
   hwtime.h
   keywordhash.h


   mutex.h
   opcodes.h
   os_common.h
   os.h
   os_os2.h
   pager.h
   parse.h
   pcache.h
   rtree.h
   sqlite4ext.h
   sqlite4.h
   sqliteicu.h
   sqliteInt.h
   sqliteLimit.h

   vdbe.h
   vdbeInt.h
} {
  set available_hdr($hdr) 1
}
set available_hdr(sqliteInt.h) 0

................................................................................
foreach file {
   sqliteInt.h

   global.c
   ctime.c
   status.c
   date.c
   os.c


   fault.c
   mem0.c
   mem1.c
   mem2.c
   mem3.c
   mem5.c
   mutex.c
   mutex_noop.c
   mutex_os2.c
   mutex_unix.c
   mutex_w32.c
   malloc.c
   printf.c
   random.c
   utf.c
   util.c

   hash.c
   opcodes.c

   os_os2.c
   os_unix.c
   os_win.c

   bitvec.c
   pcache.c
   pcache1.c
   rowset.c
   pager.c

   btmutex.c
   btree.c
   backup.c





   vdbemem.c
   vdbeaux.c
   vdbeapi.c


   vdbetrace.c
   vdbe.c
   vdbeblob.c
   vdbesort.c
   journal.c
   memjournal.c

   walker.c
   resolve.c
   expr.c
   alter.c
   analyze.c
   attach.c
................................................................................
   build.c
   callback.c
   delete.c
   func.c
   fkey.c
   insert.c
   legacy.c
   loadext.c
   pragma.c
   prepare.c
   select.c
   table.c
   trigger.c
   update.c
   vtab.c
   where.c

   parse.c

   tokenize.c
   complete.c

   main.c
   notify.c

   fts3.c
   fts3_aux.c
   fts3_expr.c
   fts3_hash.c
   fts3_porter.c
   fts3_tokenizer.c
   fts3_tokenizer1.c
   fts3_write.c
   fts3_snippet.c

   rtree.c
   icu.c
   fts3_icu.c
} {
  copy_file tsrc/$file
}

close $out







<
<
<
<
<
<



>
>


<

<
<
<
<
<
<

<


>







 







<

>








<







>



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




>
>


<
<
<
<







 







<



<


<








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





87
88
89
90
91
92
93






94
95
96
97
98
99
100

101






102

103
104
105
106
107
108
109
110
111
112
...
212
213
214
215
216
217
218

219
220
221
222
223
224
225
226
227
228

229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264




265
266
267
268
269
270
271
...
273
274
275
276
277
278
279

280
281
282

283
284

285
286
287
288
289
290
291
292















293
294
295
296
297
}

# These are the header files used by SQLite.  The first time any of these 
# files are seen in a #include statement in the C code, include the complete
# text of the file in-line.  The file only needs to be included once.
#
foreach hdr {






   hash.h
   hwtime.h
   keywordhash.h
   lsm.h
   lsmInt.h
   mutex.h
   opcodes.h

   os.h






   sqlite4.h

   sqliteInt.h
   sqliteLimit.h
   storage.h
   vdbe.h
   vdbeInt.h
} {
  set available_hdr($hdr) 1
}
set available_hdr(sqliteInt.h) 0

................................................................................
foreach file {
   sqliteInt.h

   global.c
   ctime.c
   status.c
   date.c


   os.c
   fault.c
   mem0.c
   mem1.c
   mem2.c
   mem3.c
   mem5.c
   mutex.c
   mutex_noop.c

   mutex_unix.c
   mutex_w32.c
   malloc.c
   printf.c
   random.c
   utf.c
   util.c
   varint.c
   hash.c
   opcodes.c

   lsm_ckpt.c
   lsm_file.c
   lsm_log.c
   lsm_main.c
   lsm_mem.c
   lsm_mutex.c
   lsm_shared.c
   lsm_sorted.c
   lsm_str.c
   lsm_tree.c
   lsm_unix.c
   lsm_varint.c

   storage.c
   kvmem.c
   kvlsm.c
   rowset.c

   vdbemem.c
   vdbeaux.c
   vdbeapi.c
   vdbecodec.c
   vdbecursor.c
   vdbetrace.c
   vdbe.c





   walker.c
   resolve.c
   expr.c
   alter.c
   analyze.c
   attach.c
................................................................................
   build.c
   callback.c
   delete.c
   func.c
   fkey.c
   insert.c
   legacy.c

   pragma.c
   prepare.c
   select.c

   trigger.c
   update.c

   where.c

   parse.c

   tokenize.c
   complete.c

   main.c















} {
  copy_file tsrc/$file
}

close $out