/ Check-in [78bc42e6]
Login

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

Overview
Comment:Merge recent enhancements and bug fixes from trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | sessions
Files: files | file ages | folders
SHA1:78bc42e664e9fa9ee21ad9762c369f291fcdf5db
User & Date: drh 2015-11-07 01:33:30
Context
2015-11-19
19:40
Merge the latest enhancements from trunk. check-in: 7d6cfc79 user: drh tags: sessions
2015-11-07
01:33
Merge recent enhancements and bug fixes from trunk. check-in: 78bc42e6 user: drh tags: sessions
01:19
The OPFLAG_SEEKEQ optimization is only applicable to equality comparisons against an index, not against a rowid table. check-in: 0f5b147d user: drh tags: trunk
2015-11-02
18:57
Merge all recent enhancements and fixes from trunk. check-in: 0546d1cd user: drh tags: sessions
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Makefile.in.

  1074   1074   fuzztest:	fuzzcheck$(TEXE) $(FUZZDATA)
  1075   1075   	./fuzzcheck$(TEXE) $(FUZZDATA)
  1076   1076   
  1077   1077   fastfuzztest:	fuzzcheck$(TEXE) $(FUZZDATA)
  1078   1078   	./fuzzcheck$(TEXE) --limit-mem 100M $(FUZZDATA)
  1079   1079   
  1080   1080   valgrindfuzz:	fuzzcheck$(TEXT) $(FUZZDATA)
  1081         -	valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M $(FUZZDATA)
         1081  +	valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)
  1082   1082   
  1083   1083   # Minimal testing that runs in less than 3 minutes
  1084   1084   #
  1085   1085   quicktest:	./testfixture$(TEXE)
  1086   1086   	./testfixture$(TEXE) $(TOP)/test/extraquick.test $(TESTOPTS)
  1087   1087   
  1088   1088   # This is the common case.  Run many tests that do not take too long,

Changes to ext/fts5/fts5Int.h.

   156    156     fts5_tokenizer *pTokApi;
   157    157   
   158    158     /* Values loaded from the %_config table */
   159    159     int iCookie;                    /* Incremented when %_config is modified */
   160    160     int pgsz;                       /* Approximate page size used in %_data */
   161    161     int nAutomerge;                 /* 'automerge' setting */
   162    162     int nCrisisMerge;               /* Maximum allowed segments per level */
          163  +  int nHashSize;                  /* Bytes of memory for in-memory hash */
   163    164     char *zRank;                    /* Name of rank function */
   164    165     char *zRankArgs;                /* Arguments to rank function */
   165    166   
   166    167     /* If non-NULL, points to sqlite3_vtab.base.zErrmsg. Often NULL. */
   167    168     char **pzErrmsg;
   168    169   
   169    170   #ifdef SQLITE_DEBUG

Changes to ext/fts5/fts5_config.c.

    16     16   
    17     17   
    18     18   #include "fts5Int.h"
    19     19   
    20     20   #define FTS5_DEFAULT_PAGE_SIZE   4050
    21     21   #define FTS5_DEFAULT_AUTOMERGE      4
    22     22   #define FTS5_DEFAULT_CRISISMERGE   16
           23  +#define FTS5_DEFAULT_HASHSIZE    (1024*1024)
    23     24   
    24     25   /* Maximum allowed page size */
    25     26   #define FTS5_MAX_PAGE_SIZE (128*1024)
    26     27   
    27     28   static int fts5_iswhitespace(char x){
    28     29     return (x==' ');
    29     30   }
................................................................................
   702    703     char *zRank = 0;
   703    704     char *zRankArgs = 0;
   704    705     int rc = SQLITE_OK;
   705    706   
   706    707     *pzRank = 0;
   707    708     *pzRankArgs = 0;
   708    709   
   709         -  p = fts5ConfigSkipWhitespace(p);
   710         -  pRank = p;
   711         -  p = fts5ConfigSkipBareword(p);
   712         -
   713         -  if( p ){
   714         -    zRank = sqlite3Fts5MallocZero(&rc, 1 + p - pRank);
   715         -    if( zRank ) memcpy(zRank, pRank, p-pRank);
   716         -  }else{
          710  +  if( p==0 ){
   717    711       rc = SQLITE_ERROR;
   718         -  }
   719         -
   720         -  if( rc==SQLITE_OK ){
          712  +  }else{
   721    713       p = fts5ConfigSkipWhitespace(p);
   722         -    if( *p!='(' ) rc = SQLITE_ERROR;
   723         -    p++;
   724         -  }
   725         -  if( rc==SQLITE_OK ){
   726         -    const char *pArgs; 
   727         -    p = fts5ConfigSkipWhitespace(p);
   728         -    pArgs = p;
   729         -    if( *p!=')' ){
   730         -      p = fts5ConfigSkipArgs(p);
   731         -      if( p==0 ){
   732         -        rc = SQLITE_ERROR;
   733         -      }else{
   734         -        zRankArgs = sqlite3Fts5MallocZero(&rc, 1 + p - pArgs);
   735         -        if( zRankArgs ) memcpy(zRankArgs, pArgs, p-pArgs);
          714  +    pRank = p;
          715  +    p = fts5ConfigSkipBareword(p);
          716  +
          717  +    if( p ){
          718  +      zRank = sqlite3Fts5MallocZero(&rc, 1 + p - pRank);
          719  +      if( zRank ) memcpy(zRank, pRank, p-pRank);
          720  +    }else{
          721  +      rc = SQLITE_ERROR;
          722  +    }
          723  +
          724  +    if( rc==SQLITE_OK ){
          725  +      p = fts5ConfigSkipWhitespace(p);
          726  +      if( *p!='(' ) rc = SQLITE_ERROR;
          727  +      p++;
          728  +    }
          729  +    if( rc==SQLITE_OK ){
          730  +      const char *pArgs; 
          731  +      p = fts5ConfigSkipWhitespace(p);
          732  +      pArgs = p;
          733  +      if( *p!=')' ){
          734  +        p = fts5ConfigSkipArgs(p);
          735  +        if( p==0 ){
          736  +          rc = SQLITE_ERROR;
          737  +        }else{
          738  +          zRankArgs = sqlite3Fts5MallocZero(&rc, 1 + p - pArgs);
          739  +          if( zRankArgs ) memcpy(zRankArgs, pArgs, p-pArgs);
          740  +        }
   736    741         }
   737    742       }
   738    743     }
   739    744   
   740    745     if( rc!=SQLITE_OK ){
   741    746       sqlite3_free(zRank);
   742    747       assert( zRankArgs==0 );
................................................................................
   762    767       }
   763    768       if( pgsz<=0 || pgsz>FTS5_MAX_PAGE_SIZE ){
   764    769         *pbBadkey = 1;
   765    770       }else{
   766    771         pConfig->pgsz = pgsz;
   767    772       }
   768    773     }
          774  +
          775  +  else if( 0==sqlite3_stricmp(zKey, "hashsize") ){
          776  +    int nHashSize = -1;
          777  +    if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
          778  +      nHashSize = sqlite3_value_int(pVal);
          779  +    }
          780  +    if( nHashSize<=0 ){
          781  +      *pbBadkey = 1;
          782  +    }else{
          783  +      pConfig->nHashSize = nHashSize;
          784  +    }
          785  +  }
   769    786   
   770    787     else if( 0==sqlite3_stricmp(zKey, "automerge") ){
   771    788       int nAutomerge = -1;
   772    789       if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
   773    790         nAutomerge = sqlite3_value_int(pVal);
   774    791       }
   775    792       if( nAutomerge<0 || nAutomerge>64 ){
................................................................................
   823    840     int rc = SQLITE_OK;
   824    841     int iVersion = 0;
   825    842   
   826    843     /* Set default values */
   827    844     pConfig->pgsz = FTS5_DEFAULT_PAGE_SIZE;
   828    845     pConfig->nAutomerge = FTS5_DEFAULT_AUTOMERGE;
   829    846     pConfig->nCrisisMerge = FTS5_DEFAULT_CRISISMERGE;
          847  +  pConfig->nHashSize = FTS5_DEFAULT_HASHSIZE;
   830    848   
   831    849     zSql = sqlite3Fts5Mprintf(&rc, zSelect, pConfig->zDb, pConfig->zName);
   832    850     if( zSql ){
   833    851       rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &p, 0);
   834    852       sqlite3_free(zSql);
   835    853     }
   836    854   

Changes to ext/fts5/fts5_index.c.

   284    284     int nWorkUnit;                  /* Leaf pages in a "unit" of work */
   285    285   
   286    286     /*
   287    287     ** Variables related to the accumulation of tokens and doclists within the
   288    288     ** in-memory hash tables before they are flushed to disk.
   289    289     */
   290    290     Fts5Hash *pHash;                /* Hash table for in-memory data */
   291         -  int nMaxPendingData;            /* Max pending data before flush to disk */
   292    291     int nPendingData;               /* Current bytes of pending data */
   293    292     i64 iWriteRowid;                /* Rowid for current doc being written */
   294    293     int bDelete;                    /* Current write is a delete */
   295    294   
   296    295     /* Error state. */
   297    296     int rc;                         /* Current error code */
   298    297   
................................................................................
  4449   4448     if( p->pHash==0 ){
  4450   4449       p->rc = sqlite3Fts5HashNew(&p->pHash, &p->nPendingData);
  4451   4450     }
  4452   4451   
  4453   4452     /* Flush the hash table to disk if required */
  4454   4453     if( iRowid<p->iWriteRowid 
  4455   4454      || (iRowid==p->iWriteRowid && p->bDelete==0)
  4456         -   || (p->nPendingData > p->nMaxPendingData) 
         4455  +   || (p->nPendingData > p->pConfig->nHashSize) 
  4457   4456     ){
  4458   4457       fts5IndexFlush(p);
  4459   4458     }
  4460   4459   
  4461   4460     p->iWriteRowid = iRowid;
  4462   4461     p->bDelete = bDelete;
  4463   4462     return fts5IndexReturn(p);
................................................................................
  4515   4514     int rc = SQLITE_OK;
  4516   4515     Fts5Index *p;                   /* New object */
  4517   4516   
  4518   4517     *pp = p = (Fts5Index*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Index));
  4519   4518     if( rc==SQLITE_OK ){
  4520   4519       p->pConfig = pConfig;
  4521   4520       p->nWorkUnit = FTS5_WORK_UNIT;
  4522         -    p->nMaxPendingData = 1024*1024;
  4523   4521       p->zDataTbl = sqlite3Fts5Mprintf(&rc, "%s_data", pConfig->zName);
  4524   4522       if( p->zDataTbl && bCreate ){
  4525   4523         rc = sqlite3Fts5CreateTable(
  4526   4524             pConfig, "data", "id INTEGER PRIMARY KEY, block BLOB", 0, pzErr
  4527   4525         );
  4528   4526         if( rc==SQLITE_OK ){
  4529   4527           rc = sqlite3Fts5CreateTable(pConfig, "idx", 

Changes to ext/fts5/fts5_main.c.

   390    390       );
   391    391     }
   392    392   
   393    393     /* Call sqlite3_declare_vtab() */
   394    394     if( rc==SQLITE_OK ){
   395    395       rc = sqlite3Fts5ConfigDeclareVtab(pConfig);
   396    396     }
          397  +
          398  +  /* Load the initial configuration */
          399  +  if( rc==SQLITE_OK ){
          400  +    assert( pConfig->pzErrmsg==0 );
          401  +    pConfig->pzErrmsg = pzErr;
          402  +    rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex);
          403  +    sqlite3Fts5IndexRollback(pTab->pIndex);
          404  +    pConfig->pzErrmsg = 0;
          405  +  }
   397    406   
   398    407     if( rc!=SQLITE_OK ){
   399    408       fts5FreeVtab(pTab);
   400    409       pTab = 0;
   401    410     }else if( bCreate ){
   402    411       fts5CheckTransactionState(pTab, FTS5_BEGIN, 0);
   403    412     }
................................................................................
   825    834           break;
   826    835       }
   827    836     }
   828    837     
   829    838     return rc;
   830    839   }
   831    840   
          841  +
          842  +static sqlite3_stmt *fts5PrepareStatement(
          843  +  int *pRc,
          844  +  Fts5Config *pConfig, 
          845  +  const char *zFmt,
          846  +  ...
          847  +){
          848  +  sqlite3_stmt *pRet = 0;
          849  +  va_list ap;
          850  +  va_start(ap, zFmt);
          851  +
          852  +  if( *pRc==SQLITE_OK ){
          853  +    int rc;
          854  +    char *zSql = sqlite3_vmprintf(zFmt, ap);
          855  +    if( zSql==0 ){
          856  +      rc = SQLITE_NOMEM; 
          857  +    }else{
          858  +      rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pRet, 0);
          859  +      if( rc!=SQLITE_OK ){
          860  +        *pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db));
          861  +      }
          862  +      sqlite3_free(zSql);
          863  +    }
          864  +    *pRc = rc;
          865  +  }
          866  +
          867  +  va_end(ap);
          868  +  return pRet;
          869  +} 
          870  +
   832    871   static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
   833    872     Fts5Config *pConfig = pTab->pConfig;
   834    873     Fts5Sorter *pSorter;
   835    874     int nPhrase;
   836    875     int nByte;
   837    876     int rc = SQLITE_OK;
   838         -  char *zSql;
   839    877     const char *zRank = pCsr->zRank;
   840    878     const char *zRankArgs = pCsr->zRankArgs;
   841    879     
   842    880     nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
   843    881     nByte = sizeof(Fts5Sorter) + sizeof(int) * (nPhrase-1);
   844    882     pSorter = (Fts5Sorter*)sqlite3_malloc(nByte);
   845    883     if( pSorter==0 ) return SQLITE_NOMEM;
................................................................................
   849    887     /* TODO: It would be better to have some system for reusing statement
   850    888     ** handles here, rather than preparing a new one for each query. But that
   851    889     ** is not possible as SQLite reference counts the virtual table objects.
   852    890     ** And since the statement required here reads from this very virtual 
   853    891     ** table, saving it creates a circular reference.
   854    892     **
   855    893     ** If SQLite a built-in statement cache, this wouldn't be a problem. */
   856         -  zSql = sqlite3Fts5Mprintf(&rc, 
          894  +  pSorter->pStmt = fts5PrepareStatement(&rc, pConfig,
   857    895         "SELECT rowid, rank FROM %Q.%Q ORDER BY %s(%s%s%s) %s",
   858    896         pConfig->zDb, pConfig->zName, zRank, pConfig->zName,
   859    897         (zRankArgs ? ", " : ""),
   860    898         (zRankArgs ? zRankArgs : ""),
   861    899         bDesc ? "DESC" : "ASC"
   862    900     );
   863         -  if( zSql ){
   864         -    rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pSorter->pStmt, 0);
   865         -    sqlite3_free(zSql);
   866         -  }
   867    901   
   868    902     pCsr->pSorter = pSorter;
   869    903     if( rc==SQLITE_OK ){
   870    904       assert( pTab->pSortCsr==0 );
   871    905       pTab->pSortCsr = pCsr;
   872    906       rc = fts5SorterNext(pCsr);
   873    907       pTab->pSortCsr = 0;

Changes to ext/fts5/test/fts5fault1.test.

    48     48   do_faultsim_test 2 -prep {
    49     49     faultsim_restore_and_reopen
    50     50   } -body {
    51     51     execsql { 
    52     52       INSERT INTO t1 VALUES('a b c', 'a bc def ghij klmno');
    53     53     }
    54     54   } -test {
    55         -  faultsim_test_result {0 {}} 
           55  +  faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}}
    56     56   }
    57     57   
    58     58   reset_db
    59     59   do_execsql_test 3.0 {
    60     60     CREATE VIRTUAL TABLE t1 USING fts5(a, b, prefix='1, 2, 3');
    61     61     INSERT INTO t1 VALUES('a b c', 'a bc def ghij klmno');
    62     62   }
    63     63   faultsim_save_and_close
    64     64   do_faultsim_test 3 -prep {
    65     65     faultsim_restore_and_reopen
    66     66   } -body {
    67     67     execsql { DELETE FROM t1 }
    68     68   } -test {
    69         -  faultsim_test_result {0 {}} 
           69  +  faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}}
    70     70   }
    71     71   
    72     72   reset_db
    73     73   do_execsql_test 4.0 {
    74     74     CREATE VIRTUAL TABLE t2 USING fts5(a, b);
    75     75     INSERT INTO t2 VALUES('m f a jj th q jr ar',   'hj n h h sg j i m');
    76     76     INSERT INTO t2 VALUES('nr s t g od j kf h',    'sb h aq rg op rb n nl');
................................................................................
    97     97     9 { m* + f* }       {1 8}
    98     98   } {
    99     99     do_faultsim_test 4.$tn -prep {
   100    100       faultsim_restore_and_reopen
   101    101     } -body "
   102    102       execsql { SELECT rowid FROM t2 WHERE t2 MATCH '$expr' }
   103    103     " -test "
   104         -    faultsim_test_result {[list 0 $res]}
          104  +    faultsim_test_result {[list 0 $res]} {1 {vtable constructor failed: t2}}
   105    105     "
   106    106   }
   107    107   
   108    108   
   109    109   #-------------------------------------------------------------------------
   110    110   # The following tests use a larger database populated with random data.
   111    111   #

Changes to ext/fts5/test/fts5fault4.test.

   103    103   }
   104    104   
   105    105   set ::res [db eval {SELECT rowid, x1 FROM x1 WHERE x1 MATCH '*reads'}]
   106    106   
   107    107   do_faultsim_test 4 -faults oom-* -body {
   108    108     db eval {SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads'}
   109    109   } -test {
   110         -  faultsim_test_result {0 {0 {} 3}}
          110  +  faultsim_test_result {0 {0 {} 4}}
   111    111   }
   112    112   
   113    113   #-------------------------------------------------------------------------
   114    114   # An OOM within a query that uses a custom rank function.
   115    115   #
   116    116   reset_db
   117    117   do_execsql_test 5.0 {

Changes to ext/fts5/test/fts5rank.test.

    36     36     SELECT highlight(xyz, 0, '[', ']') FROM xyz WHERE xyz MATCH 'x' ORDER BY rank
    37     37   } [list [string map {x [x]} $doc]]
    38     38   
    39     39   do_execsql_test 1.3 {
    40     40     SELECT highlight(xyz, 0, '[', ']') FROM xyz
    41     41     WHERE xyz MATCH 'x AND y' ORDER BY rank
    42     42   } [list [string map {x [x] y [y]} $doc]]
           43  +
           44  +#-------------------------------------------------------------------------
           45  +# Check that the 'rank' option really is persistent.
           46  +#
           47  +do_execsql_test 2.0 {
           48  +  CREATE VIRTUAL TABLE tt USING fts5(a);
           49  +  INSERT INTO tt VALUES('a x x x x');
           50  +  INSERT INTO tt VALUES('x x a a a');
           51  +  INSERT INTO tt VALUES('x a a x x');
           52  +}
           53  +
           54  +proc firstinst {cmd} { 
           55  +  foreach {p c o} [$cmd xInst 0] {}
           56  +  return $o
           57  +}
           58  +sqlite3_fts5_create_function db firstinst firstinst
           59  +
           60  +do_execsql_test 2.1 {
           61  +  SELECT rowid FROM tt('a') ORDER BY rank;
           62  +} {2 3 1}
           63  +
           64  +do_execsql_test 2.2 {
           65  +  SELECT rowid FROM tt('a', 'firstinst()') ORDER BY rank;
           66  +} {1 3 2}
           67  +
           68  +do_execsql_test 2.3 {
           69  +  INSERT INTO tt(tt, rank) VALUES('rank', 'firstinst()');
           70  +  SELECT rowid FROM tt('a') ORDER BY rank;
           71  +} {1 3 2}
           72  +
           73  +do_test 2.4 {
           74  +  sqlite3 db2 test.db
           75  +  catchsql { SELECT rowid FROM tt('a') ORDER BY rank; } db2
           76  +} {1 {no such function: firstinst}}
           77  +
           78  +do_test 2.5 {
           79  +  db2 close
           80  +  sqlite3 db2 test.db
           81  +  sqlite3_fts5_create_function db2 firstinst firstinst
           82  +  execsql { SELECT rowid FROM tt('a') ORDER BY rank; } db2
           83  +} {1 3 2}
           84  +
           85  +do_test 2.6 {
           86  +  execsql { SELECT rowid FROM tt('a') ORDER BY rank; } db2
           87  +} {1 3 2}
           88  +
           89  +do_test 2.7 {
           90  +  execsql { SELECT rowid FROM tt('a') ORDER BY rank; } db
           91  +} {1 3 2}
           92  +
           93  +
           94  +
           95  +
           96  +
           97  +
    43     98   
    44     99   finish_test
    45    100   

Changes to ext/fts5/test/fts5simple.test.

    14     14   set testprefix fts5simple
    15     15   
    16     16   # If SQLITE_ENABLE_FTS5 is defined, omit this file.
    17     17   ifcapable !fts5 {
    18     18     finish_test
    19     19     return
    20     20   }
    21         -
           21  + 
    22     22   #-------------------------------------------------------------------------
    23     23   #
    24     24   set doc "x x [string repeat {y } 50]z z"
    25     25   do_execsql_test 1.0 {
    26     26     CREATE VIRTUAL TABLE t1 USING fts5(x);
    27     27     INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
    28     28     BEGIN;
................................................................................
   317    317     1 {1 2 3}
   318    318     3 {2 3 4}
   319    319   }
   320    320   
   321    321   do_execsql_test 13.3 {
   322    322     INSERT INTO xy(xy) VALUES('integrity-check');
   323    323   }
          324  +
          325  +#-------------------------------------------------------------------------
          326  +#
          327  +do_execsql_test 14.1 {
          328  +  CREATE VIRTUAL TABLE ttt USING fts5(x);
          329  +  BEGIN;
          330  +    INSERT INTO ttt(rowid, x) VALUES(1, 'a b c');
          331  +    INSERT INTO ttt(rowid, x) VALUES(2, 'a b c');
          332  +    INSERT INTO ttt(rowid, x) VALUES(3, 'a b c');
          333  +  COMMIT;
          334  +}
          335  +do_test 14.2 { 
          336  +  fts5_level_segs ttt 
          337  +} {1}
          338  +
          339  +#-------------------------------------------------------------------------
          340  +db func rnddoc fts5_rnddoc
          341  +do_execsql_test 4.0 {
          342  +  CREATE VIRTUAL TABLE x1 USING fts5(x);
          343  +  INSERT INTO x1(x1, rank) VALUES('pgsz', 32);
          344  +
          345  +  WITH ii(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<10 )
          346  +  INSERT INTO x1 SELECT rnddoc(5) FROM ii;
          347  +}
          348  +
          349  +do_execsql_test 4.1 {
          350  +  SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads'
          351  +} {0 {} 4}
          352  +
   324    353   
   325    354   finish_test
   326    355   

Changes to ext/fts5/tool/loadfts5.tcl.

    44     44     puts stderr "  -porter      (use porter tokenizer)"
    45     45     puts stderr "  -delete      (delete the database file before starting)"
    46     46     puts stderr "  -limit N     (load no more than N documents)"
    47     47     puts stderr "  -automerge N (set the automerge parameter to N)"
    48     48     puts stderr "  -crisismerge N (set the crisismerge parameter to N)"
    49     49     puts stderr "  -prefix PREFIX (comma separated prefix= argument)"
    50     50     puts stderr "  -trans N     (commit after N inserts - 0 == never)"
           51  +  puts stderr "  -hashsize N  (set the fts5 hashsize parameter to N)"
    51     52     exit 1
    52     53   }
    53     54   
    54     55   set O(vtab)       fts5
    55     56   set O(tok)        ""
    56     57   set O(limit)      0
    57     58   set O(delete)     0
    58     59   set O(automerge)  -1
    59     60   set O(crisismerge)  -1
    60     61   set O(prefix)     ""
    61     62   set O(trans)      0
           63  +set O(hashsize)   -1
    62     64   
    63     65   if {[llength $argv]<2} usage
    64     66   set nOpt [expr {[llength $argv]-2}]
    65     67   for {set i 0} {$i < $nOpt} {incr i} {
    66     68     set arg [lindex $argv $i]
    67     69     switch -- [lindex $argv $i] {
    68     70       -fts4 {
................................................................................
   101    103         set O(crisismerge) [lindex $argv $i]
   102    104       }
   103    105   
   104    106       -prefix {
   105    107         if { [incr i]>=$nOpt } usage
   106    108         set O(prefix) [lindex $argv $i]
   107    109       }
          110  +
          111  +    -hashsize {
          112  +      if { [incr i]>=$nOpt } usage
          113  +      set O(hashsize) [lindex $argv $i]
          114  +    }
   108    115   
   109    116       default {
   110    117         usage
   111    118       }
   112    119     }
   113    120   }
   114    121   
................................................................................
   122    129   db eval BEGIN
   123    130     set pref ""
   124    131     if {$O(prefix)!=""} { set pref ", prefix='$O(prefix)'" }
   125    132     catch {
   126    133       db eval "CREATE VIRTUAL TABLE t1 USING $O(vtab) (path, content$O(tok)$pref)"
   127    134       db eval "INSERT INTO t1(t1, rank) VALUES('pgsz', 4050);"
   128    135     }
          136  +
          137  +  if {$O(hashsize)>=0} {
          138  +    catch {
          139  +      db eval "INSERT INTO t1(t1, rank) VALUES('hashsize', $O(hashsize));"
          140  +    }
          141  +  }
          142  +
          143  +
   129    144     if {$O(automerge)>=0} {
   130    145       if {$O(vtab) == "fts5"} {
   131    146         db eval { INSERT INTO t1(t1, rank) VALUES('automerge', $O(automerge)) }
   132    147       } else {
   133    148         db eval { INSERT INTO t1(t1) VALUES('automerge=' || $O(automerge)) }
   134    149       }
   135    150     }
................................................................................
   137    152       if {$O(vtab) == "fts5"} {
   138    153         db eval {INSERT INTO t1(t1, rank) VALUES('crisismerge', $O(crisismerge))}
   139    154       } else {
   140    155       }
   141    156     }
   142    157     load_hierachy [lindex $argv end]
   143    158   db eval COMMIT
          159  +puts ""
   144    160   
   145    161   
   146    162   

Changes to ext/misc/ieee754.c.

    90     90         sqlite3_result_double(context, 0.0);
    91     91         return;
    92     92       }
    93     93       while( (m>>32)&0xffe00000 ){
    94     94         m >>= 1;
    95     95         e++;
    96     96       }
    97         -    while( ((m>>32)&0xfff00000)==0 ){
           97  +    while( m!=0 && ((m>>32)&0xfff00000)==0 ){
    98     98         m <<= 1;
    99     99         e--;
   100    100       }
   101    101       e += 1075;
   102    102       if( e<0 ) e = m = 0;
   103         -    if( e>0x7ff ) m = 0;
          103  +    if( e>0x7ff ) e = 0x7ff;
   104    104       a = m & ((((sqlite3_int64)1)<<52)-1);
   105    105       a |= e<<52;
   106         -    if( isNeg ) a |= ((sqlite3_int64)1)<<63;
          106  +    if( isNeg ) a |= ((sqlite3_uint64)1)<<63;
   107    107       memcpy(&r, &a, sizeof(r));
   108    108       sqlite3_result_double(context, r);
   109    109     }
   110    110   }
   111    111   
   112    112   
   113    113   #ifdef _WIN32

Changes to main.mk.

   764    764   fuzztest:	fuzzcheck$(EXE) $(FUZZDATA)
   765    765   	./fuzzcheck$(EXE) $(FUZZDATA)
   766    766   
   767    767   fastfuzztest:	fuzzcheck$(EXE) $(FUZZDATA)
   768    768   	./fuzzcheck$(EXE) --limit-mem 100M $(FUZZDATA)
   769    769   
   770    770   valgrindfuzz:	fuzzcheck$(EXE) $(FUZZDATA)
   771         -	valgrind ./fuzzcheck$(EXE) --cell-size-check --limit-mem 10M $(FUZZDATA)
          771  +	valgrind ./fuzzcheck$(EXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)
   772    772   
   773    773   # A very quick test using only testfixture and omitting all the slower
   774    774   # tests.  Designed to run in under 3 minutes on a workstation.
   775    775   #
   776    776   quicktest:	./testfixture$(EXE)
   777    777   	./testfixture$(EXE) $(TOP)/test/extraquick.test $(TESTOPTS)
   778    778   

Changes to src/backup.c.

   289    289     ** page. For each iteration, variable iOff is set to the byte offset
   290    290     ** of the destination page.
   291    291     */
   292    292     for(iOff=iEnd-(i64)nSrcPgsz; rc==SQLITE_OK && iOff<iEnd; iOff+=nDestPgsz){
   293    293       DbPage *pDestPg = 0;
   294    294       Pgno iDest = (Pgno)(iOff/nDestPgsz)+1;
   295    295       if( iDest==PENDING_BYTE_PAGE(p->pDest->pBt) ) continue;
   296         -    if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg))
          296  +    if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg, 0))
   297    297        && SQLITE_OK==(rc = sqlite3PagerWrite(pDestPg))
   298    298       ){
   299    299         const u8 *zIn = &zSrcData[iOff%nSrcPgsz];
   300    300         u8 *zDestData = sqlite3PagerGetData(pDestPg);
   301    301         u8 *zOut = &zDestData[iOff%nDestPgsz];
   302    302   
   303    303         /* Copy the data from the source page into the destination page.
................................................................................
   415    415       */
   416    416       nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc);
   417    417       assert( nSrcPage>=0 );
   418    418       for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){
   419    419         const Pgno iSrcPg = p->iNext;                 /* Source page number */
   420    420         if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
   421    421           DbPage *pSrcPg;                             /* Source page object */
   422         -        rc = sqlite3PagerAcquire(pSrcPager, iSrcPg, &pSrcPg,
   423         -                                 PAGER_GET_READONLY);
          422  +        rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg,PAGER_GET_READONLY);
   424    423           if( rc==SQLITE_OK ){
   425    424             rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0);
   426    425             sqlite3PagerUnref(pSrcPg);
   427    426           }
   428    427         }
   429    428         p->iNext++;
   430    429       }
................................................................................
   516    515             ** the database file in any way, knowing that if a power failure
   517    516             ** occurs, the original database will be reconstructed from the 
   518    517             ** journal file.  */
   519    518             sqlite3PagerPagecount(pDestPager, &nDstPage);
   520    519             for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){
   521    520               if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){
   522    521                 DbPage *pPg;
   523         -              rc = sqlite3PagerGet(pDestPager, iPg, &pPg);
          522  +              rc = sqlite3PagerGet(pDestPager, iPg, &pPg, 0);
   524    523                 if( rc==SQLITE_OK ){
   525    524                   rc = sqlite3PagerWrite(pPg);
   526    525                   sqlite3PagerUnref(pPg);
   527    526                 }
   528    527               }
   529    528             }
   530    529             if( rc==SQLITE_OK ){
................................................................................
   536    535             for(
   537    536               iOff=PENDING_BYTE+pgszSrc; 
   538    537               rc==SQLITE_OK && iOff<iEnd; 
   539    538               iOff+=pgszSrc
   540    539             ){
   541    540               PgHdr *pSrcPg = 0;
   542    541               const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1);
   543         -            rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
          542  +            rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg, 0);
   544    543               if( rc==SQLITE_OK ){
   545    544                 u8 *zData = sqlite3PagerGetData(pSrcPg);
   546    545                 rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff);
   547    546               }
   548    547               sqlite3PagerUnref(pSrcPg);
   549    548             }
   550    549             if( rc==SQLITE_OK ){

Changes to src/btree.c.

   927    927   
   928    928     assert( pBt->autoVacuum );
   929    929     if( key==0 ){
   930    930       *pRC = SQLITE_CORRUPT_BKPT;
   931    931       return;
   932    932     }
   933    933     iPtrmap = PTRMAP_PAGENO(pBt, key);
   934         -  rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage);
          934  +  rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage, 0);
   935    935     if( rc!=SQLITE_OK ){
   936    936       *pRC = rc;
   937    937       return;
   938    938     }
   939    939     offset = PTRMAP_PTROFFSET(iPtrmap, key);
   940    940     if( offset<0 ){
   941    941       *pRC = SQLITE_CORRUPT_BKPT;
................................................................................
   970    970     u8 *pPtrmap;       /* Pointer map page data */
   971    971     int offset;        /* Offset of entry in pointer map */
   972    972     int rc;
   973    973   
   974    974     assert( sqlite3_mutex_held(pBt->mutex) );
   975    975   
   976    976     iPtrmap = PTRMAP_PAGENO(pBt, key);
   977         -  rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage);
          977  +  rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage, 0);
   978    978     if( rc!=0 ){
   979    979       return rc;
   980    980     }
   981    981     pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);
   982    982   
   983    983     offset = PTRMAP_PTROFFSET(iPtrmap, key);
   984    984     if( offset<0 ){
................................................................................
  1897   1897   
  1898   1898   /*
  1899   1899   ** Convert a DbPage obtained from the pager into a MemPage used by
  1900   1900   ** the btree layer.
  1901   1901   */
  1902   1902   static MemPage *btreePageFromDbPage(DbPage *pDbPage, Pgno pgno, BtShared *pBt){
  1903   1903     MemPage *pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
  1904         -  pPage->aData = sqlite3PagerGetData(pDbPage);
  1905         -  pPage->pDbPage = pDbPage;
  1906         -  pPage->pBt = pBt;
  1907         -  pPage->pgno = pgno;
  1908         -  pPage->hdrOffset = pgno==1 ? 100 : 0;
         1904  +  if( pgno!=pPage->pgno ){
         1905  +    pPage->aData = sqlite3PagerGetData(pDbPage);
         1906  +    pPage->pDbPage = pDbPage;
         1907  +    pPage->pBt = pBt;
         1908  +    pPage->pgno = pgno;
         1909  +    pPage->hdrOffset = pgno==1 ? 100 : 0;
         1910  +  }
         1911  +  assert( pPage->aData==sqlite3PagerGetData(pDbPage) );
  1909   1912     return pPage; 
  1910   1913   }
  1911   1914   
  1912   1915   /*
  1913   1916   ** Get a page from the pager.  Initialize the MemPage.pBt and
  1914   1917   ** MemPage.aData elements if needed.  See also: btreeGetUnusedPage().
  1915   1918   **
................................................................................
  1927   1930     int flags            /* PAGER_GET_NOCONTENT or PAGER_GET_READONLY */
  1928   1931   ){
  1929   1932     int rc;
  1930   1933     DbPage *pDbPage;
  1931   1934   
  1932   1935     assert( flags==0 || flags==PAGER_GET_NOCONTENT || flags==PAGER_GET_READONLY );
  1933   1936     assert( sqlite3_mutex_held(pBt->mutex) );
  1934         -  rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, flags);
         1937  +  rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, flags);
  1935   1938     if( rc ) return rc;
  1936   1939     *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt);
  1937   1940     return SQLITE_OK;
  1938   1941   }
  1939   1942   
  1940   1943   /*
  1941   1944   ** Retrieve a page from the pager cache. If the requested page is not
................................................................................
  1992   1995     assert( pCur==0 || bReadOnly==pCur->curPagerFlags );
  1993   1996     assert( pCur==0 || pCur->iPage>0 );
  1994   1997   
  1995   1998     if( pgno>btreePagecount(pBt) ){
  1996   1999       rc = SQLITE_CORRUPT_BKPT;
  1997   2000       goto getAndInitPage_error;
  1998   2001     }
  1999         -  rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly);
         2002  +  rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly);
  2000   2003     if( rc ){
  2001   2004       goto getAndInitPage_error;
  2002   2005     }
  2003         -  *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt);
         2006  +  *ppPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
  2004   2007     if( (*ppPage)->isInit==0 ){
         2008  +    btreePageFromDbPage(pDbPage, pgno, pBt);
  2005   2009       rc = btreeInitPage(*ppPage);
  2006   2010       if( rc!=SQLITE_OK ){
  2007   2011         releasePage(*ppPage);
  2008   2012         goto getAndInitPage_error;
  2009   2013       }
  2010   2014     }
         2015  +  assert( (*ppPage)->pgno==pgno );
         2016  +  assert( (*ppPage)->aData==sqlite3PagerGetData(pDbPage) );
  2011   2017   
  2012   2018     /* If obtaining a child page for a cursor, we must verify that the page is
  2013   2019     ** compatible with the root page. */
  2014         -  if( pCur
  2015         -   && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey)
  2016         -  ){
         2020  +  if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){
  2017   2021       rc = SQLITE_CORRUPT_BKPT;
  2018   2022       releasePage(*ppPage);
  2019   2023       goto getAndInitPage_error;
  2020   2024     }
  2021   2025     return SQLITE_OK;
  2022   2026   
  2023   2027   getAndInitPage_error:
................................................................................
  4589   4593             nextPage = get4byte(aWrite);
  4590   4594             memcpy(aWrite, aSave, 4);
  4591   4595           }else
  4592   4596   #endif
  4593   4597   
  4594   4598           {
  4595   4599             DbPage *pDbPage;
  4596         -          rc = sqlite3PagerAcquire(pBt->pPager, nextPage, &pDbPage,
         4600  +          rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage,
  4597   4601                 ((eOp&0x01)==0 ? PAGER_GET_READONLY : 0)
  4598   4602             );
  4599   4603             if( rc==SQLITE_OK ){
  4600   4604               aPayload = sqlite3PagerGetData(pDbPage);
  4601   4605               nextPage = get4byte(aPayload);
  4602   4606               rc = copyPayload(&aPayload[offset+4], pBuf, a, (eOp&0x01), pDbPage);
  4603   4607               sqlite3PagerUnref(pDbPage);
................................................................................
  5033   5037   **
  5034   5038   **     *pRes==0     The cursor is left pointing at an entry that
  5035   5039   **                  exactly matches intKey/pIdxKey.
  5036   5040   **
  5037   5041   **     *pRes>0      The cursor is left pointing at an entry that
  5038   5042   **                  is larger than intKey/pIdxKey.
  5039   5043   **
         5044  +** For index tables, the pIdxKey->eqSeen field is set to 1 if there
         5045  +** exists an entry in the table that exactly matches pIdxKey.  
  5040   5046   */
  5041   5047   int sqlite3BtreeMovetoUnpacked(
  5042   5048     BtCursor *pCur,          /* The cursor to be moved */
  5043   5049     UnpackedRecord *pIdxKey, /* Unpacked index key */
  5044   5050     i64 intKey,              /* The table key */
  5045   5051     int biasRight,           /* If true, bias the search to the high end */
  5046   5052     int *pRes                /* Write search results here */
................................................................................
  6956   6962   ** size of a cell stored within an internal node is always less than 1/4
  6957   6963   ** of the page-size, the aOvflSpace[] buffer is guaranteed to be large
  6958   6964   ** enough for all overflow cells.
  6959   6965   **
  6960   6966   ** If aOvflSpace is set to a null pointer, this function returns 
  6961   6967   ** SQLITE_NOMEM.
  6962   6968   */
  6963         -#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM)
  6964         -#pragma optimize("", off)
  6965         -#endif
  6966   6969   static int balance_nonroot(
  6967   6970     MemPage *pParent,               /* Parent page of siblings being balanced */
  6968   6971     int iParentIdx,                 /* Index of "the page" in pParent */
  6969   6972     u8 *aOvflSpace,                 /* page-size bytes of space for parent ovfl */
  6970   6973     int isRoot,                     /* True if pParent is a root-page */
  6971   6974     int bBulk                       /* True if this call is part of a bulk load */
  6972   6975   ){
................................................................................
  7704   7707     }
  7705   7708     for(i=0; i<nNew; i++){
  7706   7709       releasePage(apNew[i]);
  7707   7710     }
  7708   7711   
  7709   7712     return rc;
  7710   7713   }
  7711         -#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM)
  7712         -#pragma optimize("", on)
  7713         -#endif
  7714   7714   
  7715   7715   
  7716   7716   /*
  7717   7717   ** This function is called when the root page of a b-tree structure is
  7718   7718   ** overfull (has one or more overflow pages).
  7719   7719   **
  7720   7720   ** A new child page is allocated and the contents of the current root
................................................................................
  8905   8905       if( iPage<1 ){
  8906   8906         checkAppendMsg(pCheck,
  8907   8907            "%d of %d pages missing from overflow list starting at %d",
  8908   8908             N+1, expected, iFirst);
  8909   8909         break;
  8910   8910       }
  8911   8911       if( checkRef(pCheck, iPage) ) break;
  8912         -    if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage) ){
         8912  +    if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){
  8913   8913         checkAppendMsg(pCheck, "failed to get page %d", iPage);
  8914   8914         break;
  8915   8915       }
  8916   8916       pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage);
  8917   8917       if( isFreeList ){
  8918   8918         int n = get4byte(&pOvflData[4]);
  8919   8919   #ifndef SQLITE_OMIT_AUTOVACUUM
................................................................................
  9642   9642       }
  9643   9643     }
  9644   9644   
  9645   9645     pBt->btsFlags &= ~BTS_NO_WAL;
  9646   9646     return rc;
  9647   9647   }
  9648   9648   
  9649         -#ifdef SQLITE_DEBUG
  9650   9649   /*
  9651   9650   ** Return true if the cursor has a hint specified.  This routine is
  9652   9651   ** only used from within assert() statements
  9653   9652   */
  9654   9653   int sqlite3BtreeCursorHasHint(BtCursor *pCsr, unsigned int mask){
  9655   9654     return (pCsr->hints & mask)!=0;
  9656   9655   }
  9657         -#endif
  9658   9656   
  9659   9657   /*
  9660   9658   ** Return true if the given Btree is read-only.
  9661   9659   */
  9662   9660   int sqlite3BtreeIsReadonly(Btree *p){
  9663   9661     return (p->pBt->btsFlags & BTS_READ_ONLY)!=0;
  9664   9662   }
  9665   9663   
  9666   9664   /*
  9667   9665   ** Return the size of the header added to each page by this module.
  9668   9666   */
  9669   9667   int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); }

Changes to src/btree.h.

   253    253   char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
   254    254   struct Pager *sqlite3BtreePager(Btree*);
   255    255   
   256    256   int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
   257    257   void sqlite3BtreeIncrblobCursor(BtCursor *);
   258    258   void sqlite3BtreeClearCursor(BtCursor *);
   259    259   int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
   260         -#ifdef SQLITE_DEBUG
   261    260   int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask);
   262         -#endif
   263    261   int sqlite3BtreeIsReadonly(Btree *pBt);
   264    262   int sqlite3HeaderSizeBtree(void);
   265    263   
   266    264   #ifndef NDEBUG
   267    265   int sqlite3BtreeCursorIsValid(BtCursor*);
   268    266   #endif
   269    267   

Changes to src/btreeInt.h.

   513    513     i64 nKey;                 /* Size of pKey, or last integer key */
   514    514     void *pKey;               /* Saved key that was cursor last known position */
   515    515     Pgno pgnoRoot;            /* The root page of this tree */
   516    516     int nOvflAlloc;           /* Allocated size of aOverflow[] array */
   517    517     int skipNext;    /* Prev() is noop if negative. Next() is noop if positive.
   518    518                      ** Error code if eState==CURSOR_FAULT */
   519    519     u8 curFlags;              /* zero or more BTCF_* flags defined below */
   520         -  u8 curPagerFlags;         /* Flags to send to sqlite3PagerAcquire() */
          520  +  u8 curPagerFlags;         /* Flags to send to sqlite3PagerGet() */
   521    521     u8 eState;                /* One of the CURSOR_XXX constants (see below) */
   522    522     u8 hints;                 /* As configured by CursorSetHints() */
   523    523     /* All fields above are zeroed when the cursor is allocated.  See
   524    524     ** sqlite3BtreeCursorZero().  Fields that follow must be manually
   525    525     ** initialized. */
   526    526     i8 iPage;                 /* Index of current page in apPage */
   527    527     u8 curIntKey;             /* Value of apPage[0]->intKey */

Changes to src/dbstat.c.

   382    382             pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl);
   383    383             if( pCell->aOvfl==0 ) return SQLITE_NOMEM;
   384    384             pCell->aOvfl[0] = sqlite3Get4byte(&aData[iOff+nLocal]);
   385    385             for(j=1; j<nOvfl; j++){
   386    386               int rc;
   387    387               u32 iPrev = pCell->aOvfl[j-1];
   388    388               DbPage *pPg = 0;
   389         -            rc = sqlite3PagerGet(sqlite3BtreePager(pBt), iPrev, &pPg);
          389  +            rc = sqlite3PagerGet(sqlite3BtreePager(pBt), iPrev, &pPg, 0);
   390    390               if( rc!=SQLITE_OK ){
   391    391                 assert( pPg==0 );
   392    392                 return rc;
   393    393               } 
   394    394               pCell->aOvfl[j] = sqlite3Get4byte(sqlite3PagerGetData(pPg));
   395    395               sqlite3PagerUnref(pPg);
   396    396             }
................................................................................
   450    450         int nPage;
   451    451         u32 iRoot = (u32)sqlite3_column_int64(pCsr->pStmt, 1);
   452    452         sqlite3PagerPagecount(pPager, &nPage);
   453    453         if( nPage==0 ){
   454    454           pCsr->isEof = 1;
   455    455           return sqlite3_reset(pCsr->pStmt);
   456    456         }
   457         -      rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg);
          457  +      rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg, 0);
   458    458         pCsr->aPage[0].iPgno = iRoot;
   459    459         pCsr->aPage[0].iCell = 0;
   460    460         pCsr->aPage[0].zPath = z = sqlite3_mprintf("/");
   461    461         pCsr->iPage = 0;
   462    462         if( z==0 ) rc = SQLITE_NOMEM;
   463    463       }else{
   464    464         pCsr->isEof = 1;
................................................................................
   510    510       assert( p==&pCsr->aPage[pCsr->iPage-1] );
   511    511   
   512    512       if( p->iCell==p->nCell ){
   513    513         p[1].iPgno = p->iRightChildPg;
   514    514       }else{
   515    515         p[1].iPgno = p->aCell[p->iCell].iChildPg;
   516    516       }
   517         -    rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg);
          517  +    rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg, 0);
   518    518       p[1].iCell = 0;
   519    519       p[1].zPath = z = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell);
   520    520       p->iCell++;
   521    521       if( z==0 ) rc = SQLITE_NOMEM;
   522    522     }
   523    523   
   524    524   

Changes to src/pager.c.

  2329   2329       ** the data just read from the sub-journal. Mark the page as dirty 
  2330   2330       ** and if the pager requires a journal-sync, then mark the page as 
  2331   2331       ** requiring a journal-sync before it is written.
  2332   2332       */
  2333   2333       assert( isSavepnt );
  2334   2334       assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)==0 );
  2335   2335       pPager->doNotSpill |= SPILLFLAG_ROLLBACK;
  2336         -    rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1);
         2336  +    rc = sqlite3PagerGet(pPager, pgno, &pPg, 1);
  2337   2337       assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)!=0 );
  2338   2338       pPager->doNotSpill &= ~SPILLFLAG_ROLLBACK;
  2339   2339       if( rc!=SQLITE_OK ) return rc;
  2340   2340       pPg->flags &= ~PGHDR_NEED_READ;
  2341   2341       sqlite3PcacheMakeDirty(pPg);
  2342   2342     }
  2343   2343     if( pPg ){
................................................................................
  4965   4965     }
  4966   4966   
  4967   4967     return rc;
  4968   4968   }
  4969   4969   
  4970   4970   /*
  4971   4971   ** This function is called to obtain a shared lock on the database file.
  4972         -** It is illegal to call sqlite3PagerAcquire() until after this function
         4972  +** It is illegal to call sqlite3PagerGet() until after this function
  4973   4973   ** has been successfully called. If a shared-lock is already held when
  4974   4974   ** this function is called, it is a no-op.
  4975   4975   **
  4976   4976   ** The following operations are also performed by this function.
  4977   4977   **
  4978   4978   **   1) If the pager is currently in PAGER_OPEN state (no lock held
  4979   4979   **      on the database file), then an attempt is made to obtain a
................................................................................
  5268   5268   ** to find a page in the in-memory cache first.  If the page is not already
  5269   5269   ** in memory, this routine goes to disk to read it in whereas Lookup()
  5270   5270   ** just returns 0.  This routine acquires a read-lock the first time it
  5271   5271   ** has to go to disk, and could also playback an old journal if necessary.
  5272   5272   ** Since Lookup() never goes to disk, it never has to deal with locks
  5273   5273   ** or journal files.
  5274   5274   */
  5275         -int sqlite3PagerAcquire(
         5275  +int sqlite3PagerGet(
  5276   5276     Pager *pPager,      /* The pager open on the database file */
  5277   5277     Pgno pgno,          /* Page number to fetch */
  5278   5278     DbPage **ppPage,    /* Write a pointer to the page here */
  5279   5279     int flags           /* PAGER_GET_XXX flags */
  5280   5280   ){
  5281   5281     int rc = SQLITE_OK;
  5282   5282     PgHdr *pPg = 0;
................................................................................
  5854   5854     assert((pg1+nPage)>pPg->pgno);
  5855   5855   
  5856   5856     for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){
  5857   5857       Pgno pg = pg1+ii;
  5858   5858       PgHdr *pPage;
  5859   5859       if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){
  5860   5860         if( pg!=PAGER_MJ_PGNO(pPager) ){
  5861         -        rc = sqlite3PagerGet(pPager, pg, &pPage);
         5861  +        rc = sqlite3PagerGet(pPager, pg, &pPage, 0);
  5862   5862           if( rc==SQLITE_OK ){
  5863   5863             rc = pager_write(pPage);
  5864   5864             if( pPage->flags&PGHDR_NEED_SYNC ){
  5865   5865               needSync = 1;
  5866   5866             }
  5867   5867             sqlite3PagerUnrefNotNull(pPage);
  5868   5868           }
................................................................................
  6014   6014   
  6015   6015     if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){
  6016   6016       PgHdr *pPgHdr;                /* Reference to page 1 */
  6017   6017   
  6018   6018       assert( !pPager->tempFile && isOpen(pPager->fd) );
  6019   6019   
  6020   6020       /* Open page 1 of the file for writing. */
  6021         -    rc = sqlite3PagerGet(pPager, 1, &pPgHdr);
         6021  +    rc = sqlite3PagerGet(pPager, 1, &pPgHdr, 0);
  6022   6022       assert( pPgHdr==0 || rc==SQLITE_OK );
  6023   6023   
  6024   6024       /* If page one was fetched successfully, and this function is not
  6025   6025       ** operating in direct-mode, make page 1 writable.  When not in 
  6026   6026       ** direct mode, page 1 is always held in cache and hence the PagerGet()
  6027   6027       ** above is always successful - hence the ALWAYS on rc==SQLITE_OK.
  6028   6028       */
................................................................................
  6169   6169     }else{
  6170   6170       if( pagerUseWal(pPager) ){
  6171   6171         PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache);
  6172   6172         PgHdr *pPageOne = 0;
  6173   6173         if( pList==0 ){
  6174   6174           /* Must have at least one page for the WAL commit flag.
  6175   6175           ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */
  6176         -        rc = sqlite3PagerGet(pPager, 1, &pPageOne);
         6176  +        rc = sqlite3PagerGet(pPager, 1, &pPageOne, 0);
  6177   6177           pList = pPageOne;
  6178   6178           pList->pDirty = 0;
  6179   6179         }
  6180   6180         assert( rc==SQLITE_OK );
  6181   6181         if( ALWAYS(pList) ){
  6182   6182           rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1);
  6183   6183         }
................................................................................
  6874   6874       ** to a malloc() or IO failure), clear the bit in the pInJournal[]
  6875   6875       ** array. Otherwise, if the page is loaded and written again in
  6876   6876       ** this transaction, it may be written to the database file before
  6877   6877       ** it is synced into the journal file. This way, it may end up in
  6878   6878       ** the journal file twice, but that is not a problem.
  6879   6879       */
  6880   6880       PgHdr *pPgHdr;
  6881         -    rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr);
         6881  +    rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr, 0);
  6882   6882       if( rc!=SQLITE_OK ){
  6883   6883         if( needSyncPgno<=pPager->dbOrigSize ){
  6884   6884           assert( pPager->pTmpSpace!=0 );
  6885   6885           sqlite3BitvecClear(pPager->pInJournal, needSyncPgno, pPager->pTmpSpace);
  6886   6886         }
  6887   6887         return rc;
  6888   6888       }

Changes to src/pager.h.

    75     75   #define PAGER_JOURNALMODE_PERSIST     1   /* Commit by zeroing journal header */
    76     76   #define PAGER_JOURNALMODE_OFF         2   /* Journal omitted.  */
    77     77   #define PAGER_JOURNALMODE_TRUNCATE    3   /* Commit by truncating journal */
    78     78   #define PAGER_JOURNALMODE_MEMORY      4   /* In-memory journal file */
    79     79   #define PAGER_JOURNALMODE_WAL         5   /* Use write-ahead logging */
    80     80   
    81     81   /*
    82         -** Flags that make up the mask passed to sqlite3PagerAcquire().
           82  +** Flags that make up the mask passed to sqlite3PagerGet().
    83     83   */
    84     84   #define PAGER_GET_NOCONTENT     0x01  /* Do not load data from disk */
    85     85   #define PAGER_GET_READONLY      0x02  /* Read-only page is acceptable */
    86     86   
    87     87   /*
    88     88   ** Flags for sqlite3PagerSetFlags()
    89     89   */
................................................................................
   131    131   int sqlite3PagerGetJournalMode(Pager*);
   132    132   int sqlite3PagerOkToChangeJournalMode(Pager*);
   133    133   i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
   134    134   sqlite3_backup **sqlite3PagerBackupPtr(Pager*);
   135    135   int sqlite3PagerFlush(Pager*);
   136    136   
   137    137   /* Functions used to obtain and release page references. */ 
   138         -int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
   139         -#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0)
          138  +int sqlite3PagerGet(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
   140    139   DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
   141    140   void sqlite3PagerRef(DbPage*);
   142    141   void sqlite3PagerUnref(DbPage*);
   143    142   void sqlite3PagerUnrefNotNull(DbPage*);
   144    143   
   145    144   /* Operations on page references. */
   146    145   int sqlite3PagerWrite(DbPage*);

Changes to src/sqliteInt.h.

  1816   1816     u16 nXField;        /* Number of columns beyond the key columns */
  1817   1817     sqlite3 *db;        /* The database connection */
  1818   1818     u8 *aSortOrder;     /* Sort order for each column. */
  1819   1819     CollSeq *aColl[1];  /* Collating sequence for each term of the key */
  1820   1820   };
  1821   1821   
  1822   1822   /*
  1823         -** An instance of the following structure holds information about a
  1824         -** single index record that has already been parsed out into individual
  1825         -** values.
         1823  +** This object holds a record which has been parsed out into individual
         1824  +** fields, for the purposes of doing a comparison.
  1826   1825   **
  1827   1826   ** A record is an object that contains one or more fields of data.
  1828   1827   ** Records are used to store the content of a table row and to store
  1829   1828   ** the key of an index.  A blob encoding of a record is created by
  1830   1829   ** the OP_MakeRecord opcode of the VDBE and is disassembled by the
  1831   1830   ** OP_Column opcode.
  1832   1831   **
  1833         -** This structure holds a record that has already been disassembled
  1834         -** into its constituent fields.
         1832  +** An instance of this object serves as a "key" for doing a search on
         1833  +** an index b+tree. The goal of the search is to find the entry that
         1834  +** is closed to the key described by this object.  This object might hold
         1835  +** just a prefix of the key.  The number of fields is given by
         1836  +** pKeyInfo->nField.
  1835   1837   **
  1836         -** The r1 and r2 member variables are only used by the optimized comparison
  1837         -** functions vdbeRecordCompareInt() and vdbeRecordCompareString().
         1838  +** The r1 and r2 fields are the values to return if this key is less than
         1839  +** or greater than a key in the btree, respectively.  These are normally
         1840  +** -1 and +1 respectively, but might be inverted to +1 and -1 if the b-tree
         1841  +** is in DESC order.
         1842  +**
         1843  +** The key comparison functions actually return default_rc when they find
         1844  +** an equals comparison.  default_rc can be -1, 0, or +1.  If there are
         1845  +** multiple entries in the b-tree with the same key (when only looking
         1846  +** at the first pKeyInfo->nFields,) then default_rc can be set to -1 to 
         1847  +** cause the search to find the last match, or +1 to cause the search to
         1848  +** find the first match.
         1849  +**
         1850  +** The key comparison functions will set eqSeen to true if they ever
         1851  +** get and equal results when comparing this structure to a b-tree record.
         1852  +** When default_rc!=0, the search might end up on the record immediately
         1853  +** before the first match or immediately after the last match.  The
         1854  +** eqSeen field will indicate whether or not an exact match exists in the
         1855  +** b-tree.
  1838   1856   */
  1839   1857   struct UnpackedRecord {
  1840   1858     KeyInfo *pKeyInfo;  /* Collation and sort-order information */
         1859  +  Mem *aMem;          /* Values */
  1841   1860     u16 nField;         /* Number of entries in apMem[] */
  1842   1861     i8 default_rc;      /* Comparison result if keys are equal */
  1843   1862     u8 errCode;         /* Error detected by xRecordCompare (CORRUPT or NOMEM) */
  1844         -  Mem *aMem;          /* Values */
  1845         -  int r1;             /* Value to return if (lhs > rhs) */
  1846         -  int r2;             /* Value to return if (rhs < lhs) */
         1863  +  i8 r1;              /* Value to return if (lhs > rhs) */
         1864  +  i8 r2;              /* Value to return if (rhs < lhs) */
         1865  +  u8 eqSeen;          /* True if an equality comparison has been seen */
  1847   1866   };
  1848   1867   
  1849   1868   
  1850   1869   /*
  1851   1870   ** Each SQL index is represented in memory by an
  1852   1871   ** instance of the following structure.
  1853   1872   **

Changes to src/test1.c.

  7035   7035   #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
  7036   7036        { "sqlite3_stmt_scanstatus",       test_stmt_scanstatus,   0 },
  7037   7037        { "sqlite3_stmt_scanstatus_reset", test_stmt_scanstatus_reset,   0 },
  7038   7038   #endif
  7039   7039   
  7040   7040     };
  7041   7041     static int bitmask_size = sizeof(Bitmask)*8;
         7042  +  static int longdouble_size = sizeof(LONGDOUBLE_TYPE);
  7042   7043     int i;
  7043   7044     extern int sqlite3_sync_count, sqlite3_fullsync_count;
  7044   7045     extern int sqlite3_opentemp_count;
  7045   7046     extern int sqlite3_like_count;
  7046   7047     extern int sqlite3_xferopt_count;
  7047   7048     extern int sqlite3_pager_readdb_count;
  7048   7049     extern int sqlite3_pager_writedb_count;
................................................................................
  7135   7136         (char*)&sqlite_static_bind_nbyte, TCL_LINK_INT);
  7136   7137     Tcl_LinkVar(interp, "sqlite_temp_directory",
  7137   7138         (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
  7138   7139     Tcl_LinkVar(interp, "sqlite_data_directory",
  7139   7140         (char*)&sqlite3_data_directory, TCL_LINK_STRING);
  7140   7141     Tcl_LinkVar(interp, "bitmask_size",
  7141   7142         (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
         7143  +  Tcl_LinkVar(interp, "longdouble_size",
         7144  +      (char*)&longdouble_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
  7142   7145     Tcl_LinkVar(interp, "sqlite_sync_count",
  7143   7146         (char*)&sqlite3_sync_count, TCL_LINK_INT);
  7144   7147     Tcl_LinkVar(interp, "sqlite_fullsync_count",
  7145   7148         (char*)&sqlite3_fullsync_count, TCL_LINK_INT);
  7146   7149   #if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_TEST)
  7147   7150     Tcl_LinkVar(interp, "sqlite_fts3_enable_parentheses",
  7148   7151         (char*)&sqlite3_fts3_enable_parentheses, TCL_LINK_INT);
  7149   7152   #endif
  7150   7153     return TCL_OK;
  7151   7154   }

Changes to src/test2.c.

   318    318          " ID PGNO\"", 0);
   319    319       return TCL_ERROR;
   320    320     }
   321    321     pPager = sqlite3TestTextToPtr(argv[1]);
   322    322     if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
   323    323     rc = sqlite3PagerSharedLock(pPager);
   324    324     if( rc==SQLITE_OK ){
   325         -    rc = sqlite3PagerGet(pPager, pgno, &pPage);
          325  +    rc = sqlite3PagerGet(pPager, pgno, &pPage, 0);
   326    326     }
   327    327     if( rc!=SQLITE_OK ){
   328    328       Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
   329    329       return TCL_ERROR;
   330    330     }
   331    331     sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage);
   332    332     Tcl_AppendResult(interp, zBuf, 0);

Changes to src/vdbe.c.

  3602   3602   ** use the value in register P3 as the key.  If cursor P1 refers 
  3603   3603   ** to an SQL index, then P3 is the first in an array of P4 registers 
  3604   3604   ** that are used as an unpacked index key. 
  3605   3605   **
  3606   3606   ** Reposition cursor P1 so that  it points to the smallest entry that 
  3607   3607   ** is greater than or equal to the key value. If there are no records 
  3608   3608   ** greater than or equal to the key and P2 is not zero, then jump to P2.
         3609  +**
         3610  +** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this
         3611  +** opcode will always land on a record that equally equals the key, or
         3612  +** else jump immediately to P2.  When the cursor is OPFLAG_SEEKEQ, this
         3613  +** opcode must be followed by an IdxLE opcode with the same arguments.
         3614  +** The IdxLE opcode will be skipped if this opcode succeeds, but the
         3615  +** IdxLE opcode will be used on subsequent loop iterations.
  3609   3616   **
  3610   3617   ** This opcode leaves the cursor configured to move in forward order,
  3611   3618   ** from the beginning toward the end.  In other words, the cursor is
  3612   3619   ** configured to use Next, not Prev.
  3613   3620   **
  3614   3621   ** See also: Found, NotFound, SeekLt, SeekGt, SeekLe
  3615   3622   */
................................................................................
  3661   3668   ** is less than or equal to the key value. If there are no records 
  3662   3669   ** less than or equal to the key and P2 is not zero, then jump to P2.
  3663   3670   **
  3664   3671   ** This opcode leaves the cursor configured to move in reverse order,
  3665   3672   ** from the end toward the beginning.  In other words, the cursor is
  3666   3673   ** configured to use Prev, not Next.
  3667   3674   **
         3675  +** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this
         3676  +** opcode will always land on a record that equally equals the key, or
         3677  +** else jump immediately to P2.  When the cursor is OPFLAG_SEEKEQ, this
         3678  +** opcode must be followed by an IdxGE opcode with the same arguments.
         3679  +** The IdxGE opcode will be skipped if this opcode succeeds, but the
         3680  +** IdxGE opcode will be used on subsequent loop iterations.
         3681  +**
  3668   3682   ** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
  3669   3683   */
  3670   3684   case OP_SeekLT:         /* jump, in3 */
  3671   3685   case OP_SeekLE:         /* jump, in3 */
  3672   3686   case OP_SeekGE:         /* jump, in3 */
  3673   3687   case OP_SeekGT: {       /* jump, in3 */
  3674         -  int res;
  3675         -  int oc;
  3676         -  VdbeCursor *pC;
  3677         -  UnpackedRecord r;
  3678         -  int nField;
  3679         -  i64 iKey;      /* The rowid we are to seek to */
         3688  +  int res;           /* Comparison result */
         3689  +  int oc;            /* Opcode */
         3690  +  VdbeCursor *pC;    /* The cursor to seek */
         3691  +  UnpackedRecord r;  /* The key to seek for */
         3692  +  int nField;        /* Number of columns or fields in the key */
         3693  +  i64 iKey;          /* The rowid we are to seek to */
         3694  +  int eqOnly;        /* Only interested in == results */
  3680   3695   
  3681   3696     assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  3682   3697     assert( pOp->p2!=0 );
  3683   3698     pC = p->apCsr[pOp->p1];
  3684   3699     assert( pC!=0 );
  3685   3700     assert( pC->pseudoTableReg==0 );
  3686   3701     assert( OP_SeekLE == OP_SeekLT+1 );
  3687   3702     assert( OP_SeekGE == OP_SeekLT+2 );
  3688   3703     assert( OP_SeekGT == OP_SeekLT+3 );
  3689   3704     assert( pC->isOrdered );
  3690   3705     assert( pC->pCursor!=0 );
  3691   3706     oc = pOp->opcode;
         3707  +  eqOnly = 0;
  3692   3708     pC->nullRow = 0;
  3693   3709   #ifdef SQLITE_DEBUG
  3694   3710     pC->seekOp = pOp->opcode;
  3695   3711   #endif
  3696   3712   
  3697         -  /* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and
  3698         -  ** OP_SeekLE opcodes are allowed, and these must be immediately followed
  3699         -  ** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key.
  3700         -  */
  3701         -#ifdef SQLITE_DEBUG
  3702         -  if( sqlite3BtreeCursorHasHint(pC->pCursor, BTREE_SEEK_EQ) ){
  3703         -    assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE );
  3704         -    assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
  3705         -    assert( pOp[1].p1==pOp[0].p1 );
  3706         -    assert( pOp[1].p2==pOp[0].p2 );
  3707         -    assert( pOp[1].p3==pOp[0].p3 );
  3708         -    assert( pOp[1].p4.i==pOp[0].p4.i );
  3709         -  }
  3710         -#endif
  3711         - 
  3712   3713     if( pC->isTable ){
         3714  +    /* The BTREE_SEEK_EQ flag is only set on index cursors */
         3715  +    assert( sqlite3BtreeCursorHasHint(pC->pCursor, BTREE_SEEK_EQ)==0 );
         3716  +
  3713   3717       /* The input value in P3 might be of any type: integer, real, string,
  3714   3718       ** blob, or NULL.  But it needs to be an integer before we can do
  3715   3719       ** the seek, so convert it. */
  3716   3720       pIn3 = &aMem[pOp->p3];
  3717   3721       if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
  3718   3722         applyNumericAffinity(pIn3, 0);
  3719   3723       }
................................................................................
  3754   3758       } 
  3755   3759       rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res);
  3756   3760       pC->movetoTarget = iKey;  /* Used by OP_Delete */
  3757   3761       if( rc!=SQLITE_OK ){
  3758   3762         goto abort_due_to_error;
  3759   3763       }
  3760   3764     }else{
         3765  +    /* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and
         3766  +    ** OP_SeekLE opcodes are allowed, and these must be immediately followed
         3767  +    ** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key.
         3768  +    */
         3769  +    if( sqlite3BtreeCursorHasHint(pC->pCursor, BTREE_SEEK_EQ) ){
         3770  +      eqOnly = 1;
         3771  +      assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE );
         3772  +      assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
         3773  +      assert( pOp[1].p1==pOp[0].p1 );
         3774  +      assert( pOp[1].p2==pOp[0].p2 );
         3775  +      assert( pOp[1].p3==pOp[0].p3 );
         3776  +      assert( pOp[1].p4.i==pOp[0].p4.i );
         3777  +    }
         3778  +
  3761   3779       nField = pOp->p4.i;
  3762   3780       assert( pOp->p4type==P4_INT32 );
  3763   3781       assert( nField>0 );
  3764   3782       r.pKeyInfo = pC->pKeyInfo;
  3765   3783       r.nField = (u16)nField;
  3766   3784   
  3767   3785       /* The next line of code computes as follows, only faster:
................................................................................
  3778   3796       assert( oc!=OP_SeekLT || r.default_rc==+1 );
  3779   3797   
  3780   3798       r.aMem = &aMem[pOp->p3];
  3781   3799   #ifdef SQLITE_DEBUG
  3782   3800       { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
  3783   3801   #endif
  3784   3802       ExpandBlob(r.aMem);
         3803  +    r.eqSeen = 0;
  3785   3804       rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, &r, 0, 0, &res);
  3786   3805       if( rc!=SQLITE_OK ){
  3787   3806         goto abort_due_to_error;
         3807  +    }
         3808  +    if( eqOnly && r.eqSeen==0 ){
         3809  +      assert( res!=0 );
         3810  +      goto seek_not_found;
  3788   3811       }
  3789   3812     }
  3790   3813     pC->deferredMoveto = 0;
  3791   3814     pC->cacheStatus = CACHE_STALE;
  3792   3815   #ifdef SQLITE_TEST
  3793   3816     sqlite3_search_count++;
  3794   3817   #endif
................................................................................
  3809   3832       }else{
  3810   3833         /* res might be negative because the table is empty.  Check to
  3811   3834         ** see if this is the case.
  3812   3835         */
  3813   3836         res = sqlite3BtreeEof(pC->pCursor);
  3814   3837       }
  3815   3838     }
         3839  +seek_not_found:
  3816   3840     assert( pOp->p2>0 );
  3817   3841     VdbeBranchTaken(res!=0,2);
  3818   3842     if( res ){
  3819   3843       goto jump_to_p2;
         3844  +  }else if( eqOnly ){
         3845  +    assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
         3846  +    pOp++; /* Skip the OP_IdxLt or OP_IdxGT that follows */
  3820   3847     }
  3821   3848     break;
  3822   3849   }
  3823   3850   
  3824   3851   /* Opcode: Seek P1 P2 * * *
  3825   3852   ** Synopsis:  intkey=r[P2]
  3826   3853   **

Changes to src/vdbeaux.c.

  3316   3316         testcase( pMem->u.i<0 );
  3317   3317         return 3;
  3318   3318       }
  3319   3319       case 4: { /* 4-byte signed integer */
  3320   3320         /* EVIDENCE-OF: R-01849-26079 Value is a big-endian 32-bit
  3321   3321         ** twos-complement integer. */
  3322   3322         pMem->u.i = FOUR_BYTE_INT(buf);
         3323  +#ifdef __HP_cc 
         3324  +      /* Work around a sign-extension bug in the HP compiler for HP/UX */
         3325  +      if( buf[0]&0x80 ) pMem->u.i |= 0xffffffff80000000LL;
         3326  +#endif
  3323   3327         pMem->flags = MEM_Int;
  3324   3328         testcase( pMem->u.i<0 );
  3325   3329         return 4;
  3326   3330       }
  3327   3331       case 5: { /* 6-byte signed integer */
  3328   3332         /* EVIDENCE-OF: R-50385-09674 Value is a big-endian 48-bit
  3329   3333         ** twos-complement integer. */
................................................................................
  3632   3636   */
  3633   3637   static SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){
  3634   3638     int c = memcmp(pB1->z, pB2->z, pB1->n>pB2->n ? pB2->n : pB1->n);
  3635   3639     if( c ) return c;
  3636   3640     return pB1->n - pB2->n;
  3637   3641   }
  3638   3642   
         3643  +/*
         3644  +** Do a comparison between a 64-bit signed integer and a 64-bit floating-point
         3645  +** number.  Return negative, zero, or positive if the first (i64) is less than,
         3646  +** equal to, or greater than the second (double).
         3647  +*/
         3648  +static int sqlite3IntFloatCompare(i64 i, double r){
         3649  +  if( sizeof(LONGDOUBLE_TYPE)>8 ){
         3650  +    LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i;
         3651  +    if( x<r ) return -1;
         3652  +    if( x>r ) return +1;
         3653  +    return 0;
         3654  +  }else{
         3655  +    i64 y;
         3656  +    double s;
         3657  +    if( r<-9223372036854775808.0 ) return +1;
         3658  +    if( r>9223372036854775807.0 ) return -1;
         3659  +    y = (i64)r;
         3660  +    if( i<y ) return -1;
         3661  +    if( i>y ){
         3662  +      if( y==SMALLEST_INT64 && r>0.0 ) return -1;
         3663  +      return +1;
         3664  +    }
         3665  +    s = (double)i;
         3666  +    if( s<r ) return -1;
         3667  +    if( s>r ) return +1;
         3668  +    return 0;
         3669  +  }
         3670  +}
  3639   3671   
  3640   3672   /*
  3641   3673   ** Compare the values contained by the two memory cells, returning
  3642   3674   ** negative, zero or positive if pMem1 is less than, equal to, or greater
  3643   3675   ** than pMem2. Sorting order is NULL's first, followed by numbers (integers
  3644   3676   ** and reals) sorted numerically, followed by text ordered by the collating
  3645   3677   ** sequence pColl and finally blob's ordered by memcmp().
................................................................................
  3658   3690     /* If one value is NULL, it is less than the other. If both values
  3659   3691     ** are NULL, return 0.
  3660   3692     */
  3661   3693     if( combined_flags&MEM_Null ){
  3662   3694       return (f2&MEM_Null) - (f1&MEM_Null);
  3663   3695     }
  3664   3696   
  3665         -  /* If one value is a number and the other is not, the number is less.
  3666         -  ** If both are numbers, compare as reals if one is a real, or as integers
  3667         -  ** if both values are integers.
         3697  +  /* At least one of the two values is a number
  3668   3698     */
  3669   3699     if( combined_flags&(MEM_Int|MEM_Real) ){
  3670         -    double r1, r2;
  3671   3700       if( (f1 & f2 & MEM_Int)!=0 ){
  3672   3701         if( pMem1->u.i < pMem2->u.i ) return -1;
  3673         -      if( pMem1->u.i > pMem2->u.i ) return 1;
         3702  +      if( pMem1->u.i > pMem2->u.i ) return +1;
         3703  +      return 0;
         3704  +    }
         3705  +    if( (f1 & f2 & MEM_Real)!=0 ){
         3706  +      if( pMem1->u.r < pMem2->u.r ) return -1;
         3707  +      if( pMem1->u.r > pMem2->u.r ) return +1;
  3674   3708         return 0;
         3709  +    }
         3710  +    if( (f1&MEM_Int)!=0 ){
         3711  +      if( (f2&MEM_Real)!=0 ){
         3712  +        return sqlite3IntFloatCompare(pMem1->u.i, pMem2->u.r);
         3713  +      }else{
         3714  +        return -1;
         3715  +      }
  3675   3716       }
  3676   3717       if( (f1&MEM_Real)!=0 ){
  3677         -      r1 = pMem1->u.r;
  3678         -    }else if( (f1&MEM_Int)!=0 ){
  3679         -      r1 = (double)pMem1->u.i;
  3680         -    }else{
  3681         -      return 1;
         3718  +      if( (f2&MEM_Int)!=0 ){
         3719  +        return -sqlite3IntFloatCompare(pMem2->u.i, pMem1->u.r);
         3720  +      }else{
         3721  +        return -1;
         3722  +      }
  3682   3723       }
  3683         -    if( (f2&MEM_Real)!=0 ){
  3684         -      r2 = pMem2->u.r;
  3685         -    }else if( (f2&MEM_Int)!=0 ){
  3686         -      r2 = (double)pMem2->u.i;
  3687         -    }else{
  3688         -      return -1;
  3689         -    }
  3690         -    if( r1<r2 ) return -1;
  3691         -    if( r1>r2 ) return 1;
  3692         -    return 0;
         3724  +    return +1;
  3693   3725     }
  3694   3726   
  3695   3727     /* If one value is a string and the other is a blob, the string is less.
  3696   3728     ** If both are strings, compare using the collating functions.
  3697   3729     */
  3698   3730     if( combined_flags&MEM_Str ){
  3699   3731       if( (f1 & MEM_Str)==0 ){
................................................................................
  3836   3868         serial_type = aKey1[idx1];
  3837   3869         testcase( serial_type==12 );
  3838   3870         if( serial_type>=10 ){
  3839   3871           rc = +1;
  3840   3872         }else if( serial_type==0 ){
  3841   3873           rc = -1;
  3842   3874         }else if( serial_type==7 ){
  3843         -        double rhs = (double)pRhs->u.i;
  3844   3875           sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
  3845         -        if( mem1.u.r<rhs ){
  3846         -          rc = -1;
  3847         -        }else if( mem1.u.r>rhs ){
  3848         -          rc = +1;
  3849         -        }
         3876  +        rc = -sqlite3IntFloatCompare(pRhs->u.i, mem1.u.r);
  3850   3877         }else{
  3851   3878           i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]);
  3852   3879           i64 rhs = pRhs->u.i;
  3853   3880           if( lhs<rhs ){
  3854   3881             rc = -1;
  3855   3882           }else if( lhs>rhs ){
  3856   3883             rc = +1;
................................................................................
  3866   3893           ** numbers). Types 10 and 11 are currently "reserved for future 
  3867   3894           ** use", so it doesn't really matter what the results of comparing
  3868   3895           ** them to numberic values are.  */
  3869   3896           rc = +1;
  3870   3897         }else if( serial_type==0 ){
  3871   3898           rc = -1;
  3872   3899         }else{
  3873         -        double rhs = pRhs->u.r;
  3874         -        double lhs;
  3875   3900           sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
  3876   3901           if( serial_type==7 ){
  3877         -          lhs = mem1.u.r;
         3902  +          if( mem1.u.r<pRhs->u.r ){
         3903  +            rc = -1;
         3904  +          }else if( mem1.u.r>pRhs->u.r ){
         3905  +            rc = +1;
         3906  +          }
  3878   3907           }else{
  3879         -          lhs = (double)mem1.u.i;
  3880         -        }
  3881         -        if( lhs<rhs ){
  3882         -          rc = -1;
  3883         -        }else if( lhs>rhs ){
  3884         -          rc = +1;
         3908  +          rc = sqlite3IntFloatCompare(mem1.u.i, pRhs->u.r);
  3885   3909           }
  3886   3910         }
  3887   3911       }
  3888   3912   
  3889   3913       /* RHS is a string */
  3890   3914       else if( pRhs->flags & MEM_Str ){
  3891   3915         getVarint32(&aKey1[idx1], serial_type);
................................................................................
  3967   3991     /* rc==0 here means that one or both of the keys ran out of fields and
  3968   3992     ** all the fields up to that point were equal. Return the default_rc
  3969   3993     ** value.  */
  3970   3994     assert( CORRUPT_DB 
  3971   3995          || vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, pPKey2->default_rc) 
  3972   3996          || pKeyInfo->db->mallocFailed
  3973   3997     );
         3998  +  pPKey2->eqSeen = 1;
  3974   3999     return pPKey2->default_rc;
  3975   4000   }
  3976   4001   int sqlite3VdbeRecordCompare(
  3977   4002     int nKey1, const void *pKey1,   /* Left key */
  3978   4003     UnpackedRecord *pPKey2          /* Right key */
  3979   4004   ){
  3980   4005     return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0);
................................................................................
  4066   4091       /* The first fields of the two keys are equal. Compare the trailing 
  4067   4092       ** fields.  */
  4068   4093       res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
  4069   4094     }else{
  4070   4095       /* The first fields of the two keys are equal and there are no trailing
  4071   4096       ** fields. Return pPKey2->default_rc in this case. */
  4072   4097       res = pPKey2->default_rc;
         4098  +    pPKey2->eqSeen = 1;
  4073   4099     }
  4074   4100   
  4075   4101     assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, res) );
  4076   4102     return res;
  4077   4103   }
  4078   4104   
  4079   4105   /*
................................................................................
  4086   4112     int nKey1, const void *pKey1, /* Left key */
  4087   4113     UnpackedRecord *pPKey2        /* Right key */
  4088   4114   ){
  4089   4115     const u8 *aKey1 = (const u8*)pKey1;
  4090   4116     int serial_type;
  4091   4117     int res;
  4092   4118   
         4119  +  assert( pPKey2->aMem[0].flags & MEM_Str );
  4093   4120     vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo);
  4094   4121     getVarint32(&aKey1[1], serial_type);
  4095   4122     if( serial_type<12 ){
  4096   4123       res = pPKey2->r1;      /* (pKey1/nKey1) is a number or a null */
  4097   4124     }else if( !(serial_type & 0x01) ){ 
  4098   4125       res = pPKey2->r2;      /* (pKey1/nKey1) is a blob */
  4099   4126     }else{
................................................................................
  4112   4139       if( res==0 ){
  4113   4140         res = nStr - pPKey2->aMem[0].n;
  4114   4141         if( res==0 ){
  4115   4142           if( pPKey2->nField>1 ){
  4116   4143             res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
  4117   4144           }else{
  4118   4145             res = pPKey2->default_rc;
         4146  +          pPKey2->eqSeen = 1;
  4119   4147           }
  4120   4148         }else if( res>0 ){
  4121   4149           res = pPKey2->r2;
  4122   4150         }else{
  4123   4151           res = pPKey2->r1;
  4124   4152         }
  4125   4153       }else if( res>0 ){

Changes to test/atof1.test.

    11     11   # 
    12     12   # Tests of the sqlite3AtoF() function.
    13     13   #
    14     14   
    15     15   set testdir [file dirname $argv0]
    16     16   source $testdir/tester.tcl
    17     17   
    18         -if {![info exists __GNUC__] || [regexp arm $tcl_platform(machine)]} {
           18  +if {$::longdouble_size<=8} {
    19     19     finish_test
    20     20     return
    21     21   }
    22     22   
    23     23   expr srand(1)
    24     24   for {set i 1} {$i<20000} {incr i} {
    25     25     set pow [expr {int((rand()-0.5)*100)}]

Changes to test/bc_common.tcl.

     3      3   
     4      4   proc bc_find_binaries {zCaption} {
     5      5     # Search for binaries to test against. Any executable files that match
     6      6     # our naming convention are assumed to be testfixture binaries to test
     7      7     # against.
     8      8     #
     9      9     set binaries [list]
    10         -  set pattern "[file tail [info nameofexec]]?*"
           10  +  set self [file tail [info nameofexec]]
           11  +  set pattern "$self?*"
    11     12     if {$::tcl_platform(platform)=="windows"} {
    12     13       set pattern [string map {\.exe {}} $pattern]
    13     14     }
    14     15     foreach file [glob -nocomplain $pattern] {
           16  +    if {$file==$self} continue
    15     17       if {[file executable $file] && [file isfile $file]} {lappend binaries $file}
    16     18     }
    17     19   
    18     20     if {[llength $binaries]==0} {
    19     21       puts "WARNING: No historical binaries to test against."
    20     22       puts "WARNING: Omitting backwards-compatibility tests"
    21     23     }

Changes to test/collate4.test.

   348    348   do_test collate4-2.1.2 {
   349    349     execsql {
   350    350       CREATE INDEX collate4i1 ON collate4t1(a);
   351    351     }
   352    352     count {
   353    353       SELECT * FROM collate4t2, collate4t1 WHERE a = b;
   354    354     }
   355         -} {A a A A 5}
          355  +} {A a A A 4}
   356    356   do_test collate4-2.1.3 {
   357    357     count {
   358    358       SELECT * FROM collate4t2, collate4t1 WHERE b = a;
   359    359     }
   360    360   } {A A 19}
   361    361   do_test collate4-2.1.4 {
   362    362     execsql {
................................................................................
   368    368        ORDER BY collate4t2.rowid, collate4t1.rowid
   369    369     }
   370    370   } {A a A A 19}
   371    371   do_test collate4-2.1.5 {
   372    372     count {
   373    373       SELECT * FROM collate4t2, collate4t1 WHERE b = a;
   374    374     }
   375         -} {A A 4}
          375  +} {A A 3}
   376    376   ifcapable subquery {
   377    377     do_test collate4-2.1.6 {
   378    378       count {
   379    379         SELECT a FROM collate4t1 WHERE a IN (SELECT * FROM collate4t2)
   380    380          ORDER BY rowid
   381    381       }
   382    382     } {a A 10}
................................................................................
   385    385         DROP INDEX collate4i1;
   386    386         CREATE INDEX collate4i1 ON collate4t1(a);
   387    387       }
   388    388       count {
   389    389         SELECT a FROM collate4t1 WHERE a IN (SELECT * FROM collate4t2)
   390    390          ORDER BY rowid
   391    391       }
   392         -  } {a A 6}
          392  +  } {a A 5}
   393    393     do_test collate4-2.1.8 {
   394    394       count {
   395    395         SELECT a FROM collate4t1 WHERE a IN ('z', 'a');
   396    396       }
   397         -  } {a A 5}
          397  +  } {a A 4}
   398    398     do_test collate4-2.1.9 {
   399    399       execsql {
   400    400         DROP INDEX collate4i1;
   401    401         CREATE INDEX collate4i1 ON collate4t1(a COLLATE TEXT);
   402    402       }
   403    403       count {
   404    404         SELECT a FROM collate4t1 WHERE a IN ('z', 'a') ORDER BY rowid;

Changes to test/e_uri.test.

    22     22     tvfs filter xOpen
    23     23     tvfs script parse_uri_open_cb
    24     24   
    25     25     set ::uri_open [list]
    26     26     set DB [sqlite3_open_v2 $uri {
    27     27       SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_WAL
    28     28     } tvfs]
           29  +  set fileName [sqlite3_db_filename $DB main]
    29     30     sqlite3_close $DB
           31  +  forcedelete $fileName
    30     32     tvfs delete
    31     33     tvfs2 delete
    32     34   
    33     35     set ::uri_open
    34     36   }
    35     37   proc parse_uri_open_cb {method file arglist} {
    36     38     set ::uri_open [list $file $arglist]

Added test/ieee754.test.

            1  +# 2015-11-06
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +# 
           12  +# Tests of the iee754 extension
           13  +#
           14  +
           15  +set testdir [file dirname $argv0]
           16  +source $testdir/tester.tcl
           17  +
           18  +load_static_extension db ieee754
           19  +
           20  +foreach {id float rep} {
           21  +   1       1.0                            1,0
           22  +   2       2.0                            2,0
           23  +   3       0.5                            1,-1
           24  +   4       1.5                            3,-1
           25  +   5       0.0                            0,-1075
           26  +   6       4.9406564584124654e-324        4503599627370497,-1075
           27  +   7       2.2250738585072009e-308        9007199254740991,-1075
           28  +   8       2.2250738585072014e-308        1,-1022
           29  +} {
           30  +  do_test ieee754-100-$id-1 {
           31  +    db eval "SELECT ieee754($float);"
           32  +  } "ieee754($rep)"
           33  +  do_test ieee754-100-$id-2 {
           34  +    db eval "SELECT ieee754($rep)==$float;"
           35  +  } {1}
           36  +  if {$float!=0.0} {
           37  +    do_test ieee754-100-$id-3 {
           38  +      db eval "SELECT ieee754(-$float);"
           39  +    } "ieee754(-$rep)"
           40  +    do_test ieee754-100-$id-4 {
           41  +      db eval "SELECT ieee754(-$rep)==-$float;"
           42  +    } {1}
           43  +  }
           44  +}
           45  +
           46  +do_execsql_test ieee754-110 {
           47  +  SELECT ieee754(1,1024), ieee754(4503599627370495,972);
           48  +} {Inf 1.79769313486232e+308}
           49  +do_execsql_test ieee754-111 {
           50  +  SELECT ieee754(-1,1024), ieee754(-4503599627370495,972);
           51  +} {-Inf -1.79769313486232e+308}
           52  +do_execsql_test ieee754-112 {
           53  +  SELECT ieee754(4503599627370495,973) is null;
           54  +} {1}
           55  +
           56  +finish_test

Added test/numindex1.test.

            1  +# 2015-11-05
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +# This file implements tests for indexes on large numeric values.
           12  +#
           13  +
           14  +set testdir [file dirname $argv0]
           15  +source $testdir/tester.tcl
           16  +
           17  +
           18  +# Test cases from Zsb√°n Ambrus:
           19  +#
           20  +do_execsql_test numindex1-1.1 {
           21  +  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
           22  +  CREATE INDEX t1b ON t1(b);
           23  +  INSERT INTO t1(a,b) VALUES(100, 356282677878746339);
           24  +  INSERT INTO t1(a,b) VALUES(50, 356282677878746339.0);
           25  +  INSERT INTO t1(a,b) VALUES(0, 356282677878746340);
           26  +  DELETE FROM t1 WHERE a=50;
           27  +  PRAGMA integrity_check;
           28  +} {ok}
           29  +
           30  +do_execsql_test numindex1-1.2 {
           31  +  CREATE TABLE t2(a,b);
           32  +  INSERT INTO t2(a,b) VALUES('b', 1<<58),
           33  +      ('c', (1<<58)+1e-7), ('d', (1<<58)+1);
           34  +  SELECT a, b, typeof(b), '|' FROM t2 ORDER BY +a;
           35  +} {b 288230376151711744 integer | c 2.88230376151712e+17 real | d 288230376151711745 integer |}
           36  +
           37  +do_execsql_test numindex1-1.3 {
           38  +  SELECT x.a || CASE WHEN x.b==y.b THEN '==' ELSE '<>' END || y.a
           39  +    FROM t2 AS x, t2 AS y
           40  +   ORDER BY +x.a, +x.b;
           41  +} {b==b b==c b<>d c==b c==c c<>d d<>b d<>c d==d}
           42  +
           43  +# New test cases
           44  +#
           45  +do_execsql_test numindex1-2.1 {
           46  +  DROP TABLE IF EXISTS t1;
           47  +  CREATE TABLE t1(a INTEGER PRIMARY KEY,b);
           48  +  CREATE INDEX t1b ON t1(b);
           49  +  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
           50  +  INSERT INTO t1(a,b) SELECT x, 10000000000000004.0 FROM c
           51  +   WHERE x NOT IN (23,37);
           52  +  INSERT INTO t1(a,b) VALUES(23,10000000000000005);
           53  +  INSERT INTO t1(a,b) VALUES(37,10000000000000003);
           54  +  DELETE FROM t1 WHERE a NOT IN (23,37);
           55  +  PRAGMA integrity_check;
           56  +} {ok}
           57  +
           58  +do_execsql_test numindex1-3.1 {
           59  +  DROP TABLE IF EXISTS t1;
           60  +  CREATE TABLE t1(a INTEGER PRIMARY KEY,b);
           61  +  CREATE INDEX t1b ON t1(b);
           62  +  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<20)
           63  +  INSERT INTO t1(a,b) SELECT x, 100000000000000005.0
           64  +    FROM c WHERE x NOT IN (3,5,7,11,13,17,19);
           65  +  INSERT INTO t1(a,b) VALUES(3,100000000000000005);
           66  +  INSERT INTO t1(a,b) VALUES(5,100000000000000000);
           67  +  INSERT INTO t1(a,b) VALUES(7,100000000000000008);
           68  +  INSERT INTO t1(a,b) VALUES(11,100000000000000006);
           69  +  INSERT INTO t1(a,b) VALUES(13,100000000000000001);
           70  +  INSERT INTO t1(a,b) VALUES(17,100000000000000004);
           71  +  INSERT INTO t1(a,b) VALUES(19,100000000000000003);
           72  +  PRAGMA integrity_check;
           73  +} {ok}
           74  +
           75  +do_execsql_test numindex1-3.2 {
           76  +  SELECT a FROM t1 ORDER BY b;
           77  +} {1 2 4 5 6 8 9 10 12 14 15 16 18 20 13 19 17 3 11 7}
           78  +
           79  +finish_test

Changes to test/permutations.test.

   178    178   
   179    179   test_suite "valgrind" -prefix "" -description {
   180    180     Run the "veryquick" test suite with a couple of multi-process tests (that
   181    181     fail under valgrind) omitted.
   182    182   } -files [
   183    183     test_set $allquicktests -exclude *malloc* *ioerr* *fault* wal.test \
   184    184                 shell*.test crash8.test atof1.test selectG.test \
   185         -              tkt-fc62af4523.test
          185  +              tkt-fc62af4523.test numindex1.test
   186    186   ] -initialize {
   187    187     set ::G(valgrind) 1
   188    188   } -shutdown {
   189    189     unset -nocomplain ::G(valgrind)
   190    190   }
   191    191   
   192    192   test_suite "valgrind-nolookaside" -prefix "" -description {
................................................................................
   707    707   #
   708    708   test_suite "inmemory_journal" -description {
   709    709     Run tests with an in-memory journal file.
   710    710   } -presql {
   711    711     pragma journal_mode = 'memory'
   712    712   } -files [test_set $::allquicktests -exclude {
   713    713     # Exclude all tests that simulate IO errors.
   714         -  autovacuum_ioerr2.test incrvacuum_ioerr.test ioerr.test
          714  +  autovacuum_ioerr2.test cffault.test incrvacuum_ioerr.test ioerr.test
   715    715     ioerr.test ioerr2.test ioerr3.test ioerr4.test ioerr5.test
   716    716     vacuum3.test incrblob_err.test diskfull.test backup_ioerr.test
   717    717     e_fts3.test fts3cov.test fts3malloc.test fts3rnd.test
   718    718     fts3snippet.test mmapfault.test
   719    719   
   720    720     # Exclude test scripts that use tcl IO to access journal files or count
   721    721     # the number of fsync() calls.
................................................................................
   723    723     journal1.test conflict.test crash8.test tkt3457.test io.test
   724    724     journal3.test 8_3_names.test
   725    725   
   726    726     pager1.test async4.test corrupt.test filefmt.test pager2.test
   727    727     corrupt5.test corruptA.test pageropt.test
   728    728   
   729    729     # Exclude stmt.test, which expects sub-journals to use temporary files.
   730         -  stmt.test
          730  +  stmt.test symlink.test
   731    731   
   732    732     zerodamage.test
   733    733   
   734    734     # WAL mode is different.
   735    735     wal* tkt-2d1a5c67d.test backcompat.test e_wal* rowallock.test
   736    736   }]
   737    737   

Changes to test/releasetest.tcl.

    15     15       --quick                            (Run "veryquick.test" only)
    16     16       --veryquick                        (Run "make smoketest" only)
    17     17       --msvc                             (Use MSVC as the compiler)
    18     18       --buildonly                        (Just build testfixture - do not run)
    19     19       --dryrun                           (Print what would have happened)
    20     20       --info                             (Show diagnostic info)
    21     21       --with-tcl=DIR                     (Use TCL build at DIR)
           22  +    --jobs     N                       (Use N processes - default 1)
           23  +    --progress                         (Show progress messages)
    22     24   
    23     25   The default value for --srcdir is the parent of the directory holding
    24     26   this script.
    25     27   
    26     28   The script determines the default value for --platform using the
    27     29   $tcl_platform(os) and $tcl_platform(machine) variables.  Supported
    28     30   platforms are "Linux-x86", "Linux-x86_64", "Darwin-i386",
    29     31   "Darwin-x86_64", "Windows NT-intel", and "Windows NT-amd64".
    30     32   
    31     33   Every test begins with a fresh run of the configure script at the top
    32     34   of the SQLite source tree.
    33     35   }
           36  +
           37  +# Return a timestamp of the form HH:MM:SS
           38  +#
           39  +proc now {} {
           40  +  return [clock format [clock seconds] -format %H:%M:%S]
           41  +}
    34     42   
    35     43   # Omit comments (text between # and \n) in a long multi-line string.
    36     44   #
    37     45   proc strip_comments {in} {
    38     46     regsub -all {#[^\n]*\n} $in {} out
    39     47     return $out
    40     48   }
................................................................................
   116    124     "Fast-One" {
   117    125       -O6
   118    126       -DSQLITE_ENABLE_FTS4=1
   119    127       -DSQLITE_ENABLE_RTREE=1
   120    128       -DSQLITE_ENABLE_STAT4
   121    129       -DSQLITE_ENABLE_RBU
   122    130       -DSQLITE_MAX_ATTACHED=125
          131  +    -DLONGDOUBLE_TYPE=double
   123    132     }
   124    133     "Device-One" {
   125    134       -O2
   126    135       -DSQLITE_DEBUG=1
   127    136       -DSQLITE_DEFAULT_AUTOVACUUM=1
   128    137       -DSQLITE_DEFAULT_CACHE_SIZE=64
   129    138       -DSQLITE_DEFAULT_PAGE_SIZE=1024
................................................................................
   219    228     FuzzFail1 {-O0}
   220    229     FuzzFail2 {-O0}
   221    230   }]
   222    231   
   223    232   array set ::Platforms [strip_comments {
   224    233     Linux-x86_64 {
   225    234       "Check-Symbols"           checksymbols
          235  +    "Fast-One"                fuzztest
   226    236       "Debug-One"               "mptest test"
   227    237       "Have-Not"                test
   228    238       "Secure-Delete"           test
   229    239       "Unlock-Notify"           "QUICKTEST_INCLUDE=notify2.test test"
   230    240       "Update-Delete-Limit"     test
   231    241       "Extra-Robustness"        test
   232    242       "Device-Two"              test
   233    243       "No-lookaside"            test
   234    244       "Devkit"                  test
   235    245       "Sanitize"                {QUICKTEST_OMIT=func4.test,nan.test test}
   236         -    "Fast-One"                fuzztest
   237         -    "Valgrind"                valgrindtest
          246  +    "Device-One"              fulltest
   238    247       "Default"                 "threadtest fulltest"
   239         -    "Device-One"              fulltest
          248  +    "Valgrind"                valgrindtest
   240    249     }
   241    250     Linux-i686 {
   242    251       "Devkit"                  test
   243    252       "Have-Not"                test
   244    253       "Unlock-Notify"           "QUICKTEST_INCLUDE=notify2.test test"
   245    254       "Device-One"              test
   246    255       "Device-Two"              test
................................................................................
   253    262     }
   254    263     Darwin-x86_64 {
   255    264       "Locking-Style"           "mptest test"
   256    265       "Have-Not"                test
   257    266       "OS-X"                    "threadtest fulltest"
   258    267     }
   259    268     "Windows NT-intel" {
   260         -    "Default"                 "mptest fulltestonly"
   261    269       "Have-Not"                test
          270  +    "Default"                 "mptest fulltestonly"
   262    271     }
   263    272     "Windows NT-amd64" {
   264         -    "Default"                 "mptest fulltestonly"
   265    273       "Have-Not"                test
          274  +    "Default"                 "mptest fulltestonly"
   266    275     }
   267    276   
   268    277     # The Failure-Detection platform runs various tests that deliberately
   269    278     # fail.  This is used as a test of this script to verify that this script
   270    279     # correctly identifies failures.
   271    280     #
   272    281     Failure-Detection {
................................................................................
   281    290   }]
   282    291   
   283    292   
   284    293   # End of configuration section.
   285    294   #########################################################################
   286    295   #########################################################################
   287    296   
          297  +# Configuration verification: Check that each entry in the list of configs
          298  +# specified for each platforms exists.
          299  +#
   288    300   foreach {key value} [array get ::Platforms] {
   289    301     foreach {v t} $value {
   290    302       if {0==[info exists ::Configs($v)]} {
   291    303         puts stderr "No such configuration: \"$v\""
   292    304         exit -1
   293    305       }
   294    306     }
................................................................................
   368    380           set rc 1
   369    381           set errmsg "version conflict: {$::SQLITE_VERSION} vs. {$v}"
   370    382         }
   371    383       }
   372    384     }
   373    385     close $fd
   374    386     if {$::BUILDONLY} {
   375         -    if {$rc==0} {
   376         -      set errmsg "Build complete"
   377         -    } else {
          387  +    incr ::NTESTCASE
          388  +    if {$rc!=0} {
   378    389         set errmsg "Build failed"
   379    390       }
   380    391     } elseif {!$seen} {
   381    392       set rc 1
   382    393       set errmsg "Test did not complete"
   383    394       if {[file readable core]} {
   384    395         append errmsg " - core file exists"
   385    396       }
   386    397     }
   387    398   }
   388    399   
   389         -proc run_test_suite {name testtarget config} {
          400  +#--------------------------------------------------------------------------
          401  +# This command is invoked as the [main] routine for scripts run with the
          402  +# "--slave" option.
          403  +#
          404  +# For each test (i.e. "configure && make test" execution), the master
          405  +# process spawns a process with the --slave option. It writes two lines
          406  +# to the slaves stdin. The first contains a single boolean value - the
          407  +# value of ::TRACE to use in the slave script. The second line contains a
          408  +# list in the same format as each element of the list passed to the
          409  +# [run_all_test_suites] command in the master process.
          410  +#
          411  +# The slave then runs the "configure && make test" commands specified. It
          412  +# exits successfully if the tests passes, or with a non-zero error code
          413  +# otherwise.
          414  +#
          415  +proc run_slave_test {} {
          416  +  # Read global vars configuration from stdin.
          417  +  set V [gets stdin]
          418  +  foreach {::TRACE ::MSVC ::DRYRUN} $V {}
          419  +
          420  +  # Read the test-suite configuration from stdin.
          421  +  set T [gets stdin]
          422  +  foreach {title dir configOpts testtarget makeOpts cflags opts} $T {}
          423  +
          424  +  # Create and switch to the test directory.
          425  +  trace_cmd file mkdir $dir
          426  +  trace_cmd cd $dir
          427  +  catch {file delete core}
          428  +  catch {file delete test.log}
          429  +
          430  +  # Run the "./configure && make" commands.
          431  +  set rc 0
          432  +  set rc [catch [configureCommand $configOpts]]
          433  +  if {!$rc} {
          434  +    if {[info exists ::env(TCLSH_CMD)]} {
          435  +      set savedEnv(TCLSH_CMD) $::env(TCLSH_CMD)
          436  +    } else {
          437  +      unset -nocomplain savedEnv(TCLSH_CMD)
          438  +    }
          439  +    set ::env(TCLSH_CMD) [file nativename [info nameofexecutable]]
          440  +    set rc [catch [makeCommand $testtarget $makeOpts $cflags $opts]]
          441  +    if {[info exists savedEnv(TCLSH_CMD)]} {
          442  +      set ::env(TCLSH_CMD) $savedEnv(TCLSH_CMD)
          443  +    } else {
          444  +      unset -nocomplain ::env(TCLSH_CMD)
          445  +    }
          446  +  }
          447  +
          448  +  # Exis successfully if the test passed, or with a non-zero error code
          449  +  # otherwise.
          450  +  exit $rc
          451  +}
          452  +
          453  +# This command is invoked in the master process each time a slave
          454  +# file-descriptor is readable.
          455  +#
          456  +proc slave_fileevent {fd T tm1} {
          457  +  global G
          458  +  foreach {title dir configOpts testtarget makeOpts cflags opts} $T {}
          459  +
          460  +  if {[eof $fd]} {
          461  +    fconfigure $fd -blocking 1
          462  +    set rc [catch { close $fd }]
          463  +
          464  +    set errmsg {}
          465  +    set logfile [file join $dir test.log]
          466  +    if {[file exists $logfile]} {
          467  +      count_tests_and_errors [file join $dir test.log] rc errmsg
          468  +    } elseif {$rc==0 && !$::DRYRUN} {
          469  +      set rc 1
          470  +      set errmsg "no test.log file..."
          471  +    }
          472  +
          473  +    if {!$::TRACE} {
          474  +      set tm2 [clock seconds]
          475  +      set hours [expr {($tm2-$tm1)/3600}]
          476  +      set minutes [expr {(($tm2-$tm1)/60)%60}]
          477  +      set seconds [expr {($tm2-$tm1)%60}]
          478  +      set tm [format (%02d:%02d:%02d) $hours $minutes $seconds]
          479  +
          480  +      if {$rc} {
          481  +        set status FAIL
          482  +        incr ::NERR
          483  +      } else {
          484  +        set status Ok
          485  +      }
          486  +
          487  +      set n [string length $title]
          488  +      if {$::PROGRESS_MSGS} {
          489  +        PUTS "finished: ${title}[string repeat . [expr {53-$n}]] $status $tm"
          490  +      } else {
          491  +        PUTS "${title}[string repeat . [expr {63-$n}]] $status $tm"
          492  +      }
          493  +      if {$errmsg!=""} {PUTS "     $errmsg"}
          494  +      flush stdout
          495  +    }
          496  +
          497  +    incr G(nJob) -1
          498  +  } else {
          499  +    set line [gets $fd]
          500  +    if {[string trim $line] != ""} {
          501  +      puts "Trace   : $title - \"$line\""
          502  +    }
          503  +  }
          504  +}
          505  +
          506  +#--------------------------------------------------------------------------
          507  +# The only argument passed to this function is a list of test-suites to
          508  +# run. Each "test-suite" is itself a list consisting of the following
          509  +# elements:
          510  +#
          511  +#   * Test title (for display).
          512  +#   * The name of the directory to run the test in.
          513  +#   * The argument for [configureCommand]
          514  +#   * The first argument for [makeCommand]
          515  +#   * The second argument for [makeCommand]
          516  +#   * The third argument for [makeCommand]
          517  +#
          518  +proc run_all_test_suites {alltests} {
          519  +  global G
          520  +  set tests $alltests
          521  +
          522  +  set G(nJob) 0
          523  +
          524  +  while {[llength $tests]>0 || $G(nJob)>0} {
          525  +    if {$G(nJob)>=$::JOBS || [llength $tests]==0} {
          526  +      vwait G(nJob)
          527  +    }
          528  +
          529  +    if {[llength $tests]>0} {
          530  +      set T [lindex $tests 0]
          531  +      set tests [lrange $tests 1 end]
          532  +      foreach {title dir configOpts testtarget makeOpts cflags opts} $T {}
          533  +      if {$::PROGRESS_MSGS && !$::TRACE} {
          534  +        set n [string length $title]
          535  +        PUTS "starting: ${title} at [now]"
          536  +        flush stdout
          537  +      }
          538  +
          539  +      # Run the job.
          540  +      #
          541  +      set tm1 [clock seconds]
          542  +      incr G(nJob)
          543  +      set script [file normalize [info script]]
          544  +      set fd [open "|[info nameofexecutable] $script --slave" r+]
          545  +      fconfigure $fd -blocking 0
          546  +      fileevent $fd readable [list slave_fileevent $fd $T $tm1]
          547  +      puts $fd [list $::TRACE $::MSVC $::DRYRUN]
          548  +      puts $fd [list {*}$T]
          549  +      flush $fd
          550  +    }
          551  +  }
          552  +}
          553  +
          554  +proc add_test_suite {listvar name testtarget config} {
          555  +  upvar $listvar alltests
          556  +
   390    557     # Tcl variable $opts is used to build up the value used to set the
   391    558     # OPTS Makefile variable. Variable $cflags holds the value for
   392    559     # CFLAGS. The makefile will pass OPTS to both gcc and lemon, but
   393    560     # CFLAGS is only passed to gcc.
   394    561     #
          562  +  set makeOpts ""
   395    563     set cflags [expr {$::MSVC ? "-Zi" : "-g"}]
   396    564     set opts ""
   397    565     set title ${name}($testtarget)
   398    566     set configOpts $::WITHTCL
   399    567   
   400    568     regsub -all {#[^\n]*\n} $config \n config
   401    569     foreach arg $config {
   402    570       if {[regexp {^-[UD]} $arg]} {
   403    571         lappend opts $arg
   404    572       } elseif {[regexp {^[A-Z]+=} $arg]} {
   405    573         lappend testtarget $arg
   406    574       } elseif {[regexp {^--(enable|disable)-} $arg]} {
          575  +      if {$::MSVC} {
          576  +        if {$arg eq "--disable-amalgamation"} {
          577  +          lappend makeOpts USE_AMALGAMATION=0
          578  +          continue
          579  +        }
          580  +        if {$arg eq "--disable-shared"} {
          581  +          lappend makeOpts USE_CRT_DLL=0 DYNAMIC_SHELL=0
          582  +          continue
          583  +        }
          584  +        if {$arg eq "--enable-fts5"} {
          585  +          lappend opts -DSQLITE_ENABLE_FTS5
          586  +          continue
          587  +        }
          588  +        if {$arg eq "--enable-json1"} {
          589  +          lappend opts -DSQLITE_ENABLE_JSON1
          590  +          continue
          591  +        }
          592  +        if {$arg eq "--enable-shared"} {
          593  +          lappend makeOpts USE_CRT_DLL=1 DYNAMIC_SHELL=1
          594  +          continue
          595  +        }
          596  +      }
   407    597         lappend configOpts $arg
   408    598       } else {
          599  +      if {$::MSVC} {
          600  +        if {$arg eq "-g"} {
          601  +          lappend cflags -Zi
          602  +          continue
          603  +        }
          604  +        if {[regexp -- {^-O(\d+)$} $arg all level]} then {
          605  +          lappend makeOpts OPTIMIZATIONS=$level
          606  +          continue
          607  +        }
          608  +      }
   409    609         lappend cflags $arg
   410    610       }
   411    611     }
   412    612   
   413         -  set cflags [join $cflags " "]
   414         -  set opts   [join $opts " "]
   415         -  append opts " -DSQLITE_NO_SYNC=1"
          613  +  # Disable sync to make testing faster.
          614  +  #
          615  +  lappend opts -DSQLITE_NO_SYNC=1
   416    616   
   417    617     # Some configurations already set HAVE_USLEEP; in that case, skip it.
   418    618     #
   419         -  if {![regexp { -DHAVE_USLEEP$} $opts]
   420         -         && ![regexp { -DHAVE_USLEEP[ =]+} $opts]} {
   421         -    append opts " -DHAVE_USLEEP=1"
          619  +  if {[lsearch -regexp $opts {^-DHAVE_USLEEP(?:=|$)}]==-1} {
          620  +    lappend opts -DHAVE_USLEEP=1
          621  +  }
          622  +
          623  +  # Add the define for this platform.
          624  +  #
          625  +  if {$::tcl_platform(platform)=="windows"} {
          626  +    lappend opts -DSQLITE_OS_WIN=1
          627  +  } else {
          628  +    lappend opts -DSQLITE_OS_UNIX=1
   422    629     }
   423    630   
   424    631     # Set the sub-directory to use.
   425    632     #
   426    633     set dir [string tolower [string map {- _ " " _} $name]]
   427    634   
   428         -  if {$::tcl_platform(platform)=="windows"} {
   429         -    append opts " -DSQLITE_OS_WIN=1"
   430         -  } else {
   431         -    append opts " -DSQLITE_OS_UNIX=1"
   432         -  }
          635  +  # Join option lists into strings, using space as delimiter.
          636  +  #
          637  +  set makeOpts [join $makeOpts " "]
          638  +  set cflags   [join $cflags " "]
          639  +  set opts     [join $opts " "]
   433    640   
   434         -  if {!$::TRACE} {
   435         -    set n [string length $title]
   436         -    PUTS -nonewline "${title}[string repeat . [expr {63-$n}]]"
   437         -    flush stdout
   438         -  }
   439         -
   440         -  set rc 0
   441         -  set tm1 [clock seconds]
   442         -  set origdir [pwd]
   443         -  trace_cmd file mkdir $dir
   444         -  trace_cmd cd $dir
   445         -  set errmsg {}
   446         -  catch {file delete core}
   447         -  set rc [catch [configureCommand $configOpts]]
   448         -  if {!$rc} {
   449         -    set rc [catch [makeCommand $testtarget $cflags $opts]]
   450         -    count_tests_and_errors test.log rc errmsg
   451         -  }
   452         -  trace_cmd cd $origdir
   453         -  set tm2 [clock seconds]
   454         -
   455         -  if {!$::TRACE} {
   456         -    set hours [expr {($tm2-$tm1)/3600}]
   457         -    set minutes [expr {(($tm2-$tm1)/60)%60}]
   458         -    set seconds [expr {($tm2-$tm1)%60}]
   459         -    set tm [format (%02d:%02d:%02d) $hours $minutes $seconds]
   460         -    if {$rc} {
   461         -      PUTS " FAIL $tm"
   462         -      incr ::NERR
   463         -    } else {
   464         -      PUTS " Ok   $tm"
   465         -    }
   466         -    if {$errmsg!=""} {PUTS "     $errmsg"}
   467         -  }
          641  +  lappend alltests [list \
          642  +      $title $dir $configOpts $testtarget $makeOpts $cflags $opts]
   468    643   }
   469    644   
   470    645   # The following procedure returns the "configure" command to be exectued for
   471    646   # the current platform, which may be Windows (via MinGW, etc).
   472    647   #
   473    648   proc configureCommand {opts} {
   474    649     if {$::MSVC} return [list]; # This is not needed for MSVC.
................................................................................
   480    655     foreach x $opts {lappend result $x}
   481    656     lappend result >& test.log
   482    657   }
   483    658   
   484    659   # The following procedure returns the "make" command to be executed for the
   485    660   # specified targets, compiler flags, and options.
   486    661   #
   487         -proc makeCommand { targets cflags opts } {
          662  +proc makeCommand { targets makeOpts cflags opts } {
   488    663     set result [list trace_cmd exec]
   489    664     if {$::MSVC} {
   490    665       set nmakeDir [file nativename $::SRCDIR]
   491         -    set nmakeFile [file join $nmakeDir Makefile.msc]
   492         -    lappend result nmake /f $nmakeFile TOP=$nmakeDir clean
          666  +    set nmakeFile [file nativename [file join $nmakeDir Makefile.msc]]
          667  +    lappend result nmake /f $nmakeFile TOP=$nmakeDir
   493    668     } else {
   494         -    lappend result make clean
          669  +    lappend result make
          670  +  }
          671  +  foreach makeOpt $makeOpts {
          672  +    lappend result $makeOpt
   495    673     }
          674  +  lappend result clean
   496    675     foreach target $targets {
   497    676       lappend result $target
   498    677     }
   499    678     lappend result CFLAGS=$cflags OPTS=$opts >>& test.log
   500    679   }
   501    680   
   502    681   # The following procedure prints its arguments if ::TRACE is true.
................................................................................
   503    682   # And it executes the command of its arguments in the calling context
   504    683   # if ::DRYRUN is false.
   505    684   #
   506    685   proc trace_cmd {args} {
   507    686     if {$::TRACE} {
   508    687       PUTS $args
   509    688     }
          689  +  set res ""
   510    690     if {!$::DRYRUN} {
   511         -    uplevel 1 $args
          691  +    set res [uplevel 1 $args]
   512    692     }
          693  +  return $res
   513    694   }
   514    695   
   515    696   
   516    697   # This proc processes the command line options passed to this script.
   517    698   # Currently the only option supported is "-makefile", default
   518    699   # "releasetest.mk". Set the ::MAKEFILE variable to the value of this
   519    700   # option.
   520    701   #
   521    702   proc process_options {argv} {
   522    703     set ::SRCDIR    [file normalize [file dirname [file dirname $::argv0]]]
   523         -  set ::QUICK     0
   524         -  set ::MSVC      0
   525         -  set ::BUILDONLY 0
   526         -  set ::DRYRUN    0
   527         -  set ::EXEC      exec
   528         -  set ::TRACE     0
   529         -  set ::WITHTCL   {}
          704  +  set ::QUICK          0
          705  +  set ::MSVC           0
          706  +  set ::BUILDONLY      0
          707  +  set ::DRYRUN         0
          708  +  set ::TRACE          0
          709  +  set ::JOBS           1
          710  +  set ::PROGRESS_MSGS  0
          711  +  set ::WITHTCL        {}
   530    712     set config {}
   531    713     set platform $::tcl_platform(os)-$::tcl_platform(machine)
   532    714   
   533    715     for {set i 0} {$i < [llength $argv]} {incr i} {
   534    716       set x [lindex $argv $i]
   535    717       if {[regexp {^--[a-z]} $x]} {set x [string range $x 1 end]}
   536    718       switch -glob -- $x {
          719  +      -slave {
          720  +        run_slave_test
          721  +        exit
          722  +      }
          723  +
   537    724         -srcdir {
   538    725           incr i
   539    726           set ::SRCDIR [file normalize [lindex $argv $i]]
   540    727         }
   541    728   
   542    729         -platform {
   543    730           incr i
   544    731           set platform [lindex $argv $i]
   545    732         }
          733  +
          734  +      -jobs {
          735  +        incr i
          736  +        set ::JOBS [lindex $argv $i]
          737  +      }
          738  +
          739  +      -progress {
          740  +        set ::PROGRESS_MSGS 1
          741  +      }
   546    742   
   547    743         -quick {
   548    744           set ::QUICK 1
   549    745         }
   550    746         -veryquick {
   551    747           set ::QUICK 2
   552    748         }
................................................................................
   593    789           foreach y [lsort [array names ::Configs]] {
   594    790             PUTS "   [list $y]"
   595    791           }
   596    792           exit
   597    793         }
   598    794   
   599    795         -g {
   600         -        if {$::MSVC} {
   601         -          lappend ::EXTRACONFIG -Zi
   602         -        } else {
   603         -          lappend ::EXTRACONFIG [lindex $argv $i]
   604         -        }
          796  +        lappend ::EXTRACONFIG [lindex $argv $i]
   605    797         }
   606    798   
   607    799         -with-tcl=* {
   608    800           set ::WITHTCL -$x
   609    801         }
   610    802   
   611    803         -D* -
................................................................................
   636    828       exit
   637    829     }
   638    830   
   639    831     if {$config!=""} {
   640    832       if {[llength $config]==1} {lappend config fulltest}
   641    833       set ::CONFIGLIST $config
   642    834     } else {
   643         -    set ::CONFIGLIST $::Platforms($platform)
          835  +    if {$::JOBS>1} {
          836  +      set ::CONFIGLIST {}
          837  +      foreach {target zConfig} [lreverse $::Platforms($platform)] {
          838  +        append ::CONFIGLIST [format "    %-25s %s\n" \
          839  +                               [list $zConfig] [list $target]]
          840  +      }
          841  +    } else {
          842  +      set ::CONFIGLIST $::Platforms($platform)
          843  +    }
   644    844     }
   645    845     PUTS "Running the following test configurations for $platform:"
   646    846     PUTS "    [string trim $::CONFIGLIST]"
   647    847     PUTS -nonewline "Flags:"
          848  +  if {$::PROGRESS_MSGS} {PUTS -nonewline " --progress"}
   648    849     if {$::DRYRUN} {PUTS -nonewline " --dryrun"}
   649    850     if {$::BUILDONLY} {PUTS -nonewline " --buildonly"}
   650    851     if {$::MSVC} {PUTS -nonewline " --msvc"}
   651    852     switch -- $::QUICK {
   652    853        1 {PUTS -nonewline " --quick"}
   653    854        2 {PUTS -nonewline " --veryquick"}
   654    855     }
          856  +  if {$::JOBS>1} {PUTS -nonewline " --jobs $::JOBS"}
   655    857     PUTS ""
   656    858   }
   657    859   
   658    860   # Main routine.
   659    861   #
   660    862   proc main {argv} {
   661    863   
................................................................................
   679    881       if {$target ne "checksymbols"} {
   680    882         switch -- $::QUICK {
   681    883            1 {set target quicktest}
   682    884            2 {set target smoketest}
   683    885         }
   684    886         if {$::BUILDONLY} {
   685    887           set target testfixture
   686         -        if {$::MSVC} {append target .exe}
          888  +        if {$::tcl_platform(platform)=="windows"} {
          889  +          append target .exe
          890  +        }
   687    891         }
   688    892       }
   689    893       set config_options [concat $::Configs($zConfig) $::EXTRACONFIG]
   690    894   
   691    895       incr NTEST
   692         -    run_test_suite $zConfig $target $config_options
          896  +    add_test_suite all $zConfig $target $config_options
   693    897   
   694    898       # If the configuration included the SQLITE_DEBUG option, then remove
   695    899       # it and run veryquick.test. If it did not include the SQLITE_DEBUG option
   696    900       # add it and run veryquick.test.
   697    901       if {$target!="checksymbols" && $target!="valgrindtest"
   698    902              && $target!="fuzzoomtest" && !$::BUILDONLY && $::QUICK<2} {
   699    903         set debug_idx [lsearch -glob $config_options -DSQLITE_DEBUG*]
   700    904         set xtarget $target
   701    905         regsub -all {fulltest[a-z]*} $xtarget test xtarget
   702    906         regsub -all {fuzzoomtest} $xtarget fuzztest xtarget
   703    907         if {$debug_idx < 0} {
   704    908           incr NTEST
   705    909           append config_options " -DSQLITE_DEBUG=1"
   706         -        run_test_suite "${zConfig}_debug" $xtarget $config_options
          910  +        add_test_suite all "${zConfig}_debug" $xtarget $config_options
   707    911         } else {
   708    912           incr NTEST
   709    913           regsub { *-DSQLITE_MEMDEBUG[^ ]* *} $config_options { } config_options
   710    914           regsub { *-DSQLITE_DEBUG[^ ]* *} $config_options { } config_options
   711         -        run_test_suite "${zConfig}_ndebug" $xtarget $config_options
          915  +        add_test_suite all "${zConfig}_ndebug" $xtarget $config_options
   712    916         }
   713    917       }
   714    918     }
          919  +
          920  +  run_all_test_suites $all
   715    921   
   716    922     set elapsetime [expr {[clock seconds]-$STARTTIME}]
   717    923     set hr [expr {$elapsetime/3600}]
   718    924     set min [expr {($elapsetime/60)%60}]
   719    925     set sec [expr {$elapsetime%60}]
   720    926     set etime [format (%02d:%02d:%02d) $hr $min $sec]
   721    927     PUTS [string repeat * 79]

Changes to test/where.test.

   408    408         SELECT * FROM t1 WHERE rowid+0 IN (1,2,3,1234) order by 1;
   409    409       }
   410    410     } {1 0 4 2 1 9 3 1 16 102}
   411    411     do_test where-5.3a {
   412    412       count {
   413    413         SELECT * FROM t1 WHERE w IN (-1,1,2,3) order by 1;
   414    414       }
   415         -  } {1 0 4 2 1 9 3 1 16 13}
          415  +  } {1 0 4 2 1 9 3 1 16 12}
   416    416     do_test where-5.3b {
   417    417       count {
   418    418         SELECT * FROM t1 WHERE w IN (3,-1,1,2) order by 1;
   419    419       }
   420         -  } {1 0 4 2 1 9 3 1 16 13}
          420  +  } {1 0 4 2 1 9 3 1 16 12}
   421    421     do_test where-5.3c {
   422    422       count {
   423    423         SELECT * FROM t1 WHERE w IN (3,2,-1,1,2) order by 1;
   424    424       }
   425         -  } {1 0 4 2 1 9 3 1 16 13}
          425  +  } {1 0 4 2 1 9 3 1 16 12}
   426    426     do_test where-5.3d {
   427    427       count {
   428    428         SELECT * FROM t1 WHERE w IN (-1,1,2,3) order by 1 DESC;
   429    429       }
   430         -  } {3 1 16 2 1 9 1 0 4 12}
          430  +  } {3 1 16 2 1 9 1 0 4 11}
   431    431     do_test where-5.4 {
   432    432       count {
   433    433         SELECT * FROM t1 WHERE w+0 IN (-1,1,2,3) order by 1;
   434    434       }
   435    435     } {1 0 4 2 1 9 3 1 16 102}
   436    436     do_test where-5.5 {
   437    437       count {
................................................................................
   461    461         ORDER BY 1;
   462    462       }
   463    463     } {2 1 9 4 2 25 103}
   464    464     do_test where-5.9 {
   465    465       count {
   466    466         SELECT * FROM t1 WHERE x IN (1,7) ORDER BY 1;
   467    467       }
   468         -  } {2 1 9 3 1 16 7}
          468  +  } {2 1 9 3 1 16 6}
   469    469     do_test where-5.10 {
   470    470       count {
   471    471         SELECT * FROM t1 WHERE x+0 IN (1,7) ORDER BY 1;
   472    472       }
   473    473     } {2 1 9 3 1 16 199}
   474    474     do_test where-5.11 {
   475    475       count {
................................................................................
   481    481         SELECT * FROM t1 WHERE x=6 AND y IN (6400,8100) ORDER BY 1;
   482    482       }
   483    483     } {79 6 6400 89 6 8100 7}
   484    484     do_test where-5.13 {
   485    485       count {
   486    486         SELECT * FROM t1 WHERE x IN (1,7) AND y NOT IN (6400,8100) ORDER BY 1;
   487    487       }
   488         -  } {2 1 9 3 1 16 7}
          488  +  } {2 1 9 3 1 16 6}
   489    489     do_test where-5.14 {
   490    490       count {
   491    491         SELECT * FROM t1 WHERE x IN (1,7) AND y IN (9,10) ORDER BY 1;
   492    492       }
   493         -  } {2 1 9 8}
          493  +  } {2 1 9 5}
   494    494     do_test where-5.15 {
   495    495       count {
   496    496         SELECT * FROM t1 WHERE x IN (1,7) AND y IN (9,16) ORDER BY 1;
   497    497       }
   498         -  } {2 1 9 3 1 16 11}
          498  +  } {2 1 9 3 1 16 9}
   499    499     do_test where-5.100 {
   500    500       db eval {
   501    501         SELECT w, x, y FROM t1 WHERE x IN (1,5) AND y IN (9,8,3025,1000,3969)
   502    502          ORDER BY x, y
   503    503       }
   504    504     } {2 1 9 54 5 3025 62 5 3969}
   505    505     do_test where-5.101 {

Changes to test/where4.test.

    87     87     count {SELECT rowid FROM t1 WHERE w='a' AND x IS NULL AND y='c'}
    88     88   } {4 2}
    89     89   do_test where4-1.10 {
    90     90     count {SELECT rowid FROM t1 WHERE w=x'78' AND x IS NULL}
    91     91   } {6 2}
    92     92   do_test where4-1.11 {
    93     93     count {SELECT rowid FROM t1 WHERE w=x'78' AND x IS NULL AND y=123}
    94         -} {1}
           94  +} {0}
    95     95   do_test where4-1.12 {
    96     96     count {SELECT rowid FROM t1 WHERE w=x'78' AND x IS NULL AND y=x'7A'}
    97     97   } {6 2}
    98     98   do_test where4-1.13 {
    99     99     count {SELECT rowid FROM t1 WHERE w IS NULL AND x IS NULL}
   100    100   } {7 2}
   101    101   do_test where4-1.14 {