/ Check-in [201fcbee]
Login

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

Overview
Comment:Merge OOM handling optimizations and PRAGMA synchronous=EXTRA as well as other enhancements from trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | apple-osx
Files: files | file ages | folders
SHA1:201fcbeef35d3d06d71ef5770fb72152840fcc2e
User & Date: drh 2016-02-05 14:29:18
Context
2016-02-09
15:50
Merge recent fixes and enhancements from trunk. check-in: f0734017 user: drh tags: apple-osx
2016-02-05
14:29
Merge OOM handling optimizations and PRAGMA synchronous=EXTRA as well as other enhancements from trunk. check-in: 201fcbee user: drh tags: apple-osx
14:11
Improvements to the way out-of-memory conditions are handled, resulting in an almost 1% performance gain in the commmon case where OOM errors do not occur. check-in: b082538d user: drh tags: trunk
2016-02-02
02:30
Merge recent enhancements from trunk. check-in: e6a4a163 user: drh tags: apple-osx
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/fts5/fts5Int.h.

   315    315   typedef struct Fts5Index Fts5Index;
   316    316   typedef struct Fts5IndexIter Fts5IndexIter;
   317    317   
   318    318   struct Fts5IndexIter {
   319    319     i64 iRowid;
   320    320     const u8 *pData;
   321    321     int nData;
          322  +  u8 bEof;
   322    323   };
          324  +
          325  +#define sqlite3Fts5IterEof(x) ((x)->bEof)
   323    326   
   324    327   /*
   325    328   ** Values used as part of the flags argument passed to IndexQuery().
   326    329   */
   327    330   #define FTS5INDEX_QUERY_PREFIX     0x0001   /* Prefix query */
   328    331   #define FTS5INDEX_QUERY_DESC       0x0002   /* Docs in descending rowid order */
   329    332   #define FTS5INDEX_QUERY_TEST_NOIDX 0x0004   /* Do not use prefix index */
   330    333   #define FTS5INDEX_QUERY_SCAN       0x0008   /* Scan query (fts5vocab) */
          334  +
          335  +/* The following are used internally by the fts5_index.c module. They are
          336  +** defined here only to make it easier to avoid clashes with the flags
          337  +** above. */
          338  +#define FTS5INDEX_QUERY_SKIPEMPTY  0x0010
          339  +#define FTS5INDEX_QUERY_NOOUTPUT   0x0020
   331    340   
   332    341   /*
   333    342   ** Create/destroy an Fts5Index object.
   334    343   */
   335    344   int sqlite3Fts5IndexOpen(Fts5Config *pConfig, int bCreate, Fts5Index**, char**);
   336    345   int sqlite3Fts5IndexClose(Fts5Index *p);
   337    346   
................................................................................
   380    389     Fts5IndexIter **ppIter          /* OUT: New iterator object */
   381    390   );
   382    391   
   383    392   /*
   384    393   ** The various operations on open token or token prefix iterators opened
   385    394   ** using sqlite3Fts5IndexQuery().
   386    395   */
   387         -int sqlite3Fts5IterEof(Fts5IndexIter*);
   388    396   int sqlite3Fts5IterNext(Fts5IndexIter*);
   389    397   int sqlite3Fts5IterNextFrom(Fts5IndexIter*, i64 iMatch);
   390    398   i64 sqlite3Fts5IterRowid(Fts5IndexIter*);
   391    399   
   392    400   /*
   393    401   ** Close an iterator opened by sqlite3Fts5IndexQuery().
   394    402   */

Changes to ext/fts5/fts5_expr.c.

   299    299     int bRetValid = 0;
   300    300     Fts5ExprTerm *p;
   301    301   
   302    302     assert( pTerm->pSynonym );
   303    303     assert( bDesc==0 || bDesc==1 );
   304    304     for(p=pTerm; p; p=p->pSynonym){
   305    305       if( 0==sqlite3Fts5IterEof(p->pIter) ){
   306         -      i64 iRowid = sqlite3Fts5IterRowid(p->pIter);
          306  +      i64 iRowid = p->pIter->iRowid;
   307    307         if( bRetValid==0 || (bDesc!=(iRowid<iRet)) ){
   308    308           iRet = iRowid;
   309    309           bRetValid = 1;
   310    310         }
   311    311       }
   312    312     }
   313    313   
................................................................................
   332    332     int nAlloc = 4;
   333    333     int rc = SQLITE_OK;
   334    334     Fts5ExprTerm *p;
   335    335   
   336    336     assert( pTerm->pSynonym );
   337    337     for(p=pTerm; p; p=p->pSynonym){
   338    338       Fts5IndexIter *pIter = p->pIter;
   339         -    if( sqlite3Fts5IterEof(pIter)==0 && sqlite3Fts5IterRowid(pIter)==iRowid ){
          339  +    if( sqlite3Fts5IterEof(pIter)==0 && pIter->iRowid==iRowid ){
   340    340         if( pIter->nData==0 ) continue;
   341    341         if( nIter==nAlloc ){
   342    342           int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2;
   343    343           Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte);
   344    344           if( aNew==0 ){
   345    345             rc = SQLITE_NOMEM;
   346    346             goto synonym_poslist_out;
................................................................................
   627    627       int bRet = a[0].pOut->n>0;
   628    628       *pRc = rc;
   629    629       if( a!=aStatic ) sqlite3_free(a);
   630    630       return bRet;
   631    631     }
   632    632   }
   633    633   
   634         -/*
   635         -** Advance the first term iterator in the first phrase of pNear. Set output
   636         -** variable *pbEof to true if it reaches EOF or if an error occurs.
   637         -**
   638         -** Return SQLITE_OK if successful, or an SQLite error code if an error
   639         -** occurs.
   640         -*/
   641         -static int fts5ExprNearAdvanceFirst(
   642         -  Fts5Expr *pExpr,                /* Expression pPhrase belongs to */
   643         -  Fts5ExprNode *pNode,            /* FTS5_STRING or FTS5_TERM node */
   644         -  int bFromValid,
   645         -  i64 iFrom 
   646         -){
   647         -  Fts5ExprTerm *pTerm = &pNode->pNear->apPhrase[0]->aTerm[0];
   648         -  int rc = SQLITE_OK;
   649         -
   650         -  pNode->bNomatch = 0;
   651         -  if( pTerm->pSynonym ){
   652         -    int bEof = 1;
   653         -    Fts5ExprTerm *p;
   654         -
   655         -    /* Find the firstest rowid any synonym points to. */
   656         -    i64 iRowid = fts5ExprSynonymRowid(pTerm, pExpr->bDesc, 0);
   657         -
   658         -    /* Advance each iterator that currently points to iRowid. Or, if iFrom
   659         -    ** is valid - each iterator that points to a rowid before iFrom.  */
   660         -    for(p=pTerm; p; p=p->pSynonym){
   661         -      if( sqlite3Fts5IterEof(p->pIter)==0 ){
   662         -        i64 ii = sqlite3Fts5IterRowid(p->pIter);
   663         -        if( ii==iRowid 
   664         -         || (bFromValid && ii!=iFrom && (ii>iFrom)==pExpr->bDesc) 
   665         -        ){
   666         -          if( bFromValid ){
   667         -            rc = sqlite3Fts5IterNextFrom(p->pIter, iFrom);
   668         -          }else{
   669         -            rc = sqlite3Fts5IterNext(p->pIter);
   670         -          }
   671         -          if( rc!=SQLITE_OK ) break;
   672         -          if( sqlite3Fts5IterEof(p->pIter)==0 ){
   673         -            bEof = 0;
   674         -          }
   675         -        }else{
   676         -          bEof = 0;
   677         -        }
   678         -      }
   679         -    }
   680         -
   681         -    /* Set the EOF flag if either all synonym iterators are at EOF or an
   682         -    ** error has occurred.  */
   683         -    pNode->bEof = (rc || bEof);
   684         -  }else{
   685         -    Fts5IndexIter *pIter = pTerm->pIter;
   686         -
   687         -    assert( Fts5NodeIsString(pNode) );
   688         -    if( bFromValid ){
   689         -      rc = sqlite3Fts5IterNextFrom(pIter, iFrom);
   690         -    }else{
   691         -      rc = sqlite3Fts5IterNext(pIter);
   692         -    }
   693         -
   694         -    pNode->bEof = (rc || sqlite3Fts5IterEof(pIter));
   695         -  }
   696         -
   697         -  return rc;
   698         -}
   699         -
   700    634   /*
   701    635   ** Advance iterator pIter until it points to a value equal to or laster
   702    636   ** than the initial value of *piLast. If this means the iterator points
   703    637   ** to a value laster than *piLast, update *piLast to the new lastest value.
   704    638   **
   705    639   ** If the iterator reaches EOF, set *pbEof to true before returning. If
   706    640   ** an error occurs, set *pRc to an error code. If either *pbEof or *pRc
................................................................................
   712    646     i64 *piLast,                    /* IN/OUT: Lastest rowid seen so far */
   713    647     int *pRc,                       /* OUT: Error code */
   714    648     int *pbEof                      /* OUT: Set to true if EOF */
   715    649   ){
   716    650     i64 iLast = *piLast;
   717    651     i64 iRowid;
   718    652   
   719         -  iRowid = sqlite3Fts5IterRowid(pIter);
          653  +  iRowid = pIter->iRowid;
   720    654     if( (bDesc==0 && iLast>iRowid) || (bDesc && iLast<iRowid) ){
   721    655       int rc = sqlite3Fts5IterNextFrom(pIter, iLast);
   722    656       if( rc || sqlite3Fts5IterEof(pIter) ){
   723    657         *pRc = rc;
   724    658         *pbEof = 1;
   725    659         return 1;
   726    660       }
   727         -    iRowid = sqlite3Fts5IterRowid(pIter);
          661  +    iRowid = pIter->iRowid;
   728    662       assert( (bDesc==0 && iRowid>=iLast) || (bDesc==1 && iRowid<=iLast) );
   729    663     }
   730    664     *piLast = iRowid;
   731    665   
   732    666     return 0;
   733    667   }
   734    668   
................................................................................
   741    675     int rc = SQLITE_OK;
   742    676     i64 iLast = *piLast;
   743    677     Fts5ExprTerm *p;
   744    678     int bEof = 0;
   745    679   
   746    680     for(p=pTerm; rc==SQLITE_OK && p; p=p->pSynonym){
   747    681       if( sqlite3Fts5IterEof(p->pIter)==0 ){
   748         -      i64 iRowid = sqlite3Fts5IterRowid(p->pIter);
          682  +      i64 iRowid = p->pIter->iRowid;
   749    683         if( (bDesc==0 && iLast>iRowid) || (bDesc && iLast<iRowid) ){
   750    684           rc = sqlite3Fts5IterNextFrom(p->pIter, iLast);
   751    685         }
   752    686       }
   753    687     }
   754    688   
   755    689     if( rc!=SQLITE_OK ){
................................................................................
   805    739       if( i==pNear->nPhrase && (i==1 || fts5ExprNearIsMatch(pRc, pNear)) ){
   806    740         return 1;
   807    741       }
   808    742       return 0;
   809    743     }
   810    744   }
   811    745   
   812         -static int fts5ExprTokenTest(
   813         -  Fts5Expr *pExpr,                /* Expression that pNear is a part of */
   814         -  Fts5ExprNode *pNode             /* The "NEAR" node (FTS5_TERM) */
   815         -){
   816         -  /* As this "NEAR" object is actually a single phrase that consists 
   817         -  ** of a single term only, grab pointers into the poslist managed by the
   818         -  ** fts5_index.c iterator object. This is much faster than synthesizing 
   819         -  ** a new poslist the way we have to for more complicated phrase or NEAR
   820         -  ** expressions.  */
   821         -  Fts5ExprPhrase *pPhrase = pNode->pNear->apPhrase[0];
   822         -  Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter;
   823         -
   824         -  assert( pNode->eType==FTS5_TERM );
   825         -  assert( pNode->pNear->nPhrase==1 && pPhrase->nTerm==1 );
   826         -  assert( pPhrase->aTerm[0].pSynonym==0 );
   827         -
   828         -  pPhrase->poslist.n = pIter->nData;
   829         -  if( pExpr->pConfig->eDetail==FTS5_DETAIL_FULL ){
   830         -    pPhrase->poslist.p = (u8*)pIter->pData;
   831         -  }
   832         -  pNode->iRowid = pIter->iRowid;
   833         -  pNode->bNomatch = (pPhrase->poslist.n==0);
   834         -  return SQLITE_OK;
   835         -}
   836         -
   837         -/*
   838         -** All individual term iterators in pNear are guaranteed to be valid when
   839         -** this function is called. This function checks if all term iterators
   840         -** point to the same rowid, and if not, advances them until they do.
   841         -** If an EOF is reached before this happens, *pbEof is set to true before
   842         -** returning.
   843         -**
   844         -** SQLITE_OK is returned if an error occurs, or an SQLite error code 
   845         -** otherwise. It is not considered an error code if an iterator reaches
   846         -** EOF.
   847         -*/
   848         -static int fts5ExprNearNextMatch(
   849         -  Fts5Expr *pExpr,                /* Expression pPhrase belongs to */
   850         -  Fts5ExprNode *pNode
   851         -){
   852         -  Fts5ExprNearset *pNear = pNode->pNear;
   853         -  Fts5ExprPhrase *pLeft = pNear->apPhrase[0];
   854         -  int rc = SQLITE_OK;
   855         -  i64 iLast;                      /* Lastest rowid any iterator points to */
   856         -  int i, j;                       /* Phrase and token index, respectively */
   857         -  int bMatch;                     /* True if all terms are at the same rowid */
   858         -  const int bDesc = pExpr->bDesc;
   859         -
   860         -  /* Check that this node should not be FTS5_TERM */
   861         -  assert( pNear->nPhrase>1 
   862         -       || pNear->apPhrase[0]->nTerm>1 
   863         -       || pNear->apPhrase[0]->aTerm[0].pSynonym
   864         -  );
   865         -
   866         -  /* Initialize iLast, the "lastest" rowid any iterator points to. If the
   867         -  ** iterator skips through rowids in the default ascending order, this means
   868         -  ** the maximum rowid. Or, if the iterator is "ORDER BY rowid DESC", then it
   869         -  ** means the minimum rowid.  */
   870         -  if( pLeft->aTerm[0].pSynonym ){
   871         -    iLast = fts5ExprSynonymRowid(&pLeft->aTerm[0], bDesc, 0);
   872         -  }else{
   873         -    iLast = sqlite3Fts5IterRowid(pLeft->aTerm[0].pIter);
   874         -  }
   875         -
   876         -  do {
   877         -    bMatch = 1;
   878         -    for(i=0; i<pNear->nPhrase; i++){
   879         -      Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
   880         -      for(j=0; j<pPhrase->nTerm; j++){
   881         -        Fts5ExprTerm *pTerm = &pPhrase->aTerm[j];
   882         -        if( pTerm->pSynonym ){
   883         -          i64 iRowid = fts5ExprSynonymRowid(pTerm, bDesc, 0);
   884         -          if( iRowid==iLast ) continue;
   885         -          bMatch = 0;
   886         -          if( fts5ExprSynonymAdvanceto(pTerm, bDesc, &iLast, &rc) ){
   887         -            pNode->bNomatch = 0;
   888         -            pNode->bEof = 1;
   889         -            return rc;
   890         -          }
   891         -        }else{
   892         -          Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter;
   893         -          i64 iRowid = sqlite3Fts5IterRowid(pIter);
   894         -          if( iRowid==iLast ) continue;
   895         -          bMatch = 0;
   896         -          if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){
   897         -            return rc;
   898         -          }
   899         -        }
   900         -      }
   901         -    }
   902         -  }while( bMatch==0 );
   903         -
   904         -  pNode->iRowid = iLast;
   905         -  pNode->bNomatch = ((0==fts5ExprNearTest(&rc, pExpr, pNode)) && rc==SQLITE_OK);
   906         -  assert( pNode->bEof==0 || pNode->bNomatch==0 );
   907         -
   908         -  return rc;
   909         -}
   910    746   
   911    747   /*
   912    748   ** Initialize all term iterators in the pNear object. If any term is found
   913    749   ** to match no documents at all, return immediately without initializing any
   914    750   ** further iterators.
   915    751   */
   916    752   static int fts5ExprNearInitAll(
................................................................................
   952    788           return rc;
   953    789         }
   954    790       }
   955    791     }
   956    792   
   957    793     return rc;
   958    794   }
   959         -
   960         -/* fts5ExprNodeNext() calls fts5ExprNodeNextMatch(). And vice-versa. */
   961         -static int fts5ExprNodeNextMatch(Fts5Expr*, Fts5ExprNode*);
   962         -
   963    795   
   964    796   /*
   965    797   ** If pExpr is an ASC iterator, this function returns a value with the
   966    798   ** same sign as:
   967    799   **
   968    800   **   (iLhs - iRhs)
   969    801   **
................................................................................
  1008    840       for(i=0; i<pNode->nChild; i++){
  1009    841         fts5ExprNodeZeroPoslist(pNode->apChild[i]);
  1010    842       }
  1011    843     }
  1012    844   }
  1013    845   
  1014    846   
          847  +
          848  +/*
          849  +** Compare the values currently indicated by the two nodes as follows:
          850  +**
          851  +**    res = (*p1) - (*p2)
          852  +**
          853  +** Nodes that point to values that come later in the iteration order are
          854  +** considered to be larger. Nodes at EOF are the largest of all.
          855  +**
          856  +** This means that if the iteration order is ASC, then numerically larger
          857  +** rowids are considered larger. Or if it is the default DESC, numerically
          858  +** smaller rowids are larger.
          859  +*/
          860  +static int fts5NodeCompare(
          861  +  Fts5Expr *pExpr,
          862  +  Fts5ExprNode *p1, 
          863  +  Fts5ExprNode *p2
          864  +){
          865  +  if( p2->bEof ) return -1;
          866  +  if( p1->bEof ) return +1;
          867  +  return fts5RowidCmp(pExpr, p1->iRowid, p2->iRowid);
          868  +}
          869  +
          870  +/*
          871  +** All individual term iterators in pNear are guaranteed to be valid when
          872  +** this function is called. This function checks if all term iterators
          873  +** point to the same rowid, and if not, advances them until they do.
          874  +** If an EOF is reached before this happens, *pbEof is set to true before
          875  +** returning.
          876  +**
          877  +** SQLITE_OK is returned if an error occurs, or an SQLite error code 
          878  +** otherwise. It is not considered an error code if an iterator reaches
          879  +** EOF.
          880  +*/
          881  +static int fts5ExprNodeTest_STRING(
          882  +  Fts5Expr *pExpr,                /* Expression pPhrase belongs to */
          883  +  Fts5ExprNode *pNode
          884  +){
          885  +  Fts5ExprNearset *pNear = pNode->pNear;
          886  +  Fts5ExprPhrase *pLeft = pNear->apPhrase[0];
          887  +  int rc = SQLITE_OK;
          888  +  i64 iLast;                      /* Lastest rowid any iterator points to */
          889  +  int i, j;                       /* Phrase and token index, respectively */
          890  +  int bMatch;                     /* True if all terms are at the same rowid */
          891  +  const int bDesc = pExpr->bDesc;
          892  +
          893  +  /* Check that this node should not be FTS5_TERM */
          894  +  assert( pNear->nPhrase>1 
          895  +       || pNear->apPhrase[0]->nTerm>1 
          896  +       || pNear->apPhrase[0]->aTerm[0].pSynonym
          897  +  );
          898  +
          899  +  /* Initialize iLast, the "lastest" rowid any iterator points to. If the
          900  +  ** iterator skips through rowids in the default ascending order, this means
          901  +  ** the maximum rowid. Or, if the iterator is "ORDER BY rowid DESC", then it
          902  +  ** means the minimum rowid.  */
          903  +  if( pLeft->aTerm[0].pSynonym ){
          904  +    iLast = fts5ExprSynonymRowid(&pLeft->aTerm[0], bDesc, 0);
          905  +  }else{
          906  +    iLast = pLeft->aTerm[0].pIter->iRowid;
          907  +  }
          908  +
          909  +  do {
          910  +    bMatch = 1;
          911  +    for(i=0; i<pNear->nPhrase; i++){
          912  +      Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
          913  +      for(j=0; j<pPhrase->nTerm; j++){
          914  +        Fts5ExprTerm *pTerm = &pPhrase->aTerm[j];
          915  +        if( pTerm->pSynonym ){
          916  +          i64 iRowid = fts5ExprSynonymRowid(pTerm, bDesc, 0);
          917  +          if( iRowid==iLast ) continue;
          918  +          bMatch = 0;
          919  +          if( fts5ExprSynonymAdvanceto(pTerm, bDesc, &iLast, &rc) ){
          920  +            pNode->bNomatch = 0;
          921  +            pNode->bEof = 1;
          922  +            return rc;
          923  +          }
          924  +        }else{
          925  +          Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter;
          926  +          if( pIter->iRowid==iLast ) continue;
          927  +          bMatch = 0;
          928  +          if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){
          929  +            return rc;
          930  +          }
          931  +        }
          932  +      }
          933  +    }
          934  +  }while( bMatch==0 );
          935  +
          936  +  pNode->iRowid = iLast;
          937  +  pNode->bNomatch = ((0==fts5ExprNearTest(&rc, pExpr, pNode)) && rc==SQLITE_OK);
          938  +  assert( pNode->bEof==0 || pNode->bNomatch==0 );
          939  +
          940  +  return rc;
          941  +}
          942  +
          943  +/*
          944  +** Advance the first term iterator in the first phrase of pNear. Set output
          945  +** variable *pbEof to true if it reaches EOF or if an error occurs.
          946  +**
          947  +** Return SQLITE_OK if successful, or an SQLite error code if an error
          948  +** occurs.
          949  +*/
          950  +static int fts5ExprNodeNext_STRING(
          951  +  Fts5Expr *pExpr,                /* Expression pPhrase belongs to */
          952  +  Fts5ExprNode *pNode,            /* FTS5_STRING or FTS5_TERM node */
          953  +  int bFromValid,
          954  +  i64 iFrom 
          955  +){
          956  +  Fts5ExprTerm *pTerm = &pNode->pNear->apPhrase[0]->aTerm[0];
          957  +  int rc = SQLITE_OK;
          958  +
          959  +  pNode->bNomatch = 0;
          960  +  if( pTerm->pSynonym ){
          961  +    int bEof = 1;
          962  +    Fts5ExprTerm *p;
          963  +
          964  +    /* Find the firstest rowid any synonym points to. */
          965  +    i64 iRowid = fts5ExprSynonymRowid(pTerm, pExpr->bDesc, 0);
          966  +
          967  +    /* Advance each iterator that currently points to iRowid. Or, if iFrom
          968  +    ** is valid - each iterator that points to a rowid before iFrom.  */
          969  +    for(p=pTerm; p; p=p->pSynonym){
          970  +      if( sqlite3Fts5IterEof(p->pIter)==0 ){
          971  +        i64 ii = p->pIter->iRowid;
          972  +        if( ii==iRowid 
          973  +         || (bFromValid && ii!=iFrom && (ii>iFrom)==pExpr->bDesc) 
          974  +        ){
          975  +          if( bFromValid ){
          976  +            rc = sqlite3Fts5IterNextFrom(p->pIter, iFrom);
          977  +          }else{
          978  +            rc = sqlite3Fts5IterNext(p->pIter);
          979  +          }
          980  +          if( rc!=SQLITE_OK ) break;
          981  +          if( sqlite3Fts5IterEof(p->pIter)==0 ){
          982  +            bEof = 0;
          983  +          }
          984  +        }else{
          985  +          bEof = 0;
          986  +        }
          987  +      }
          988  +    }
          989  +
          990  +    /* Set the EOF flag if either all synonym iterators are at EOF or an
          991  +    ** error has occurred.  */
          992  +    pNode->bEof = (rc || bEof);
          993  +  }else{
          994  +    Fts5IndexIter *pIter = pTerm->pIter;
          995  +
          996  +    assert( Fts5NodeIsString(pNode) );
          997  +    if( bFromValid ){
          998  +      rc = sqlite3Fts5IterNextFrom(pIter, iFrom);
          999  +    }else{
         1000  +      rc = sqlite3Fts5IterNext(pIter);
         1001  +    }
         1002  +
         1003  +    pNode->bEof = (rc || sqlite3Fts5IterEof(pIter));
         1004  +  }
         1005  +
         1006  +  if( pNode->bEof==0 ){
         1007  +    assert( rc==SQLITE_OK );
         1008  +    rc = fts5ExprNodeTest_STRING(pExpr, pNode);
         1009  +  }
         1010  +
         1011  +  return rc;
         1012  +}
         1013  +
         1014  +
         1015  +static int fts5ExprNodeTest_TERM(
         1016  +  Fts5Expr *pExpr,                /* Expression that pNear is a part of */
         1017  +  Fts5ExprNode *pNode             /* The "NEAR" node (FTS5_TERM) */
         1018  +){
         1019  +  /* As this "NEAR" object is actually a single phrase that consists 
         1020  +  ** of a single term only, grab pointers into the poslist managed by the
         1021  +  ** fts5_index.c iterator object. This is much faster than synthesizing 
         1022  +  ** a new poslist the way we have to for more complicated phrase or NEAR
         1023  +  ** expressions.  */
         1024  +  Fts5ExprPhrase *pPhrase = pNode->pNear->apPhrase[0];
         1025  +  Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter;
         1026  +
         1027  +  assert( pNode->eType==FTS5_TERM );
         1028  +  assert( pNode->pNear->nPhrase==1 && pPhrase->nTerm==1 );
         1029  +  assert( pPhrase->aTerm[0].pSynonym==0 );
         1030  +
         1031  +  pPhrase->poslist.n = pIter->nData;
         1032  +  if( pExpr->pConfig->eDetail==FTS5_DETAIL_FULL ){
         1033  +    pPhrase->poslist.p = (u8*)pIter->pData;
         1034  +  }
         1035  +  pNode->iRowid = pIter->iRowid;
         1036  +  pNode->bNomatch = (pPhrase->poslist.n==0);
         1037  +  return SQLITE_OK;
         1038  +}
         1039  +
         1040  +/*
         1041  +** xNext() method for a node of type FTS5_TERM.
         1042  +*/
         1043  +static int fts5ExprNodeNext_TERM(
         1044  +  Fts5Expr *pExpr, 
         1045  +  Fts5ExprNode *pNode,
         1046  +  int bFromValid,
         1047  +  i64 iFrom
         1048  +){
         1049  +  int rc;
         1050  +  Fts5IndexIter *pIter = pNode->pNear->apPhrase[0]->aTerm[0].pIter;
         1051  +
         1052  +  assert( pNode->bEof==0 );
         1053  +  if( bFromValid ){
         1054  +    rc = sqlite3Fts5IterNextFrom(pIter, iFrom);
         1055  +  }else{
         1056  +    rc = sqlite3Fts5IterNext(pIter);
         1057  +  }
         1058  +  if( rc==SQLITE_OK && sqlite3Fts5IterEof(pIter)==0 ){
         1059  +    rc = fts5ExprNodeTest_TERM(pExpr, pNode);
         1060  +  }else{
         1061  +    pNode->bEof = 1;
         1062  +    pNode->bNomatch = 0;
         1063  +  }
         1064  +  return rc;
         1065  +}
         1066  +
         1067  +static void fts5ExprNodeTest_OR(
         1068  +  Fts5Expr *pExpr,                /* Expression of which pNode is a part */
         1069  +  Fts5ExprNode *pNode             /* Expression node to test */
         1070  +){
         1071  +  Fts5ExprNode *pNext = pNode->apChild[0];
         1072  +  int i;
         1073  +
         1074  +  for(i=1; i<pNode->nChild; i++){
         1075  +    Fts5ExprNode *pChild = pNode->apChild[i];
         1076  +    int cmp = fts5NodeCompare(pExpr, pNext, pChild);
         1077  +    if( cmp>0 || (cmp==0 && pChild->bNomatch==0) ){
         1078  +      pNext = pChild;
         1079  +    }
         1080  +  }
         1081  +  pNode->iRowid = pNext->iRowid;
         1082  +  pNode->bEof = pNext->bEof;
         1083  +  pNode->bNomatch = pNext->bNomatch;
         1084  +}
         1085  +
         1086  +static int fts5ExprNodeNext_OR(
         1087  +  Fts5Expr *pExpr, 
         1088  +  Fts5ExprNode *pNode,
         1089  +  int bFromValid,
         1090  +  i64 iFrom
         1091  +){
         1092  +  int i;
         1093  +  i64 iLast = pNode->iRowid;
         1094  +
         1095  +  for(i=0; i<pNode->nChild; i++){
         1096  +    Fts5ExprNode *p1 = pNode->apChild[i];
         1097  +    assert( p1->bEof || fts5RowidCmp(pExpr, p1->iRowid, iLast)>=0 );
         1098  +    if( p1->bEof==0 ){
         1099  +      if( (p1->iRowid==iLast) 
         1100  +       || (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0)
         1101  +      ){
         1102  +        int rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom);
         1103  +        if( rc!=SQLITE_OK ) return rc;
         1104  +      }
         1105  +    }
         1106  +  }
         1107  +
         1108  +  fts5ExprNodeTest_OR(pExpr, pNode);
         1109  +  return SQLITE_OK;
         1110  +}
         1111  +
  1015   1112   /*
  1016   1113   ** Argument pNode is an FTS5_AND node.
  1017   1114   */
  1018         -static int fts5ExprAndNextRowid(
         1115  +static int fts5ExprNodeTest_AND(
  1019   1116     Fts5Expr *pExpr,                /* Expression pPhrase belongs to */
  1020   1117     Fts5ExprNode *pAnd              /* FTS5_AND node to advance */
  1021   1118   ){
  1022   1119     int iChild;
  1023   1120     i64 iLast = pAnd->iRowid;
  1024   1121     int rc = SQLITE_OK;
  1025   1122     int bMatch;
................................................................................
  1026   1123   
  1027   1124     assert( pAnd->bEof==0 );
  1028   1125     do {
  1029   1126       pAnd->bNomatch = 0;
  1030   1127       bMatch = 1;
  1031   1128       for(iChild=0; iChild<pAnd->nChild; iChild++){
  1032   1129         Fts5ExprNode *pChild = pAnd->apChild[iChild];
  1033         -      if( 0 && pChild->eType==FTS5_STRING ){
  1034         -        /* TODO */
  1035         -      }else{
  1036         -        int cmp = fts5RowidCmp(pExpr, iLast, pChild->iRowid);
  1037         -        if( cmp>0 ){
  1038         -          /* Advance pChild until it points to iLast or laster */
  1039         -          rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast);
  1040         -          if( rc!=SQLITE_OK ) return rc;
  1041         -        }
         1130  +      int cmp = fts5RowidCmp(pExpr, iLast, pChild->iRowid);
         1131  +      if( cmp>0 ){
         1132  +        /* Advance pChild until it points to iLast or laster */
         1133  +        rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast);
         1134  +        if( rc!=SQLITE_OK ) return rc;
  1042   1135         }
  1043   1136   
  1044   1137         /* If the child node is now at EOF, so is the parent AND node. Otherwise,
  1045   1138         ** the child node is guaranteed to have advanced at least as far as
  1046   1139         ** rowid iLast. So if it is not at exactly iLast, pChild->iRowid is the
  1047   1140         ** new lastest rowid seen so far.  */
  1048   1141         assert( pChild->bEof || fts5RowidCmp(pExpr, iLast, pChild->iRowid)<=0 );
................................................................................
  1064   1157     if( pAnd->bNomatch && pAnd!=pExpr->pRoot ){
  1065   1158       fts5ExprNodeZeroPoslist(pAnd);
  1066   1159     }
  1067   1160     pAnd->iRowid = iLast;
  1068   1161     return SQLITE_OK;
  1069   1162   }
  1070   1163   
  1071         -
  1072         -/*
  1073         -** Compare the values currently indicated by the two nodes as follows:
  1074         -**
  1075         -**    res = (*p1) - (*p2)
  1076         -**
  1077         -** Nodes that point to values that come later in the iteration order are
  1078         -** considered to be larger. Nodes at EOF are the largest of all.
  1079         -**
  1080         -** This means that if the iteration order is ASC, then numerically larger
  1081         -** rowids are considered larger. Or if it is the default DESC, numerically
  1082         -** smaller rowids are larger.
  1083         -*/
  1084         -static int fts5NodeCompare(
  1085         -  Fts5Expr *pExpr,
  1086         -  Fts5ExprNode *p1, 
  1087         -  Fts5ExprNode *p2
  1088         -){
  1089         -  if( p2->bEof ) return -1;
  1090         -  if( p1->bEof ) return +1;
  1091         -  return fts5RowidCmp(pExpr, p1->iRowid, p2->iRowid);
  1092         -}
  1093         -
  1094         -/*
  1095         -** xNext() method for a node of type FTS5_TERM.
  1096         -*/
  1097         -static int fts5ExprNodeNext_Term(
         1164  +static int fts5ExprNodeNext_AND(
  1098   1165     Fts5Expr *pExpr, 
  1099   1166     Fts5ExprNode *pNode,
  1100   1167     int bFromValid,
  1101   1168     i64 iFrom
  1102   1169   ){
  1103         -  int rc;
  1104         -  Fts5IndexIter *pIter = pNode->pNear->apPhrase[0]->aTerm[0].pIter;
  1105         -
  1106         -  assert( pNode->bEof==0 );
  1107         -  if( bFromValid ){
  1108         -    rc = sqlite3Fts5IterNextFrom(pIter, iFrom);
  1109         -  }else{
  1110         -    rc = sqlite3Fts5IterNext(pIter);
  1111         -  }
  1112         -  if( rc==SQLITE_OK && sqlite3Fts5IterEof(pIter)==0 ){
  1113         -    rc = fts5ExprTokenTest(pExpr, pNode);
  1114         -  }else{
  1115         -    pNode->bEof = 1;
  1116         -    pNode->bNomatch = 0;
         1170  +  int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom);
         1171  +  if( rc==SQLITE_OK ){
         1172  +    rc = fts5ExprNodeTest_AND(pExpr, pNode);
         1173  +  }
         1174  +  return rc;
         1175  +}
         1176  +
         1177  +static int fts5ExprNodeTest_NOT(
         1178  +  Fts5Expr *pExpr,                /* Expression pPhrase belongs to */
         1179  +  Fts5ExprNode *pNode             /* FTS5_NOT node to advance */
         1180  +){
         1181  +  int rc = SQLITE_OK;
         1182  +  Fts5ExprNode *p1 = pNode->apChild[0];
         1183  +  Fts5ExprNode *p2 = pNode->apChild[1];
         1184  +  assert( pNode->nChild==2 );
         1185  +
         1186  +  while( rc==SQLITE_OK && p1->bEof==0 ){
         1187  +    int cmp = fts5NodeCompare(pExpr, p1, p2);
         1188  +    if( cmp>0 ){
         1189  +      rc = fts5ExprNodeNext(pExpr, p2, 1, p1->iRowid);
         1190  +      cmp = fts5NodeCompare(pExpr, p1, p2);
         1191  +    }
         1192  +    assert( rc!=SQLITE_OK || cmp<=0 );
         1193  +    if( cmp || p2->bNomatch ) break;
         1194  +    rc = fts5ExprNodeNext(pExpr, p1, 0, 0);
         1195  +  }
         1196  +  pNode->bEof = p1->bEof;
         1197  +  pNode->bNomatch = p1->bNomatch;
         1198  +  pNode->iRowid = p1->iRowid;
         1199  +  if( p1->bEof ){
         1200  +    fts5ExprNodeZeroPoslist(p2);
  1117   1201     }
  1118   1202     return rc;
  1119   1203   }
  1120   1204   
  1121         -/*
  1122         -** Advance node iterator pNode, part of expression pExpr. If argument
  1123         -** bFromValid is zero, then pNode is advanced exactly once. Or, if argument
  1124         -** bFromValid is non-zero, then pNode is advanced until it is at or past
  1125         -** rowid value iFrom. Whether "past" means "less than" or "greater than"
  1126         -** depends on whether this is an ASC or DESC iterator.
  1127         -*/
  1128         -static int fts5ExprNodeNext_Fallback(
         1205  +static int fts5ExprNodeNext_NOT(
  1129   1206     Fts5Expr *pExpr, 
  1130   1207     Fts5ExprNode *pNode,
  1131   1208     int bFromValid,
  1132   1209     i64 iFrom
  1133   1210   ){
  1134         -  int rc = SQLITE_OK;
  1135         -
  1136         -  if( pNode->bEof==0 ){
  1137         -    switch( pNode->eType ){
  1138         -      case FTS5_STRING: {
  1139         -        rc = fts5ExprNearAdvanceFirst(pExpr, pNode, bFromValid, iFrom);
  1140         -        break;
  1141         -      };
  1142         -
  1143         -      case FTS5_TERM: {
  1144         -        Fts5IndexIter *pIter = pNode->pNear->apPhrase[0]->aTerm[0].pIter;
  1145         -        if( bFromValid ){
  1146         -          rc = sqlite3Fts5IterNextFrom(pIter, iFrom);
  1147         -        }else{
  1148         -          rc = sqlite3Fts5IterNext(pIter);
  1149         -        }
  1150         -        if( rc==SQLITE_OK && sqlite3Fts5IterEof(pIter)==0 ){
  1151         -          assert( rc==SQLITE_OK );
  1152         -          rc = fts5ExprTokenTest(pExpr, pNode);
  1153         -        }else{
  1154         -          pNode->bEof = 1;
  1155         -          pNode->bNomatch = 0;
  1156         -        }
  1157         -        return rc;
  1158         -      };
  1159         -
  1160         -      case FTS5_AND: {
  1161         -        Fts5ExprNode *pLeft = pNode->apChild[0];
  1162         -        rc = fts5ExprNodeNext(pExpr, pLeft, bFromValid, iFrom);
  1163         -        break;
  1164         -      }
  1165         -
  1166         -      case FTS5_OR: {
  1167         -        int i;
  1168         -        i64 iLast = pNode->iRowid;
  1169         -
  1170         -        for(i=0; rc==SQLITE_OK && i<pNode->nChild; i++){
  1171         -          Fts5ExprNode *p1 = pNode->apChild[i];
  1172         -          assert( p1->bEof || fts5RowidCmp(pExpr, p1->iRowid, iLast)>=0 );
  1173         -          if( p1->bEof==0 ){
  1174         -            if( (p1->iRowid==iLast) 
  1175         -             || (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0)
  1176         -            ){
  1177         -              rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom);
  1178         -            }
  1179         -          }
  1180         -        }
  1181         -
  1182         -        break;
  1183         -      }
  1184         -
  1185         -      default: assert( pNode->eType==FTS5_NOT ); {
  1186         -        assert( pNode->nChild==2 );
  1187         -        rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom);
  1188         -        break;
  1189         -      }
  1190         -    }
  1191         -
  1192         -    if( rc==SQLITE_OK ){
  1193         -      rc = fts5ExprNodeNextMatch(pExpr, pNode);
  1194         -    }
         1211  +  int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom);
         1212  +  if( rc==SQLITE_OK ){
         1213  +    rc = fts5ExprNodeTest_NOT(pExpr, pNode);
  1195   1214     }
  1196         -
  1197         -  /* Assert that if bFromValid was true, either:
  1198         -  **
  1199         -  **   a) an error occurred, or
  1200         -  **   b) the node is now at EOF, or
  1201         -  **   c) the node is now at or past rowid iFrom.
  1202         -  */
  1203         -  assert( bFromValid==0 
  1204         -      || rc!=SQLITE_OK                                                  /* a */
  1205         -      || pNode->bEof                                                    /* b */
  1206         -      || pNode->iRowid==iFrom || pExpr->bDesc==(pNode->iRowid<iFrom)    /* c */
  1207         -  );
  1208         -
  1209         -  assert( pNode->bNomatch==0 || rc==SQLITE_OK );
  1210   1215     return rc;
  1211   1216   }
  1212         -
  1213   1217   
  1214   1218   /*
  1215   1219   ** If pNode currently points to a match, this function returns SQLITE_OK
  1216   1220   ** without modifying it. Otherwise, pNode is advanced until it does point
  1217   1221   ** to a match or EOF is reached.
  1218   1222   */
  1219         -static int fts5ExprNodeNextMatch(
         1223  +static int fts5ExprNodeTest(
  1220   1224     Fts5Expr *pExpr,                /* Expression of which pNode is a part */
  1221   1225     Fts5ExprNode *pNode             /* Expression node to test */
  1222   1226   ){
  1223   1227     int rc = SQLITE_OK;
  1224   1228     if( pNode->bEof==0 ){
  1225   1229       switch( pNode->eType ){
  1226   1230   
  1227   1231         case FTS5_STRING: {
  1228         -        /* Advance the iterators until they all point to the same rowid */
  1229         -        rc = fts5ExprNearNextMatch(pExpr, pNode);
         1232  +        rc = fts5ExprNodeTest_STRING(pExpr, pNode);
  1230   1233           break;
  1231   1234         }
  1232   1235   
  1233   1236         case FTS5_TERM: {
  1234         -        rc = fts5ExprTokenTest(pExpr, pNode);
         1237  +        rc = fts5ExprNodeTest_TERM(pExpr, pNode);
  1235   1238           break;
  1236   1239         }
  1237   1240   
  1238   1241         case FTS5_AND: {
  1239         -        rc = fts5ExprAndNextRowid(pExpr, pNode);
         1242  +        rc = fts5ExprNodeTest_AND(pExpr, pNode);
  1240   1243           break;
  1241   1244         }
  1242   1245   
  1243   1246         case FTS5_OR: {
  1244         -        Fts5ExprNode *pNext = pNode->apChild[0];
  1245         -        int i;
  1246         -
  1247         -        for(i=1; i<pNode->nChild; i++){
  1248         -          Fts5ExprNode *pChild = pNode->apChild[i];
  1249         -          int cmp = fts5NodeCompare(pExpr, pNext, pChild);
  1250         -          if( cmp>0 || (cmp==0 && pChild->bNomatch==0) ){
  1251         -            pNext = pChild;
  1252         -          }
  1253         -        }
  1254         -        pNode->iRowid = pNext->iRowid;
  1255         -        pNode->bEof = pNext->bEof;
  1256         -        pNode->bNomatch = pNext->bNomatch;
         1247  +        fts5ExprNodeTest_OR(pExpr, pNode);
  1257   1248           break;
  1258   1249         }
  1259   1250   
  1260   1251         default: assert( pNode->eType==FTS5_NOT ); {
  1261         -        Fts5ExprNode *p1 = pNode->apChild[0];
  1262         -        Fts5ExprNode *p2 = pNode->apChild[1];
  1263         -        assert( pNode->nChild==2 );
  1264         -
  1265         -        while( rc==SQLITE_OK && p1->bEof==0 ){
  1266         -          int cmp = fts5NodeCompare(pExpr, p1, p2);
  1267         -          if( cmp>0 ){
  1268         -            rc = fts5ExprNodeNext(pExpr, p2, 1, p1->iRowid);
  1269         -            cmp = fts5NodeCompare(pExpr, p1, p2);
  1270         -          }
  1271         -          assert( rc!=SQLITE_OK || cmp<=0 );
  1272         -          if( cmp || p2->bNomatch ) break;
  1273         -          rc = fts5ExprNodeNext(pExpr, p1, 0, 0);
  1274         -        }
  1275         -        pNode->bEof = p1->bEof;
  1276         -        pNode->bNomatch = p1->bNomatch;
  1277         -        pNode->iRowid = p1->iRowid;
  1278         -        if( p1->bEof ){
  1279         -          fts5ExprNodeZeroPoslist(p2);
  1280         -        }
         1252  +        rc = fts5ExprNodeTest_NOT(pExpr, pNode);
  1281   1253           break;
  1282   1254         }
  1283   1255       }
  1284   1256     }
  1285   1257     return rc;
  1286   1258   }
  1287   1259   
................................................................................
  1325   1297           assert( pNode->eType==FTS5_NOT );
  1326   1298           pNode->bEof = pNode->apChild[0]->bEof;
  1327   1299           break;
  1328   1300       }
  1329   1301     }
  1330   1302   
  1331   1303     if( rc==SQLITE_OK ){
  1332         -    rc = fts5ExprNodeNextMatch(pExpr, pNode);
         1304  +    rc = fts5ExprNodeTest(pExpr, pNode);
  1333   1305     }
  1334   1306     return rc;
  1335   1307   }
  1336   1308   
  1337   1309   
  1338   1310   /*
  1339   1311   ** Begin iterating through the set of documents in index pIdx matched by
................................................................................
  1361   1333       /* If not at EOF but the current rowid occurs earlier than iFirst in
  1362   1334       ** the iteration order, move to document iFirst or later. */
  1363   1335       if( pRoot->bEof==0 && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 ){
  1364   1336         rc = fts5ExprNodeNext(p, pRoot, 1, iFirst);
  1365   1337       }
  1366   1338   
  1367   1339       /* If the iterator is not at a real match, skip forward until it is. */
  1368         -    while( pRoot->bNomatch && rc==SQLITE_OK && pRoot->bEof==0 ){
         1340  +    while( pRoot->bNomatch ){
         1341  +      assert( pRoot->bEof==0 && rc==SQLITE_OK );
  1369   1342         rc = fts5ExprNodeNext(p, pRoot, 0, 0);
  1370   1343       }
  1371   1344     }
  1372   1345     return rc;
  1373   1346   }
  1374   1347   
  1375   1348   /*
................................................................................
  1686   1659       /* All the allocations succeeded. Put the expression object together. */
  1687   1660       pNew->pIndex = pExpr->pIndex;
  1688   1661       pNew->pConfig = pExpr->pConfig;
  1689   1662       pNew->nPhrase = 1;
  1690   1663       pNew->apExprPhrase[0] = sCtx.pPhrase;
  1691   1664       pNew->pRoot->pNear->apPhrase[0] = sCtx.pPhrase;
  1692   1665       pNew->pRoot->pNear->nPhrase = 1;
  1693         -    pNew->pRoot->xNext = fts5ExprNodeNext_Fallback;
  1694   1666       sCtx.pPhrase->pNode = pNew->pRoot;
  1695   1667   
  1696   1668       if( pOrig->nTerm==1 && pOrig->aTerm[0].pSynonym==0 ){
  1697   1669         pNew->pRoot->eType = FTS5_TERM;
         1670  +      pNew->pRoot->xNext = fts5ExprNodeNext_TERM;
  1698   1671       }else{
  1699   1672         pNew->pRoot->eType = FTS5_STRING;
         1673  +      pNew->pRoot->xNext = fts5ExprNodeNext_STRING;
  1700   1674       }
  1701   1675     }else{
  1702   1676       sqlite3Fts5ExprFree(pNew);
  1703   1677       fts5ExprPhraseFree(sCtx.pPhrase);
  1704   1678       pNew = 0;
  1705   1679     }
  1706   1680   
................................................................................
  1839   1813   
  1840   1814     if( pNear ){
  1841   1815       pNear->pColset = pColset;
  1842   1816     }else{
  1843   1817       sqlite3_free(pColset);
  1844   1818     }
  1845   1819   }
         1820  +
         1821  +static void fts5ExprAssignXNext(Fts5ExprNode *pNode){
         1822  +  switch( pNode->eType ){
         1823  +    case FTS5_STRING: {
         1824  +      Fts5ExprNearset *pNear = pNode->pNear;
         1825  +      if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1 
         1826  +       && pNear->apPhrase[0]->aTerm[0].pSynonym==0
         1827  +      ){
         1828  +        pNode->eType = FTS5_TERM;
         1829  +        pNode->xNext = fts5ExprNodeNext_TERM;
         1830  +      }else{
         1831  +        pNode->xNext = fts5ExprNodeNext_STRING;
         1832  +      }
         1833  +      break;
         1834  +    };
         1835  +
         1836  +    case FTS5_OR: {
         1837  +      pNode->xNext = fts5ExprNodeNext_OR;
         1838  +      break;
         1839  +    };
         1840  +
         1841  +    case FTS5_AND: {
         1842  +      pNode->xNext = fts5ExprNodeNext_AND;
         1843  +      break;
         1844  +    };
         1845  +
         1846  +    default: assert( pNode->eType==FTS5_NOT ); {
         1847  +      pNode->xNext = fts5ExprNodeNext_NOT;
         1848  +      break;
         1849  +    };
         1850  +  }
         1851  +}
  1846   1852   
  1847   1853   static void fts5ExprAddChildren(Fts5ExprNode *p, Fts5ExprNode *pSub){
  1848   1854     if( p->eType!=FTS5_NOT && pSub->eType==p->eType ){
  1849   1855       int nByte = sizeof(Fts5ExprNode*) * pSub->nChild;
  1850   1856       memcpy(&p->apChild[p->nChild], pSub->apChild, nByte);
  1851   1857       p->nChild += pSub->nChild;
  1852   1858       sqlite3_free(pSub);
................................................................................
  1887   1893         if( pRight->eType==eType ) nChild += pRight->nChild-1;
  1888   1894       }
  1889   1895   
  1890   1896       nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
  1891   1897       pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
  1892   1898   
  1893   1899       if( pRet ){
  1894         -      pRet->xNext = fts5ExprNodeNext_Fallback;
  1895   1900         pRet->eType = eType;
  1896   1901         pRet->pNear = pNear;
         1902  +      fts5ExprAssignXNext(pRet);
  1897   1903         if( eType==FTS5_STRING ){
  1898   1904           int iPhrase;
  1899   1905           for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
  1900   1906             pNear->apPhrase[iPhrase]->pNode = pRet;
  1901   1907           }
  1902         -        if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1 ){
  1903         -          if( pNear->apPhrase[0]->aTerm[0].pSynonym==0 ){
  1904         -            pRet->eType = FTS5_TERM;
  1905         -            pRet->xNext = fts5ExprNodeNext_Term;
  1906         -          }
  1907         -        }else if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
         1908  +
         1909  +        if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL 
         1910  +         && (pNear->nPhrase!=1 || pNear->apPhrase[0]->nTerm!=1)
         1911  +        ){
  1908   1912             assert( pParse->rc==SQLITE_OK );
  1909   1913             pParse->rc = SQLITE_ERROR;
  1910   1914             assert( pParse->zErr==0 );
  1911   1915             pParse->zErr = sqlite3_mprintf(
  1912   1916                 "fts5: %s queries are not supported (detail!=full)", 
  1913   1917                 pNear->nPhrase==1 ? "phrase": "NEAR"
  1914   1918             );
  1915   1919             sqlite3_free(pRet);
  1916   1920             pRet = 0;
  1917   1921           }
         1922  +
  1918   1923         }else{
  1919   1924           fts5ExprAddChildren(pRet, pLeft);
  1920   1925           fts5ExprAddChildren(pRet, pRight);
  1921   1926         }
  1922   1927       }
  1923   1928     }
  1924   1929   

Changes to ext/fts5/fts5_index.c.

   514    514   
   515    515     /* Invoked to set output variables. */
   516    516     void (*xSetOutputs)(Fts5Iter*, Fts5SegIter*);
   517    517   
   518    518     int nSeg;                       /* Size of aSeg[] array */
   519    519     int bRev;                       /* True to iterate in reverse order */
   520    520     u8 bSkipEmpty;                  /* True to skip deleted entries */
   521         -  u8 bEof;                        /* True at EOF */
   522    521     u8 bFiltered;                   /* True if column-filter already applied */
   523    522   
   524    523     i64 iSwitchRowid;               /* Firstest rowid of other than aFirst[1] */
   525    524     Fts5CResult *aFirst;            /* Current merge state (see above) */
   526    525     Fts5SegIter aSeg[1];            /* Array of segment iterators */
   527    526   };
   528    527   
................................................................................
  2261   2260     Fts5StructureSegment *pSeg,     /* Description of segment */
  2262   2261     Fts5SegIter *pIter              /* Object to populate */
  2263   2262   ){
  2264   2263     int iPg = 1;
  2265   2264     int bGe = (flags & FTS5INDEX_QUERY_SCAN);
  2266   2265     int bDlidx = 0;                 /* True if there is a doclist-index */
  2267   2266   
  2268         -  static int nCall = 0;
  2269         -  nCall++;
  2270         -
  2271   2267     assert( bGe==0 || (flags & FTS5INDEX_QUERY_DESC)==0 );
  2272   2268     assert( pTerm && nTerm );
  2273   2269     memset(pIter, 0, sizeof(*pIter));
  2274   2270     pIter->pSeg = pSeg;
  2275   2271   
  2276   2272     /* This block sets stack variable iPg to the leaf page number that may
  2277   2273     ** contain term (pTerm/nTerm), if it is present in the segment. */
................................................................................
  2455   2451   ** are correct.
  2456   2452   */
  2457   2453   static void fts5AssertMultiIterSetup(Fts5Index *p, Fts5Iter *pIter){
  2458   2454     if( p->rc==SQLITE_OK ){
  2459   2455       Fts5SegIter *pFirst = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
  2460   2456       int i;
  2461   2457   
  2462         -    assert( (pFirst->pLeaf==0)==pIter->bEof );
         2458  +    assert( (pFirst->pLeaf==0)==pIter->base.bEof );
  2463   2459   
  2464   2460       /* Check that pIter->iSwitchRowid is set correctly. */
  2465   2461       for(i=0; i<pIter->nSeg; i++){
  2466   2462         Fts5SegIter *p1 = &pIter->aSeg[i];
  2467   2463         assert( p1==pFirst 
  2468   2464              || p1->pLeaf==0 
  2469   2465              || fts5BufferCompare(&pFirst->term, &p1->term) 
................................................................................
  2727   2723   }
  2728   2724   
  2729   2725   /*
  2730   2726   ** Set the pIter->bEof variable based on the state of the sub-iterators.
  2731   2727   */
  2732   2728   static void fts5MultiIterSetEof(Fts5Iter *pIter){
  2733   2729     Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
  2734         -  pIter->bEof = pSeg->pLeaf==0;
         2730  +  pIter->base.bEof = pSeg->pLeaf==0;
  2735   2731     pIter->iSwitchRowid = pSeg->iRowid;
  2736   2732   }
  2737   2733   
  2738   2734   /*
  2739   2735   ** Move the iterator to the next entry. 
  2740   2736   **
  2741   2737   ** If an error occurs, an error code is left in Fts5Index.rc. It is not 
................................................................................
  2829   2825       pNew->aFirst = (Fts5CResult*)&pNew->aSeg[nSlot];
  2830   2826       pNew->pIndex = p;
  2831   2827       pNew->xSetOutputs = fts5IterSetOutputs_Noop;
  2832   2828     }
  2833   2829     return pNew;
  2834   2830   }
  2835   2831   
  2836         -/*
  2837         -** Allocate a new Fts5Iter object.
  2838         -**
  2839         -** The new object will be used to iterate through data in structure pStruct.
  2840         -** If iLevel is -ve, then all data in all segments is merged. Or, if iLevel
  2841         -** is zero or greater, data from the first nSegment segments on level iLevel
  2842         -** is merged.
  2843         -**
  2844         -** The iterator initially points to the first term/rowid entry in the 
  2845         -** iterated data.
  2846         -*/
  2847         -static void fts5MultiIterNew(
  2848         -  Fts5Index *p,                   /* FTS5 backend to iterate within */
  2849         -  Fts5Structure *pStruct,         /* Structure of specific index */
  2850         -  int bSkipEmpty,                 /* True to ignore delete-keys */
  2851         -  int flags,                      /* FTS5INDEX_QUERY_XXX flags */
  2852         -  const u8 *pTerm, int nTerm,     /* Term to seek to (or NULL/0) */
  2853         -  int iLevel,                     /* Level to iterate (-1 for all) */
  2854         -  int nSegment,                   /* Number of segments to merge (iLevel>=0) */
  2855         -  Fts5Iter **ppOut                /* New object */
  2856         -){
  2857         -  int nSeg = 0;                   /* Number of segment-iters in use */
  2858         -  int iIter = 0;                  /* */
  2859         -  int iSeg;                       /* Used to iterate through segments */
  2860         -  Fts5Buffer buf = {0,0,0};       /* Buffer used by fts5SegIterSeekInit() */
  2861         -  Fts5StructureLevel *pLvl;
  2862         -  Fts5Iter *pNew;
  2863         -
  2864         -  assert( (pTerm==0 && nTerm==0) || iLevel<0 );
  2865         -
  2866         -  /* Allocate space for the new multi-seg-iterator. */
  2867         -  if( p->rc==SQLITE_OK ){
  2868         -    if( iLevel<0 ){
  2869         -      assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) );
  2870         -      nSeg = pStruct->nSegment;
  2871         -      nSeg += (p->pHash ? 1 : 0);
  2872         -    }else{
  2873         -      nSeg = MIN(pStruct->aLevel[iLevel].nSeg, nSegment);
  2874         -    }
  2875         -  }
  2876         -  *ppOut = pNew = fts5MultiIterAlloc(p, nSeg);
  2877         -  if( pNew==0 ) return;
  2878         -  pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC));
  2879         -  pNew->bSkipEmpty = (u8)bSkipEmpty;
  2880         -  pNew->pStruct = pStruct;
  2881         -  fts5StructureRef(pStruct);
  2882         -
  2883         -  /* Initialize each of the component segment iterators. */
  2884         -  if( iLevel<0 ){
  2885         -    Fts5StructureLevel *pEnd = &pStruct->aLevel[pStruct->nLevel];
  2886         -    if( p->pHash ){
  2887         -      /* Add a segment iterator for the current contents of the hash table. */
  2888         -      Fts5SegIter *pIter = &pNew->aSeg[iIter++];
  2889         -      fts5SegIterHashInit(p, pTerm, nTerm, flags, pIter);
  2890         -    }
  2891         -    for(pLvl=&pStruct->aLevel[0]; pLvl<pEnd; pLvl++){
  2892         -      for(iSeg=pLvl->nSeg-1; iSeg>=0; iSeg--){
  2893         -        Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg];
  2894         -        Fts5SegIter *pIter = &pNew->aSeg[iIter++];
  2895         -        if( pTerm==0 ){
  2896         -          fts5SegIterInit(p, pSeg, pIter);
         2832  +static void fts5PoslistCallback(
         2833  +  Fts5Index *p, 
         2834  +  void *pContext, 
         2835  +  const u8 *pChunk, int nChunk
         2836  +){
         2837  +  assert_nc( nChunk>=0 );
         2838  +  if( nChunk>0 ){
         2839  +    fts5BufferSafeAppendBlob((Fts5Buffer*)pContext, pChunk, nChunk);
         2840  +  }
         2841  +}
         2842  +
         2843  +typedef struct PoslistCallbackCtx PoslistCallbackCtx;
         2844  +struct PoslistCallbackCtx {
         2845  +  Fts5Buffer *pBuf;               /* Append to this buffer */
         2846  +  Fts5Colset *pColset;            /* Restrict matches to this column */
         2847  +  int eState;                     /* See above */
         2848  +};
         2849  +
         2850  +typedef struct PoslistOffsetsCtx PoslistOffsetsCtx;
         2851  +struct PoslistOffsetsCtx {
         2852  +  Fts5Buffer *pBuf;               /* Append to this buffer */
         2853  +  Fts5Colset *pColset;            /* Restrict matches to this column */
         2854  +  int iRead;
         2855  +  int iWrite;
         2856  +};
         2857  +
         2858  +/*
         2859  +** TODO: Make this more efficient!
         2860  +*/
         2861  +static int fts5IndexColsetTest(Fts5Colset *pColset, int iCol){
         2862  +  int i;
         2863  +  for(i=0; i<pColset->nCol; i++){
         2864  +    if( pColset->aiCol[i]==iCol ) return 1;
         2865  +  }
         2866  +  return 0;
         2867  +}
         2868  +
         2869  +static void fts5PoslistOffsetsCallback(
         2870  +  Fts5Index *p, 
         2871  +  void *pContext, 
         2872  +  const u8 *pChunk, int nChunk
         2873  +){
         2874  +  PoslistOffsetsCtx *pCtx = (PoslistOffsetsCtx*)pContext;
         2875  +  assert_nc( nChunk>=0 );
         2876  +  if( nChunk>0 ){
         2877  +    int i = 0;
         2878  +    while( i<nChunk ){
         2879  +      int iVal;
         2880  +      i += fts5GetVarint32(&pChunk[i], iVal);
         2881  +      iVal += pCtx->iRead - 2;
         2882  +      pCtx->iRead = iVal;
         2883  +      if( fts5IndexColsetTest(pCtx->pColset, iVal) ){
         2884  +        fts5BufferSafeAppendVarint(pCtx->pBuf, iVal + 2 - pCtx->iWrite);
         2885  +        pCtx->iWrite = iVal;
         2886  +      }
         2887  +    }
         2888  +  }
         2889  +}
         2890  +
         2891  +static void fts5PoslistFilterCallback(
         2892  +  Fts5Index *p, 
         2893  +  void *pContext, 
         2894  +  const u8 *pChunk, int nChunk
         2895  +){
         2896  +  PoslistCallbackCtx *pCtx = (PoslistCallbackCtx*)pContext;
         2897  +  assert_nc( nChunk>=0 );
         2898  +  if( nChunk>0 ){
         2899  +    /* Search through to find the first varint with value 1. This is the
         2900  +    ** start of the next columns hits. */
         2901  +    int i = 0;
         2902  +    int iStart = 0;
         2903  +
         2904  +    if( pCtx->eState==2 ){
         2905  +      int iCol;
         2906  +      fts5FastGetVarint32(pChunk, i, iCol);
         2907  +      if( fts5IndexColsetTest(pCtx->pColset, iCol) ){
         2908  +        pCtx->eState = 1;
         2909  +        fts5BufferSafeAppendVarint(pCtx->pBuf, 1);
         2910  +      }else{
         2911  +        pCtx->eState = 0;
         2912  +      }
         2913  +    }
         2914  +
         2915  +    do {
         2916  +      while( i<nChunk && pChunk[i]!=0x01 ){
         2917  +        while( pChunk[i] & 0x80 ) i++;
         2918  +        i++;
         2919  +      }
         2920  +      if( pCtx->eState ){
         2921  +        fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart);
         2922  +      }
         2923  +      if( i<nChunk ){
         2924  +        int iCol;
         2925  +        iStart = i;
         2926  +        i++;
         2927  +        if( i>=nChunk ){
         2928  +          pCtx->eState = 2;
  2897   2929           }else{
  2898         -          fts5SegIterSeekInit(p, &buf, pTerm, nTerm, flags, pSeg, pIter);
  2899         -        }
  2900         -      }
  2901         -    }
  2902         -  }else{
  2903         -    pLvl = &pStruct->aLevel[iLevel];
  2904         -    for(iSeg=nSeg-1; iSeg>=0; iSeg--){
  2905         -      fts5SegIterInit(p, &pLvl->aSeg[iSeg], &pNew->aSeg[iIter++]);
  2906         -    }
  2907         -  }
  2908         -  assert( iIter==nSeg );
  2909         -
  2910         -  /* If the above was successful, each component iterators now points 
  2911         -  ** to the first entry in its segment. In this case initialize the 
  2912         -  ** aFirst[] array. Or, if an error has occurred, free the iterator
  2913         -  ** object and set the output variable to NULL.  */
  2914         -  if( p->rc==SQLITE_OK ){
  2915         -    for(iIter=pNew->nSeg-1; iIter>0; iIter--){
  2916         -      int iEq;
  2917         -      if( (iEq = fts5MultiIterDoCompare(pNew, iIter)) ){
  2918         -        Fts5SegIter *pSeg = &pNew->aSeg[iEq];
  2919         -        if( p->rc==SQLITE_OK ) pSeg->xNext(p, pSeg, 0);
  2920         -        fts5MultiIterAdvanced(p, pNew, iEq, iIter);
  2921         -      }
  2922         -    }
  2923         -    fts5MultiIterSetEof(pNew);
  2924         -    fts5AssertMultiIterSetup(p, pNew);
  2925         -
  2926         -    if( pNew->bSkipEmpty && fts5MultiIterIsEmpty(p, pNew) ){
  2927         -      fts5MultiIterNext(p, pNew, 0, 0);
  2928         -    }
  2929         -  }else{
  2930         -    fts5MultiIterFree(p, pNew);
  2931         -    *ppOut = 0;
  2932         -  }
  2933         -  fts5BufferFree(&buf);
  2934         -}
  2935         -
  2936         -/*
  2937         -** Create an Fts5Iter that iterates through the doclist provided
  2938         -** as the second argument.
  2939         -*/
  2940         -static void fts5MultiIterNew2(
  2941         -  Fts5Index *p,                   /* FTS5 backend to iterate within */
  2942         -  Fts5Data *pData,                /* Doclist to iterate through */
  2943         -  int bDesc,                      /* True for descending rowid order */
  2944         -  Fts5Iter **ppOut                /* New object */
  2945         -){
  2946         -  Fts5Iter *pNew;
  2947         -  pNew = fts5MultiIterAlloc(p, 2);
  2948         -  if( pNew ){
  2949         -    Fts5SegIter *pIter = &pNew->aSeg[1];
  2950         -
  2951         -    pNew->bFiltered = 1;
  2952         -    pIter->flags = FTS5_SEGITER_ONETERM;
  2953         -    if( pData->szLeaf>0 ){
  2954         -      pIter->pLeaf = pData;
  2955         -      pIter->iLeafOffset = fts5GetVarint(pData->p, (u64*)&pIter->iRowid);
  2956         -      pIter->iEndofDoclist = pData->nn;
  2957         -      pNew->aFirst[1].iFirst = 1;
  2958         -      if( bDesc ){
  2959         -        pNew->bRev = 1;
  2960         -        pIter->flags |= FTS5_SEGITER_REVERSE;
  2961         -        fts5SegIterReverseInitPage(p, pIter);
  2962         -      }else{
  2963         -        fts5SegIterLoadNPos(p, pIter);
  2964         -      }
  2965         -      pData = 0;
  2966         -    }else{
  2967         -      pNew->bEof = 1;
  2968         -    }
  2969         -    fts5SegIterSetNext(p, pIter);
  2970         -
  2971         -    *ppOut = pNew;
  2972         -  }
  2973         -
  2974         -  fts5DataRelease(pData);
  2975         -}
  2976         -
  2977         -/*
  2978         -** Return true if the iterator is at EOF or if an error has occurred. 
  2979         -** False otherwise.
  2980         -*/
  2981         -static int fts5MultiIterEof(Fts5Index *p, Fts5Iter *pIter){
  2982         -  assert( p->rc 
  2983         -      || (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->bEof 
  2984         -  );
  2985         -  return (p->rc || pIter->bEof);
  2986         -}
  2987         -
  2988         -/*
  2989         -** Return the rowid of the entry that the iterator currently points
  2990         -** to. If the iterator points to EOF when this function is called the
  2991         -** results are undefined.
  2992         -*/
  2993         -static i64 fts5MultiIterRowid(Fts5Iter *pIter){
  2994         -  assert( pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf );
  2995         -  return pIter->aSeg[ pIter->aFirst[1].iFirst ].iRowid;
  2996         -}
  2997         -
  2998         -/*
  2999         -** Move the iterator to the next entry at or following iMatch.
  3000         -*/
  3001         -static void fts5MultiIterNextFrom(
  3002         -  Fts5Index *p, 
  3003         -  Fts5Iter *pIter, 
  3004         -  i64 iMatch
  3005         -){
  3006         -  while( 1 ){
  3007         -    i64 iRowid;
  3008         -    fts5MultiIterNext(p, pIter, 1, iMatch);
  3009         -    if( fts5MultiIterEof(p, pIter) ) break;
  3010         -    iRowid = fts5MultiIterRowid(pIter);
  3011         -    if( pIter->bRev==0 && iRowid>=iMatch ) break;
  3012         -    if( pIter->bRev!=0 && iRowid<=iMatch ) break;
  3013         -  }
  3014         -}
  3015         -
  3016         -/*
  3017         -** Return a pointer to a buffer containing the term associated with the 
  3018         -** entry that the iterator currently points to.
  3019         -*/
  3020         -static const u8 *fts5MultiIterTerm(Fts5Iter *pIter, int *pn){
  3021         -  Fts5SegIter *p = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
  3022         -  *pn = p->term.n;
  3023         -  return p->term.p;
         2930  +          fts5FastGetVarint32(pChunk, i, iCol);
         2931  +          pCtx->eState = fts5IndexColsetTest(pCtx->pColset, iCol);
         2932  +          if( pCtx->eState ){
         2933  +            fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart);
         2934  +            iStart = i;
         2935  +          }
         2936  +        }
         2937  +      }
         2938  +    }while( i<nChunk );
         2939  +  }
  3024   2940   }
  3025   2941   
  3026   2942   static void fts5ChunkIterate(
  3027   2943     Fts5Index *p,                   /* Index object */
  3028   2944     Fts5SegIter *pSeg,              /* Poslist of this iterator */
  3029   2945     void *pCtx,                     /* Context pointer for xChunk callback */
  3030   2946     void (*xChunk)(Fts5Index*, void*, const u8*, int)
................................................................................
  3060   2976           pSeg->pNextLeaf = pData;
  3061   2977           pData = 0;
  3062   2978         }
  3063   2979       }
  3064   2980     }
  3065   2981   }
  3066   2982   
  3067         -
         2983  +/*
         2984  +** Iterator pIter currently points to a valid entry (not EOF). This
         2985  +** function appends the position list data for the current entry to
         2986  +** buffer pBuf. It does not make a copy of the position-list size
         2987  +** field.
         2988  +*/
         2989  +static void fts5SegiterPoslist(
         2990  +  Fts5Index *p,
         2991  +  Fts5SegIter *pSeg,
         2992  +  Fts5Colset *pColset,
         2993  +  Fts5Buffer *pBuf
         2994  +){
         2995  +  if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){
         2996  +    if( pColset==0 ){
         2997  +      fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
         2998  +    }else{
         2999  +      if( p->pConfig->eDetail==FTS5_DETAIL_FULL ){
         3000  +        PoslistCallbackCtx sCtx;
         3001  +        sCtx.pBuf = pBuf;
         3002  +        sCtx.pColset = pColset;
         3003  +        sCtx.eState = fts5IndexColsetTest(pColset, 0);
         3004  +        assert( sCtx.eState==0 || sCtx.eState==1 );
         3005  +        fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback);
         3006  +      }else{
         3007  +        PoslistOffsetsCtx sCtx;
         3008  +        memset(&sCtx, 0, sizeof(sCtx));
         3009  +        sCtx.pBuf = pBuf;
         3010  +        sCtx.pColset = pColset;
         3011  +        fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistOffsetsCallback);
         3012  +      }
         3013  +    }
         3014  +  }
         3015  +}
         3016  +
         3017  +/*
         3018  +** IN/OUT parameter (*pa) points to a position list n bytes in size. If
         3019  +** the position list contains entries for column iCol, then (*pa) is set
         3020  +** to point to the sub-position-list for that column and the number of
         3021  +** bytes in it returned. Or, if the argument position list does not
         3022  +** contain any entries for column iCol, return 0.
         3023  +*/
         3024  +static int fts5IndexExtractCol(
         3025  +  const u8 **pa,                  /* IN/OUT: Pointer to poslist */
         3026  +  int n,                          /* IN: Size of poslist in bytes */
         3027  +  int iCol                        /* Column to extract from poslist */
         3028  +){
         3029  +  int iCurrent = 0;               /* Anything before the first 0x01 is col 0 */
         3030  +  const u8 *p = *pa;
         3031  +  const u8 *pEnd = &p[n];         /* One byte past end of position list */
         3032  +
         3033  +  while( iCol>iCurrent ){
         3034  +    /* Advance pointer p until it points to pEnd or an 0x01 byte that is
         3035  +    ** not part of a varint. Note that it is not possible for a negative
         3036  +    ** or extremely large varint to occur within an uncorrupted position 
         3037  +    ** list. So the last byte of each varint may be assumed to have a clear
         3038  +    ** 0x80 bit.  */
         3039  +    while( *p!=0x01 ){
         3040  +      while( *p++ & 0x80 );
         3041  +      if( p>=pEnd ) return 0;
         3042  +    }
         3043  +    *pa = p++;
         3044  +    iCurrent = *p++;
         3045  +    if( iCurrent & 0x80 ){
         3046  +      p--;
         3047  +      p += fts5GetVarint32(p, iCurrent);
         3048  +    }
         3049  +  }
         3050  +  if( iCol!=iCurrent ) return 0;
         3051  +
         3052  +  /* Advance pointer p until it points to pEnd or an 0x01 byte that is
         3053  +  ** not part of a varint */
         3054  +  while( p<pEnd && *p!=0x01 ){
         3055  +    while( *p++ & 0x80 );
         3056  +  }
         3057  +
         3058  +  return p - (*pa);
         3059  +}
         3060  +
         3061  +static int fts5IndexExtractColset (
         3062  +  Fts5Colset *pColset,            /* Colset to filter on */
         3063  +  const u8 *pPos, int nPos,       /* Position list */
         3064  +  Fts5Buffer *pBuf                /* Output buffer */
         3065  +){
         3066  +  int rc = SQLITE_OK;
         3067  +  int i;
         3068  +
         3069  +  fts5BufferZero(pBuf);
         3070  +  for(i=0; i<pColset->nCol; i++){
         3071  +    const u8 *pSub = pPos;
         3072  +    int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]);
         3073  +    if( nSub ){
         3074  +      fts5BufferAppendBlob(&rc, pBuf, nSub, pSub);
         3075  +    }
         3076  +  }
         3077  +  return rc;
         3078  +}
         3079  +
         3080  +/*
         3081  +** xSetOutputs callback used by detail=none tables.
         3082  +*/
         3083  +static void fts5IterSetOutputs_None(Fts5Iter *pIter, Fts5SegIter *pSeg){
         3084  +  assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_NONE );
         3085  +  pIter->base.iRowid = pSeg->iRowid;
         3086  +  pIter->base.nData = pSeg->nPos;
         3087  +}
         3088  +
         3089  +/*
         3090  +** xSetOutputs callback used by detail=full and detail=col tables when no
         3091  +** column filters are specified.
         3092  +*/
         3093  +static void fts5IterSetOutputs_Nocolset(Fts5Iter *pIter, Fts5SegIter *pSeg){
         3094  +  pIter->base.iRowid = pSeg->iRowid;
         3095  +  pIter->base.nData = pSeg->nPos;
         3096  +
         3097  +  assert( pIter->pIndex->pConfig->eDetail!=FTS5_DETAIL_NONE );
         3098  +  assert( pIter->pColset==0 || pIter->bFiltered );
         3099  +
         3100  +  if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){
         3101  +    /* All data is stored on the current page. Populate the output 
         3102  +    ** variables to point into the body of the page object. */
         3103  +    pIter->base.pData = &pSeg->pLeaf->p[pSeg->iLeafOffset];
         3104  +  }else{
         3105  +    /* The data is distributed over two or more pages. Copy it into the
         3106  +    ** Fts5Iter.poslist buffer and then set the output pointer to point
         3107  +    ** to this buffer.  */
         3108  +    fts5BufferZero(&pIter->poslist);
         3109  +    fts5SegiterPoslist(pIter->pIndex, pSeg, 0, &pIter->poslist);
         3110  +    pIter->base.pData = pIter->poslist.p;
         3111  +  }
         3112  +}
         3113  +
         3114  +/*
         3115  +** xSetOutputs callback used by detail=col when there is a column filter
         3116  +** and there are 100 or more columns. Also called as a fallback from
         3117  +** fts5IterSetOutputs_Col100 if the column-list spans more than one page.
         3118  +*/
         3119  +static void fts5IterSetOutputs_Col(Fts5Iter *pIter, Fts5SegIter *pSeg){
         3120  +  fts5BufferZero(&pIter->poslist);
         3121  +  fts5SegiterPoslist(pIter->pIndex, pSeg, pIter->pColset, &pIter->poslist);
         3122  +  pIter->base.iRowid = pSeg->iRowid;
         3123  +  pIter->base.pData = pIter->poslist.p;
         3124  +  pIter->base.nData = pIter->poslist.n;
         3125  +}
         3126  +
         3127  +/*
         3128  +** xSetOutputs callback used when: 
         3129  +**
         3130  +**   * detail=col,
         3131  +**   * there is a column filter, and
         3132  +**   * the table contains 100 or fewer columns. 
         3133  +**
         3134  +** The last point is to ensure all column numbers are stored as 
         3135  +** single-byte varints.
         3136  +*/
         3137  +static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){
         3138  +
         3139  +  assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS );
         3140  +  assert( pIter->pColset );
         3141  +
         3142  +  if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf ){
         3143  +    fts5IterSetOutputs_Col(pIter, pSeg);
         3144  +  }else{
         3145  +    u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset];
         3146  +    u8 *pEnd = (u8*)&a[pSeg->nPos]; 
         3147  +    int iPrev = 0;
         3148  +    int *aiCol = pIter->pColset->aiCol;
         3149  +    int *aiColEnd = &aiCol[pIter->pColset->nCol];
         3150  +
         3151  +    u8 *aOut = pIter->poslist.p;
         3152  +    int iPrevOut = 0;
         3153  +
         3154  +    pIter->base.iRowid = pSeg->iRowid;
         3155  +
         3156  +    while( a<pEnd ){
         3157  +      iPrev += (int)a++[0] - 2;
         3158  +      while( *aiCol<iPrev ){
         3159  +        aiCol++;
         3160  +        if( aiCol==aiColEnd ) goto setoutputs_col_out;
         3161  +      }
         3162  +      if( *aiCol==iPrev ){
         3163  +        *aOut++ = (iPrev - iPrevOut) + 2;
         3164  +        iPrevOut = iPrev;
         3165  +      }
         3166  +    }
         3167  +
         3168  +setoutputs_col_out:
         3169  +    pIter->base.pData = pIter->poslist.p;
         3170  +    pIter->base.nData = aOut - pIter->poslist.p;
         3171  +  }
         3172  +}
         3173  +
         3174  +/*
         3175  +** xSetOutputs callback used by detail=full when there is a column filter.
         3176  +*/
         3177  +static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){
         3178  +  Fts5Colset *pColset = pIter->pColset;
         3179  +  pIter->base.iRowid = pSeg->iRowid;
         3180  +
         3181  +  assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_FULL );
         3182  +  assert( pColset );
         3183  +
         3184  +  if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){
         3185  +    /* All data is stored on the current page. Populate the output 
         3186  +    ** variables to point into the body of the page object. */
         3187  +    const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset];
         3188  +    if( pColset->nCol==1 ){
         3189  +      pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]);
         3190  +      pIter->base.pData = a;
         3191  +    }else{
         3192  +      fts5BufferZero(&pIter->poslist);
         3193  +      fts5IndexExtractColset(pColset, a, pSeg->nPos, &pIter->poslist);
         3194  +      pIter->base.pData = pIter->poslist.p;
         3195  +      pIter->base.nData = pIter->poslist.n;
         3196  +    }
         3197  +  }else{
         3198  +    /* The data is distributed over two or more pages. Copy it into the
         3199  +    ** Fts5Iter.poslist buffer and then set the output pointer to point
         3200  +    ** to this buffer.  */
         3201  +    fts5BufferZero(&pIter->poslist);
         3202  +    fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist);
         3203  +    pIter->base.pData = pIter->poslist.p;
         3204  +    pIter->base.nData = pIter->poslist.n;
         3205  +  }
         3206  +}
         3207  +
         3208  +static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){
         3209  +  if( *pRc==SQLITE_OK ){
         3210  +    Fts5Config *pConfig = pIter->pIndex->pConfig;
         3211  +    if( pConfig->eDetail==FTS5_DETAIL_NONE ){
         3212  +      pIter->xSetOutputs = fts5IterSetOutputs_None;
         3213  +    }
         3214  +
         3215  +    else if( pIter->pColset==0 || pIter->bFiltered ){
         3216  +      pIter->xSetOutputs = fts5IterSetOutputs_Nocolset;
         3217  +    }
         3218  +
         3219  +    else if( pConfig->eDetail==FTS5_DETAIL_FULL ){
         3220  +      pIter->xSetOutputs = fts5IterSetOutputs_Full;
         3221  +    }
         3222  +
         3223  +    else{
         3224  +      assert( pConfig->eDetail==FTS5_DETAIL_COLUMNS );
         3225  +      if( pConfig->nCol<=100 ){
         3226  +        pIter->xSetOutputs = fts5IterSetOutputs_Col100;
         3227  +        sqlite3Fts5BufferSize(pRc, &pIter->poslist, pConfig->nCol);
         3228  +      }else{
         3229  +        pIter->xSetOutputs = fts5IterSetOutputs_Col;
         3230  +      }
         3231  +    }
         3232  +  }
         3233  +}
         3234  +
         3235  +
         3236  +/*
         3237  +** Allocate a new Fts5Iter object.
         3238  +**
         3239  +** The new object will be used to iterate through data in structure pStruct.
         3240  +** If iLevel is -ve, then all data in all segments is merged. Or, if iLevel
         3241  +** is zero or greater, data from the first nSegment segments on level iLevel
         3242  +** is merged.
         3243  +**
         3244  +** The iterator initially points to the first term/rowid entry in the 
         3245  +** iterated data.
         3246  +*/
         3247  +static void fts5MultiIterNew(
         3248  +  Fts5Index *p,                   /* FTS5 backend to iterate within */
         3249  +  Fts5Structure *pStruct,         /* Structure of specific index */
         3250  +  int flags,                      /* FTS5INDEX_QUERY_XXX flags */
         3251  +  Fts5Colset *pColset,            /* Colset to filter on (or NULL) */
         3252  +  const u8 *pTerm, int nTerm,     /* Term to seek to (or NULL/0) */
         3253  +  int iLevel,                     /* Level to iterate (-1 for all) */
         3254  +  int nSegment,                   /* Number of segments to merge (iLevel>=0) */
         3255  +  Fts5Iter **ppOut                /* New object */
         3256  +){
         3257  +  int nSeg = 0;                   /* Number of segment-iters in use */
         3258  +  int iIter = 0;                  /* */
         3259  +  int iSeg;                       /* Used to iterate through segments */
         3260  +  Fts5Buffer buf = {0,0,0};       /* Buffer used by fts5SegIterSeekInit() */
         3261  +  Fts5StructureLevel *pLvl;
         3262  +  Fts5Iter *pNew;
         3263  +
         3264  +  assert( (pTerm==0 && nTerm==0) || iLevel<0 );
         3265  +
         3266  +  /* Allocate space for the new multi-seg-iterator. */
         3267  +  if( p->rc==SQLITE_OK ){
         3268  +    if( iLevel<0 ){
         3269  +      assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) );
         3270  +      nSeg = pStruct->nSegment;
         3271  +      nSeg += (p->pHash ? 1 : 0);
         3272  +    }else{
         3273  +      nSeg = MIN(pStruct->aLevel[iLevel].nSeg, nSegment);
         3274  +    }
         3275  +  }
         3276  +  *ppOut = pNew = fts5MultiIterAlloc(p, nSeg);
         3277  +  if( pNew==0 ) return;
         3278  +  pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC));
         3279  +  pNew->bSkipEmpty = (0!=(flags & FTS5INDEX_QUERY_SKIPEMPTY));
         3280  +  pNew->pStruct = pStruct;
         3281  +  pNew->pColset = pColset;
         3282  +  fts5StructureRef(pStruct);
         3283  +  if( (flags & FTS5INDEX_QUERY_NOOUTPUT)==0 ){
         3284  +    fts5IterSetOutputCb(&p->rc, pNew);
         3285  +  }
         3286  +
         3287  +  /* Initialize each of the component segment iterators. */
         3288  +  if( p->rc==SQLITE_OK ){
         3289  +    if( iLevel<0 ){
         3290  +      Fts5StructureLevel *pEnd = &pStruct->aLevel[pStruct->nLevel];
         3291  +      if( p->pHash ){
         3292  +        /* Add a segment iterator for the current contents of the hash table. */
         3293  +        Fts5SegIter *pIter = &pNew->aSeg[iIter++];
         3294  +        fts5SegIterHashInit(p, pTerm, nTerm, flags, pIter);
         3295  +      }
         3296  +      for(pLvl=&pStruct->aLevel[0]; pLvl<pEnd; pLvl++){
         3297  +        for(iSeg=pLvl->nSeg-1; iSeg>=0; iSeg--){
         3298  +          Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg];
         3299  +          Fts5SegIter *pIter = &pNew->aSeg[iIter++];
         3300  +          if( pTerm==0 ){
         3301  +            fts5SegIterInit(p, pSeg, pIter);
         3302  +          }else{
         3303  +            fts5SegIterSeekInit(p, &buf, pTerm, nTerm, flags, pSeg, pIter);
         3304  +          }
         3305  +        }
         3306  +      }
         3307  +    }else{
         3308  +      pLvl = &pStruct->aLevel[iLevel];
         3309  +      for(iSeg=nSeg-1; iSeg>=0; iSeg--){
         3310  +        fts5SegIterInit(p, &pLvl->aSeg[iSeg], &pNew->aSeg[iIter++]);
         3311  +      }
         3312  +    }
         3313  +    assert( iIter==nSeg );
         3314  +  }
         3315  +
         3316  +  /* If the above was successful, each component iterators now points 
         3317  +  ** to the first entry in its segment. In this case initialize the 
         3318  +  ** aFirst[] array. Or, if an error has occurred, free the iterator
         3319  +  ** object and set the output variable to NULL.  */
         3320  +  if( p->rc==SQLITE_OK ){
         3321  +    for(iIter=pNew->nSeg-1; iIter>0; iIter--){
         3322  +      int iEq;
         3323  +      if( (iEq = fts5MultiIterDoCompare(pNew, iIter)) ){
         3324  +        Fts5SegIter *pSeg = &pNew->aSeg[iEq];
         3325  +        if( p->rc==SQLITE_OK ) pSeg->xNext(p, pSeg, 0);
         3326  +        fts5MultiIterAdvanced(p, pNew, iEq, iIter);
         3327  +      }
         3328  +    }
         3329  +    fts5MultiIterSetEof(pNew);
         3330  +    fts5AssertMultiIterSetup(p, pNew);
         3331  +
         3332  +    if( pNew->bSkipEmpty && fts5MultiIterIsEmpty(p, pNew) ){
         3333  +      fts5MultiIterNext(p, pNew, 0, 0);
         3334  +    }else if( pNew->base.bEof==0 ){
         3335  +      Fts5SegIter *pSeg = &pNew->aSeg[pNew->aFirst[1].iFirst];
         3336  +      pNew->xSetOutputs(pNew, pSeg);
         3337  +    }
         3338  +
         3339  +  }else{
         3340  +    fts5MultiIterFree(p, pNew);
         3341  +    *ppOut = 0;
         3342  +  }
         3343  +  fts5BufferFree(&buf);
         3344  +
         3345  +}
         3346  +
         3347  +/*
         3348  +** Create an Fts5Iter that iterates through the doclist provided
         3349  +** as the second argument.
         3350  +*/
         3351  +static void fts5MultiIterNew2(
         3352  +  Fts5Index *p,                   /* FTS5 backend to iterate within */
         3353  +  Fts5Data *pData,                /* Doclist to iterate through */
         3354  +  int bDesc,                      /* True for descending rowid order */
         3355  +  Fts5Iter **ppOut                /* New object */
         3356  +){
         3357  +  Fts5Iter *pNew;
         3358  +  pNew = fts5MultiIterAlloc(p, 2);
         3359  +  if( pNew ){
         3360  +    Fts5SegIter *pIter = &pNew->aSeg[1];
         3361  +
         3362  +    pNew->bFiltered = 1;
         3363  +    pIter->flags = FTS5_SEGITER_ONETERM;
         3364  +    if( pData->szLeaf>0 ){
         3365  +      pIter->pLeaf = pData;
         3366  +      pIter->iLeafOffset = fts5GetVarint(pData->p, (u64*)&pIter->iRowid);
         3367  +      pIter->iEndofDoclist = pData->nn;
         3368  +      pNew->aFirst[1].iFirst = 1;
         3369  +      if( bDesc ){
         3370  +        pNew->bRev = 1;
         3371  +        pIter->flags |= FTS5_SEGITER_REVERSE;
         3372  +        fts5SegIterReverseInitPage(p, pIter);
         3373  +      }else{
         3374  +        fts5SegIterLoadNPos(p, pIter);
         3375  +      }
         3376  +      pData = 0;
         3377  +    }else{
         3378  +      pNew->base.bEof = 1;
         3379  +    }
         3380  +    fts5SegIterSetNext(p, pIter);
         3381  +
         3382  +    *ppOut = pNew;
         3383  +  }
         3384  +
         3385  +  fts5DataRelease(pData);
         3386  +}
         3387  +
         3388  +/*
         3389  +** Return true if the iterator is at EOF or if an error has occurred. 
         3390  +** False otherwise.
         3391  +*/
         3392  +static int fts5MultiIterEof(Fts5Index *p, Fts5Iter *pIter){
         3393  +  assert( p->rc 
         3394  +      || (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->base.bEof 
         3395  +  );
         3396  +  return (p->rc || pIter->base.bEof);
         3397  +}
         3398  +
         3399  +/*
         3400  +** Return the rowid of the entry that the iterator currently points
         3401  +** to. If the iterator points to EOF when this function is called the
         3402  +** results are undefined.
         3403  +*/
         3404  +static i64 fts5MultiIterRowid(Fts5Iter *pIter){
         3405  +  assert( pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf );
         3406  +  return pIter->aSeg[ pIter->aFirst[1].iFirst ].iRowid;
         3407  +}
         3408  +
         3409  +/*
         3410  +** Move the iterator to the next entry at or following iMatch.
         3411  +*/
         3412  +static void fts5MultiIterNextFrom(
         3413  +  Fts5Index *p, 
         3414  +  Fts5Iter *pIter, 
         3415  +  i64 iMatch
         3416  +){
         3417  +  while( 1 ){
         3418  +    i64 iRowid;
         3419  +    fts5MultiIterNext(p, pIter, 1, iMatch);
         3420  +    if( fts5MultiIterEof(p, pIter) ) break;
         3421  +    iRowid = fts5MultiIterRowid(pIter);
         3422  +    if( pIter->bRev==0 && iRowid>=iMatch ) break;
         3423  +    if( pIter->bRev!=0 && iRowid<=iMatch ) break;
         3424  +  }
         3425  +}
         3426  +
         3427  +/*
         3428  +** Return a pointer to a buffer containing the term associated with the 
         3429  +** entry that the iterator currently points to.
         3430  +*/
         3431  +static const u8 *fts5MultiIterTerm(Fts5Iter *pIter, int *pn){
         3432  +  Fts5SegIter *p = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
         3433  +  *pn = p->term.n;
         3434  +  return p->term.p;
         3435  +}
  3068   3436   
  3069   3437   /*
  3070   3438   ** Allocate a new segment-id for the structure pStruct. The new segment
  3071   3439   ** id must be between 1 and 65335 inclusive, and must not be used by 
  3072   3440   ** any currently existing segment. If a free segment id cannot be found,
  3073   3441   ** SQLITE_FULL is returned.
  3074   3442   **
................................................................................
  3681   4049     int nRem = pnRem ? *pnRem : 0;  /* Output leaf pages left to write */
  3682   4050     int nInput;                     /* Number of input segments */
  3683   4051     Fts5SegWriter writer;           /* Writer object */
  3684   4052     Fts5StructureSegment *pSeg;     /* Output segment */
  3685   4053     Fts5Buffer term;
  3686   4054     int bOldest;                    /* True if the output segment is the oldest */
  3687   4055     int eDetail = p->pConfig->eDetail;
         4056  +  const int flags = FTS5INDEX_QUERY_NOOUTPUT;
  3688   4057   
  3689   4058     assert( iLvl<pStruct->nLevel );
  3690   4059     assert( pLvl->nMerge<=pLvl->nSeg );
  3691   4060   
  3692   4061     memset(&writer, 0, sizeof(Fts5SegWriter));
  3693   4062     memset(&term, 0, sizeof(Fts5Buffer));
  3694   4063     if( pLvl->nMerge ){
................................................................................
  3725   4094   
  3726   4095       /* Read input from all segments in the input level */
  3727   4096       nInput = pLvl->nSeg;
  3728   4097     }
  3729   4098     bOldest = (pLvlOut->nSeg==1 && pStruct->nLevel==iLvl+2);
  3730   4099   
  3731   4100     assert( iLvl>=0 );
  3732         -  for(fts5MultiIterNew(p, pStruct, 0, 0, 0, 0, iLvl, nInput, &pIter);
         4101  +  for(fts5MultiIterNew(p, pStruct, flags, 0, 0, 0, iLvl, nInput, &pIter);
  3733   4102         fts5MultiIterEof(p, pIter)==0;
  3734   4103         fts5MultiIterNext(p, pIter, 0, 0)
  3735   4104     ){
  3736   4105       Fts5SegIter *pSegIter = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
  3737   4106       int nPos;                     /* position-list size field value */
  3738   4107       int nTerm;
  3739   4108       const u8 *pTerm;
................................................................................
  4170   4539       fts5StructureWrite(p, pStruct);
  4171   4540     }
  4172   4541     fts5StructureRelease(pStruct);
  4173   4542   
  4174   4543     return fts5IndexReturn(p);
  4175   4544   }
  4176   4545   
  4177         -static void fts5PoslistCallback(
  4178         -  Fts5Index *p, 
  4179         -  void *pContext, 
  4180         -  const u8 *pChunk, int nChunk
  4181         -){
  4182         -  assert_nc( nChunk>=0 );
  4183         -  if( nChunk>0 ){
  4184         -    fts5BufferSafeAppendBlob((Fts5Buffer*)pContext, pChunk, nChunk);
  4185         -  }
  4186         -}
  4187         -
  4188         -typedef struct PoslistCallbackCtx PoslistCallbackCtx;
  4189         -struct PoslistCallbackCtx {
  4190         -  Fts5Buffer *pBuf;               /* Append to this buffer */
  4191         -  Fts5Colset *pColset;            /* Restrict matches to this column */
  4192         -  int eState;                     /* See above */
  4193         -};
  4194         -
  4195         -typedef struct PoslistOffsetsCtx PoslistOffsetsCtx;
  4196         -struct PoslistOffsetsCtx {
  4197         -  Fts5Buffer *pBuf;               /* Append to this buffer */
  4198         -  Fts5Colset *pColset;            /* Restrict matches to this column */
  4199         -  int iRead;
  4200         -  int iWrite;
  4201         -};
  4202         -
  4203         -/*
  4204         -** TODO: Make this more efficient!
  4205         -*/
  4206         -static int fts5IndexColsetTest(Fts5Colset *pColset, int iCol){
  4207         -  int i;
  4208         -  for(i=0; i<pColset->nCol; i++){
  4209         -    if( pColset->aiCol[i]==iCol ) return 1;
  4210         -  }
  4211         -  return 0;
  4212         -}
  4213         -
  4214         -static void fts5PoslistOffsetsCallback(
  4215         -  Fts5Index *p, 
  4216         -  void *pContext, 
  4217         -  const u8 *pChunk, int nChunk
  4218         -){
  4219         -  PoslistOffsetsCtx *pCtx = (PoslistOffsetsCtx*)pContext;
  4220         -  assert_nc( nChunk>=0 );
  4221         -  if( nChunk>0 ){
  4222         -    int i = 0;
  4223         -    while( i<nChunk ){
  4224         -      int iVal;
  4225         -      i += fts5GetVarint32(&pChunk[i], iVal);
  4226         -      iVal += pCtx->iRead - 2;
  4227         -      pCtx->iRead = iVal;
  4228         -      if( fts5IndexColsetTest(pCtx->pColset, iVal) ){
  4229         -        fts5BufferSafeAppendVarint(pCtx->pBuf, iVal + 2 - pCtx->iWrite);
  4230         -        pCtx->iWrite = iVal;
  4231         -      }
  4232         -    }
  4233         -  }
  4234         -}
  4235         -
  4236         -static void fts5PoslistFilterCallback(
  4237         -  Fts5Index *p, 
  4238         -  void *pContext, 
  4239         -  const u8 *pChunk, int nChunk
  4240         -){
  4241         -  PoslistCallbackCtx *pCtx = (PoslistCallbackCtx*)pContext;
  4242         -  assert_nc( nChunk>=0 );
  4243         -  if( nChunk>0 ){
  4244         -    /* Search through to find the first varint with value 1. This is the
  4245         -    ** start of the next columns hits. */
  4246         -    int i = 0;
  4247         -    int iStart = 0;
  4248         -
  4249         -    if( pCtx->eState==2 ){
  4250         -      int iCol;
  4251         -      fts5FastGetVarint32(pChunk, i, iCol);
  4252         -      if( fts5IndexColsetTest(pCtx->pColset, iCol) ){
  4253         -        pCtx->eState = 1;
  4254         -        fts5BufferSafeAppendVarint(pCtx->pBuf, 1);
  4255         -      }else{
  4256         -        pCtx->eState = 0;
  4257         -      }
  4258         -    }
  4259         -
  4260         -    do {
  4261         -      while( i<nChunk && pChunk[i]!=0x01 ){
  4262         -        while( pChunk[i] & 0x80 ) i++;
  4263         -        i++;
  4264         -      }
  4265         -      if( pCtx->eState ){
  4266         -        fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart);
  4267         -      }
  4268         -      if( i<nChunk ){
  4269         -        int iCol;
  4270         -        iStart = i;
  4271         -        i++;
  4272         -        if( i>=nChunk ){
  4273         -          pCtx->eState = 2;
  4274         -        }else{
  4275         -          fts5FastGetVarint32(pChunk, i, iCol);
  4276         -          pCtx->eState = fts5IndexColsetTest(pCtx->pColset, iCol);
  4277         -          if( pCtx->eState ){
  4278         -            fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart);
  4279         -            iStart = i;
  4280         -          }
  4281         -        }
  4282         -      }
  4283         -    }while( i<nChunk );
  4284         -  }
  4285         -}
  4286         -
  4287         -/*
  4288         -** Iterator pIter currently points to a valid entry (not EOF). This
  4289         -** function appends the position list data for the current entry to
  4290         -** buffer pBuf. It does not make a copy of the position-list size
  4291         -** field.
  4292         -*/
  4293         -static void fts5SegiterPoslist(
         4546  +static void fts5AppendRowid(
  4294   4547     Fts5Index *p,
  4295         -  Fts5SegIter *pSeg,
  4296         -  Fts5Colset *pColset,
         4548  +  i64 iDelta,
         4549  +  Fts5Iter *pMulti,
  4297   4550     Fts5Buffer *pBuf
  4298   4551   ){
  4299         -  if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){
  4300         -    if( pColset==0 ){
  4301         -      fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
  4302         -    }else{
  4303         -      if( p->pConfig->eDetail==FTS5_DETAIL_FULL ){
  4304         -        PoslistCallbackCtx sCtx;
  4305         -        sCtx.pBuf = pBuf;
  4306         -        sCtx.pColset = pColset;
  4307         -        sCtx.eState = fts5IndexColsetTest(pColset, 0);
  4308         -        assert( sCtx.eState==0 || sCtx.eState==1 );
  4309         -        fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback);
  4310         -      }else{
  4311         -        PoslistOffsetsCtx sCtx;
  4312         -        memset(&sCtx, 0, sizeof(sCtx));
  4313         -        sCtx.pBuf = pBuf;
  4314         -        sCtx.pColset = pColset;
  4315         -        fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistOffsetsCallback);
  4316         -      }
  4317         -    }
  4318         -  }
         4552  +  fts5BufferAppendVarint(&p->rc, pBuf, iDelta);
  4319   4553   }
  4320   4554   
  4321         -/*
  4322         -** IN/OUT parameter (*pa) points to a position list n bytes in size. If
  4323         -** the position list contains entries for column iCol, then (*pa) is set
  4324         -** to point to the sub-position-list for that column and the number of
  4325         -** bytes in it returned. Or, if the argument position list does not
  4326         -** contain any entries for column iCol, return 0.
  4327         -*/
  4328         -static int fts5IndexExtractCol(
  4329         -  const u8 **pa,                  /* IN/OUT: Pointer to poslist */
  4330         -  int n,                          /* IN: Size of poslist in bytes */
  4331         -  int iCol                        /* Column to extract from poslist */
  4332         -){
  4333         -  int iCurrent = 0;               /* Anything before the first 0x01 is col 0 */
  4334         -  const u8 *p = *pa;
  4335         -  const u8 *pEnd = &p[n];         /* One byte past end of position list */
  4336         -
  4337         -  while( iCol>iCurrent ){
  4338         -    /* Advance pointer p until it points to pEnd or an 0x01 byte that is
  4339         -    ** not part of a varint. Note that it is not possible for a negative
  4340         -    ** or extremely large varint to occur within an uncorrupted position 
  4341         -    ** list. So the last byte of each varint may be assumed to have a clear
  4342         -    ** 0x80 bit.  */
  4343         -    while( *p!=0x01 ){
  4344         -      while( *p++ & 0x80 );
  4345         -      if( p>=pEnd ) return 0;
  4346         -    }
  4347         -    *pa = p++;
  4348         -    iCurrent = *p++;
  4349         -    if( iCurrent & 0x80 ){
  4350         -      p--;
  4351         -      p += fts5GetVarint32(p, iCurrent);
  4352         -    }
  4353         -  }
  4354         -  if( iCol!=iCurrent ) return 0;
  4355         -
  4356         -  /* Advance pointer p until it points to pEnd or an 0x01 byte that is
  4357         -  ** not part of a varint */
  4358         -  while( p<pEnd && *p!=0x01 ){
  4359         -    while( *p++ & 0x80 );
  4360         -  }
  4361         -
  4362         -  return p - (*pa);
  4363         -}
  4364         -
  4365         -static int fts5AppendRowid(
         4555  +static void fts5AppendPoslist(
  4366   4556     Fts5Index *p,
  4367   4557     i64 iDelta,
  4368   4558     Fts5Iter *pMulti,
  4369         -  Fts5Colset *pColset,
  4370   4559     Fts5Buffer *pBuf
  4371   4560   ){
  4372         -  fts5BufferAppendVarint(&p->rc, pBuf, iDelta);
  4373         -  return 0;
  4374         -}
  4375         -
  4376         -/*
  4377         -** Iterator pMulti currently points to a valid entry (not EOF). This
  4378         -** function appends the following to buffer pBuf:
  4379         -**
  4380         -**   * The varint iDelta, and
  4381         -**   * the position list that currently points to, including the size field.
  4382         -**
  4383         -** If argument pColset is NULL, then the position list is filtered according
  4384         -** to pColset before being appended to the buffer. If this means there are
  4385         -** no entries in the position list, nothing is appended to the buffer (not
  4386         -** even iDelta).
  4387         -**
  4388         -** If an error occurs, an error code is left in p->rc. 
  4389         -*/
  4390         -static int fts5AppendPoslist(
  4391         -  Fts5Index *p,
  4392         -  i64 iDelta,
  4393         -  Fts5Iter *pMulti,
  4394         -  Fts5Colset *pColset,
  4395         -  Fts5Buffer *pBuf
  4396         -){
  4397         -  if( p->rc==SQLITE_OK ){
  4398         -    Fts5SegIter *pSeg = &pMulti->aSeg[ pMulti->aFirst[1].iFirst ];
  4399         -    assert( fts5MultiIterEof(p, pMulti)==0 );
  4400         -    assert( pSeg->nPos>0 );
  4401         -    if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+9+9) ){
  4402         -      if( p->pConfig->eDetail==FTS5_DETAIL_FULL
  4403         -       && pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf 
  4404         -       && (pColset==0 || pColset->nCol==1)
  4405         -      ){
  4406         -        const u8 *pPos = &pSeg->pLeaf->p[pSeg->iLeafOffset];
  4407         -        int nPos;
  4408         -        if( pColset ){
  4409         -          nPos = fts5IndexExtractCol(&pPos, pSeg->nPos, pColset->aiCol[0]);
  4410         -          if( nPos==0 ) return 1;
  4411         -        }else{
  4412         -          nPos = pSeg->nPos;
  4413         -        }
  4414         -        assert( nPos>0 );
  4415         -        fts5BufferSafeAppendVarint(pBuf, iDelta);
  4416         -        fts5BufferSafeAppendVarint(pBuf, nPos*2);
  4417         -        fts5BufferSafeAppendBlob(pBuf, pPos, nPos);
  4418         -      }else{
  4419         -        int iSv1;
  4420         -        int iSv2;
  4421         -        int iData;
  4422         -
  4423         -        /* Append iDelta */
  4424         -        iSv1 = pBuf->n;
  4425         -        fts5BufferSafeAppendVarint(pBuf, iDelta);
  4426         -
  4427         -        /* WRITEPOSLISTSIZE */
  4428         -        iSv2 = pBuf->n;
  4429         -        fts5BufferSafeAppendVarint(pBuf, pSeg->nPos*2);
  4430         -        iData = pBuf->n;
  4431         -
  4432         -        fts5SegiterPoslist(p, pSeg, pColset, pBuf);
  4433         -
  4434         -        if( pColset ){
  4435         -          int nActual = pBuf->n - iData;
  4436         -          if( nActual!=pSeg->nPos ){
  4437         -            if( nActual==0 ){
  4438         -              pBuf->n = iSv1;
  4439         -              return 1;
  4440         -            }else{
  4441         -              int nReq = sqlite3Fts5GetVarintLen((u32)(nActual*2));
  4442         -              while( iSv2<(iData-nReq) ){ pBuf->p[iSv2++] = 0x80; }
  4443         -              sqlite3Fts5PutVarint(&pBuf->p[iSv2], nActual*2);
  4444         -            }
  4445         -          }
  4446         -        }
  4447         -      }
  4448         -    }
  4449         -  }
  4450         -
  4451         -  return 0;
         4561  +  int nData = pMulti->base.nData;
         4562  +  assert( nData>0 );
         4563  +  if( p->rc==SQLITE_OK && 0==fts5BufferGrow(&p->rc, pBuf, nData+9+9) ){
         4564  +    fts5BufferSafeAppendVarint(pBuf, iDelta);
         4565  +    fts5BufferSafeAppendVarint(pBuf, nData*2);
         4566  +    fts5BufferSafeAppendBlob(pBuf, pMulti->base.pData, nData);
         4567  +  }
  4452   4568   }
  4453   4569   
  4454   4570   
  4455   4571   static void fts5DoclistIterNext(Fts5DoclistIter *pIter){
  4456   4572     u8 *p = pIter->aPoslist + pIter->nSize + pIter->nPoslist;
  4457   4573   
  4458   4574     assert( pIter->aPoslist );
................................................................................
  4585   4701   */
  4586   4702   static void fts5MergePrefixLists(
  4587   4703     Fts5Index *p,                   /* FTS5 backend object */
  4588   4704     Fts5Buffer *p1,                 /* First list to merge */
  4589   4705     Fts5Buffer *p2                  /* Second list to merge */
  4590   4706   ){
  4591   4707     if( p2->n ){
  4592         -    i64 iLastRowid = 0;
  4593         -    Fts5DoclistIter i1;
  4594         -    Fts5DoclistIter i2;
  4595         -    Fts5Buffer out;
  4596         -    Fts5Buffer tmp;
  4597         -    memset(&out, 0, sizeof(out));
  4598         -    memset(&tmp, 0, sizeof(tmp));
  4599         -
  4600         -    sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n);
  4601         -    fts5DoclistIterInit(p1, &i1);
  4602         -    fts5DoclistIterInit(p2, &i2);
  4603         -    while( p->rc==SQLITE_OK && (i1.aPoslist!=0 || i2.aPoslist!=0) ){
  4604         -      if( i2.aPoslist==0 || (i1.aPoslist && i1.iRowid<i2.iRowid) ){
  4605         -        /* Copy entry from i1 */
  4606         -        fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid);
  4607         -        fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.nPoslist+i1.nSize);
  4608         -        fts5DoclistIterNext(&i1);
  4609         -      }
  4610         -      else if( i1.aPoslist==0 || i2.iRowid!=i1.iRowid ){
  4611         -        /* Copy entry from i2 */
  4612         -        fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
  4613         -        fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.nPoslist+i2.nSize);
  4614         -        fts5DoclistIterNext(&i2);
  4615         -      }
  4616         -      else{
  4617         -        i64 iPos1 = 0;
  4618         -        i64 iPos2 = 0;
  4619         -        int iOff1 = 0;
  4620         -        int iOff2 = 0;
  4621         -        u8 *a1 = &i1.aPoslist[i1.nSize];
  4622         -        u8 *a2 = &i2.aPoslist[i2.nSize];
  4623         -
  4624         -        Fts5PoslistWriter writer;
  4625         -        memset(&writer, 0, sizeof(writer));
  4626         -
  4627         -        /* Merge the two position lists. */ 
  4628         -        fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
  4629         -        fts5BufferZero(&tmp);
  4630         -
  4631         -        sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
  4632         -        sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
  4633         -
  4634         -        while( p->rc==SQLITE_OK && (iPos1>=0 || iPos2>=0) ){
  4635         -          i64 iNew;
  4636         -          if( iPos2<0 || (iPos1>=0 && iPos1<iPos2) ){
  4637         -            iNew = iPos1;
  4638         -            sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
  4639         -          }else{
  4640         -            iNew = iPos2;
  4641         -            sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
  4642         -            if( iPos1==iPos2 ){
  4643         -              sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1,&iPos1);
         4708  +    if( p1->n==0 ){
         4709  +      fts5BufferSwap(p1, p2);
         4710  +    }else{
         4711  +      i64 iLastRowid = 0;
         4712  +      Fts5DoclistIter i1;
         4713  +      Fts5DoclistIter i2;
         4714  +      Fts5Buffer out = {0, 0, 0};
         4715  +      Fts5Buffer tmp = {0, 0, 0};
         4716  +
         4717  +      if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n) ) return;
         4718  +      fts5DoclistIterInit(p1, &i1);
         4719  +      fts5DoclistIterInit(p2, &i2);
         4720  +
         4721  +      while( 1 ){
         4722  +
         4723  +        if( i1.iRowid<i2.iRowid ){
         4724  +          /* Copy entry from i1 */
         4725  +          fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid);
         4726  +          fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.nPoslist+i1.nSize);
         4727  +          fts5DoclistIterNext(&i1);
         4728  +          if( i1.aPoslist==0 ) break;
         4729  +        }
         4730  +        else if( i2.iRowid!=i1.iRowid ){
         4731  +          /* Copy entry from i2 */
         4732  +          fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
         4733  +          fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.nPoslist+i2.nSize);
         4734  +          fts5DoclistIterNext(&i2);
         4735  +          if( i2.aPoslist==0 ) break;
         4736  +        }
         4737  +        else{
         4738  +          i64 iPos1 = 0;
         4739  +          i64 iPos2 = 0;
         4740  +          int iOff1 = 0;
         4741  +          int iOff2 = 0;
         4742  +          u8 *a1 = &i1.aPoslist[i1.nSize];
         4743  +          u8 *a2 = &i2.aPoslist[i2.nSize];
         4744  +
         4745  +          Fts5PoslistWriter writer;
         4746  +          memset(&writer, 0, sizeof(writer));
         4747  +
         4748  +          /* Merge the two position lists. */ 
         4749  +          fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
         4750  +          fts5BufferZero(&tmp);
         4751  +
         4752  +          sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
         4753  +          sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
         4754  +
         4755  +          while( iPos1>=0 || iPos2>=0 ){
         4756  +            i64 iNew;
         4757  +            if( iPos2<0 || (iPos1>=0 && iPos1<iPos2) ){
         4758  +              iNew = iPos1;
         4759  +              sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
         4760  +            }else{
         4761  +              iNew = iPos2;
         4762  +              sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
         4763  +              if( iPos1==iPos2 ){
         4764  +                sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1,&iPos1);
         4765  +              }
         4766  +            }
         4767  +            if( iNew!=writer.iPrev || tmp.n==0 ){
         4768  +              p->rc = sqlite3Fts5PoslistWriterAppend(&tmp, &writer, iNew);
         4769  +              if( p->rc ) goto error_out;
  4644   4770               }
  4645   4771             }
  4646         -          if( iNew!=writer.iPrev || tmp.n==0 ){
  4647         -            p->rc = sqlite3Fts5PoslistWriterAppend(&tmp, &writer, iNew);
  4648         -          }
         4772  +
         4773  +          /* WRITEPOSLISTSIZE */
         4774  +          fts5BufferSafeAppendVarint(&out, tmp.n * 2);
         4775  +          fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
         4776  +          fts5DoclistIterNext(&i1);
         4777  +          fts5DoclistIterNext(&i2);
         4778  +          if( i1.aPoslist==0 || i2.aPoslist==0 ) break;
  4649   4779           }
         4780  +      }
  4650   4781   
  4651         -        /* WRITEPOSLISTSIZE */
  4652         -        fts5BufferSafeAppendVarint(&out, tmp.n * 2);
  4653         -        fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
  4654         -        fts5DoclistIterNext(&i1);
  4655         -        fts5DoclistIterNext(&i2);
         4782  +      if( i1.aPoslist ){
         4783  +        fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid);
         4784  +        fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.aEof - i1.aPoslist);
  4656   4785         }
         4786  +      else if( i2.aPoslist ){
         4787  +        fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
         4788  +        fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist);
         4789  +      }
         4790  +
         4791  +     error_out:
         4792  +      fts5BufferSet(&p->rc, p1, out.n, out.p);
         4793  +      fts5BufferFree(&tmp);
         4794  +      fts5BufferFree(&out);
  4657   4795       }
  4658         -
  4659         -    fts5BufferSet(&p->rc, p1, out.n, out.p);
  4660         -    fts5BufferFree(&tmp);
  4661         -    fts5BufferFree(&out);
  4662   4796     }
  4663   4797   }
  4664   4798   
  4665   4799   static void fts5SetupPrefixIter(
  4666   4800     Fts5Index *p,                   /* Index to read from */
  4667   4801     int bDesc,                      /* True for "ORDER BY rowid DESC" */
  4668   4802     const u8 *pToken,               /* Buffer containing prefix to match */
................................................................................
  4671   4805     Fts5Iter **ppIter          /* OUT: New iterator */
  4672   4806   ){
  4673   4807     Fts5Structure *pStruct;
  4674   4808     Fts5Buffer *aBuf;
  4675   4809     const int nBuf = 32;
  4676   4810   
  4677   4811     void (*xMerge)(Fts5Index*, Fts5Buffer*, Fts5Buffer*);
  4678         -  int (*xAppend)(Fts5Index*, i64, Fts5Iter*, Fts5Colset*, Fts5Buffer*);
         4812  +  void (*xAppend)(Fts5Index*, i64, Fts5Iter*, Fts5Buffer*);
  4679   4813     if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
  4680   4814       xMerge = fts5MergeRowidLists;
  4681   4815       xAppend = fts5AppendRowid;
  4682   4816     }else{
  4683   4817       xMerge = fts5MergePrefixLists;
  4684   4818       xAppend = fts5AppendPoslist;
  4685   4819     }
  4686   4820   
  4687   4821     aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*nBuf);
  4688   4822     pStruct = fts5StructureRead(p);
  4689   4823   
  4690   4824     if( aBuf && pStruct ){
  4691         -    const int flags = FTS5INDEX_QUERY_SCAN;
         4825  +    const int flags = FTS5INDEX_QUERY_SCAN 
         4826  +                    | FTS5INDEX_QUERY_SKIPEMPTY 
         4827  +                    | FTS5INDEX_QUERY_NOOUTPUT;
  4692   4828       int i;
  4693   4829       i64 iLastRowid = 0;
  4694   4830       Fts5Iter *p1 = 0;     /* Iterator used to gather data from index */
  4695   4831       Fts5Data *pData;
  4696   4832       Fts5Buffer doclist;
  4697   4833       int bNewTerm = 1;
  4698   4834   
  4699   4835       memset(&doclist, 0, sizeof(doclist));
  4700         -    for(fts5MultiIterNew(p, pStruct, 1, flags, pToken, nToken, -1, 0, &p1);
         4836  +    fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1);
         4837  +    fts5IterSetOutputCb(&p->rc, p1);
         4838  +    for( /* no-op */ ;
  4701   4839           fts5MultiIterEof(p, p1)==0;
  4702   4840           fts5MultiIterNext2(p, p1, &bNewTerm)
  4703   4841       ){
  4704         -      i64 iRowid = fts5MultiIterRowid(p1);
  4705         -      int nTerm;
  4706         -      const u8 *pTerm = fts5MultiIterTerm(p1, &nTerm);
         4842  +      Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
         4843  +      int nTerm = pSeg->term.n;
         4844  +      const u8 *pTerm = pSeg->term.p;
         4845  +      p1->xSetOutputs(p1, pSeg);
         4846  +
  4707   4847         assert_nc( memcmp(pToken, pTerm, MIN(nToken, nTerm))<=0 );
  4708   4848         if( bNewTerm ){
  4709   4849           if( nTerm<nToken || memcmp(pToken, pTerm, nToken) ) break;
  4710   4850         }
  4711   4851   
  4712         -      if( doclist.n>0 && iRowid<=iLastRowid ){
         4852  +      if( p1->base.nData==0 ) continue;
         4853  +
         4854  +      if( p1->base.iRowid<=iLastRowid && doclist.n>0 ){
  4713   4855           for(i=0; p->rc==SQLITE_OK && doclist.n; i++){
  4714   4856             assert( i<nBuf );
  4715   4857             if( aBuf[i].n==0 ){
  4716   4858               fts5BufferSwap(&doclist, &aBuf[i]);
  4717   4859               fts5BufferZero(&doclist);
  4718   4860             }else{
  4719   4861               xMerge(p, &doclist, &aBuf[i]);
  4720   4862               fts5BufferZero(&aBuf[i]);
  4721   4863             }
  4722   4864           }
  4723   4865           iLastRowid = 0;
  4724   4866         }
  4725   4867   
  4726         -      if( !xAppend(p, iRowid-iLastRowid, p1, pColset, &doclist) ){
  4727         -        iLastRowid = iRowid;
  4728         -      }
         4868  +      xAppend(p, p1->base.iRowid-iLastRowid, p1, &doclist);
         4869  +      iLastRowid = p1->base.iRowid;
  4729   4870       }
  4730   4871   
  4731   4872       for(i=0; i<nBuf; i++){
  4732   4873         if( p->rc==SQLITE_OK ){
  4733   4874           xMerge(p, &doclist, &aBuf[i]);
  4734   4875         }
  4735   4876         fts5BufferFree(&aBuf[i]);
................................................................................
  4951   5092         );
  4952   5093       }
  4953   5094     }
  4954   5095   
  4955   5096     return rc;
  4956   5097   }
  4957   5098   
  4958         -
  4959         -static int fts5IndexExtractColset (
  4960         -  Fts5Colset *pColset,            /* Colset to filter on */
  4961         -  const u8 *pPos, int nPos,       /* Position list */
  4962         -  Fts5Buffer *pBuf                /* Output buffer */
  4963         -){
  4964         -  int rc = SQLITE_OK;
  4965         -  int i;
  4966         -
  4967         -  fts5BufferZero(pBuf);
  4968         -  for(i=0; i<pColset->nCol; i++){
  4969         -    const u8 *pSub = pPos;
  4970         -    int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]);
  4971         -    if( nSub ){
  4972         -      fts5BufferAppendBlob(&rc, pBuf, nSub, pSub);
  4973         -    }
  4974         -  }
  4975         -  return rc;
  4976         -}
  4977         -
  4978         -/*
  4979         -** xSetOutputs callback used by detail=none tables.
  4980         -*/
  4981         -static void fts5IterSetOutputs_None(Fts5Iter *pIter, Fts5SegIter *pSeg){
  4982         -  assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_NONE );
  4983         -  pIter->base.iRowid = pSeg->iRowid;
  4984         -  pIter->base.nData = pSeg->nPos;
  4985         -}
  4986         -
  4987         -/*
  4988         -** xSetOutputs callback used by detail=full and detail=col tables when no
  4989         -** column filters are specified.
  4990         -*/
  4991         -static void fts5IterSetOutputs_Nocolset(Fts5Iter *pIter, Fts5SegIter *pSeg){
  4992         -  pIter->base.iRowid = pSeg->iRowid;
  4993         -  pIter->base.nData = pSeg->nPos;
  4994         -
  4995         -  assert( pIter->pIndex->pConfig->eDetail!=FTS5_DETAIL_NONE );
  4996         -  assert( pIter->pColset==0 || pIter->bFiltered );
  4997         -
  4998         -  if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){
  4999         -    /* All data is stored on the current page. Populate the output 
  5000         -    ** variables to point into the body of the page object. */
  5001         -    pIter->base.pData = &pSeg->pLeaf->p[pSeg->iLeafOffset];
  5002         -  }else{
  5003         -    /* The data is distributed over two or more pages. Copy it into the
  5004         -    ** Fts5Iter.poslist buffer and then set the output pointer to point
  5005         -    ** to this buffer.  */
  5006         -    fts5BufferZero(&pIter->poslist);
  5007         -    fts5SegiterPoslist(pIter->pIndex, pSeg, 0, &pIter->poslist);
  5008         -    pIter->base.pData = pIter->poslist.p;
  5009         -  }
  5010         -}
  5011         -
  5012         -/*
  5013         -** xSetOutputs callback used by detail=col when there is a column filter
  5014         -** and there are 100 or more columns. Also called as a fallback from
  5015         -** fts5IterSetOutputs_Col100 if the column-list spans more than one page.
  5016         -*/
  5017         -static void fts5IterSetOutputs_Col(Fts5Iter *pIter, Fts5SegIter *pSeg){
  5018         -  fts5BufferZero(&pIter->poslist);
  5019         -  fts5SegiterPoslist(pIter->pIndex, pSeg, pIter->pColset, &pIter->poslist);
  5020         -  pIter->base.iRowid = pSeg->iRowid;
  5021         -  pIter->base.pData = pIter->poslist.p;
  5022         -  pIter->base.nData = pIter->poslist.n;
  5023         -}
  5024         -
  5025         -/*
  5026         -** xSetOutputs callback used when: 
  5027         -**
  5028         -**   * detail=col,
  5029         -**   * there is a column filter, and
  5030         -**   * the table contains 100 or fewer columns. 
  5031         -**
  5032         -** The last point is to ensure all column numbers are stored as 
  5033         -** single-byte varints.
  5034         -*/
  5035         -static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){
  5036         -
  5037         -  assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS );
  5038         -  assert( pIter->pColset );
  5039         -
  5040         -  if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf ){
  5041         -    fts5IterSetOutputs_Col(pIter, pSeg);
  5042         -  }else{
  5043         -    u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset];
  5044         -    u8 *pEnd = (u8*)&a[pSeg->nPos]; 
  5045         -    int iPrev = 0;
  5046         -    int *aiCol = pIter->pColset->aiCol;
  5047         -    int *aiColEnd = &aiCol[pIter->pColset->nCol];
  5048         -
  5049         -    u8 *aOut = pIter->poslist.p;
  5050         -    int iPrevOut = 0;
  5051         -
  5052         -    pIter->base.iRowid = pSeg->iRowid;
  5053         -
  5054         -    while( a<pEnd ){
  5055         -      iPrev += (int)a++[0] - 2;
  5056         -      while( *aiCol<iPrev ){
  5057         -        aiCol++;
  5058         -        if( aiCol==aiColEnd ) goto setoutputs_col_out;
  5059         -      }
  5060         -      if( *aiCol==iPrev ){
  5061         -        *aOut++ = (iPrev - iPrevOut) + 2;
  5062         -        iPrevOut = iPrev;
  5063         -      }
  5064         -    }
  5065         -
  5066         -setoutputs_col_out:
  5067         -    pIter->base.pData = pIter->poslist.p;
  5068         -    pIter->base.nData = aOut - pIter->poslist.p;
  5069         -  }
  5070         -}
  5071         -
  5072         -/*
  5073         -** xSetOutputs callback used by detail=full when there is a column filter.
  5074         -*/
  5075         -static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){
  5076         -  Fts5Colset *pColset = pIter->pColset;
  5077         -  pIter->base.iRowid = pSeg->iRowid;
  5078         -
  5079         -  assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_FULL );
  5080         -  assert( pColset );
  5081         -
  5082         -  if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){
  5083         -    /* All data is stored on the current page. Populate the output 
  5084         -    ** variables to point into the body of the page object. */
  5085         -    const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset];
  5086         -    if( pColset->nCol==1 ){
  5087         -      pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]);
  5088         -      pIter->base.pData = a;
  5089         -    }else{
  5090         -      fts5BufferZero(&pIter->poslist);
  5091         -      fts5IndexExtractColset(pColset, a, pSeg->nPos, &pIter->poslist);
  5092         -      pIter->base.pData = pIter->poslist.p;
  5093         -      pIter->base.nData = pIter->poslist.n;
  5094         -    }
  5095         -  }else{
  5096         -    /* The data is distributed over two or more pages. Copy it into the
  5097         -    ** Fts5Iter.poslist buffer and then set the output pointer to point
  5098         -    ** to this buffer.  */
  5099         -    fts5BufferZero(&pIter->poslist);
  5100         -    fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist);
  5101         -    pIter->base.pData = pIter->poslist.p;
  5102         -    pIter->base.nData = pIter->poslist.n;
  5103         -  }
  5104         -}
  5105         -
  5106         -static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){
  5107         -  Fts5Config *pConfig = pIter->pIndex->pConfig;
  5108         -  if( pConfig->eDetail==FTS5_DETAIL_NONE ){
  5109         -    pIter->xSetOutputs = fts5IterSetOutputs_None;
  5110         -  }
  5111         -
  5112         -  else if( pIter->pColset==0 || pIter->bFiltered ){
  5113         -    pIter->xSetOutputs = fts5IterSetOutputs_Nocolset;
  5114         -  }
  5115         -
  5116         -  else if( pConfig->eDetail==FTS5_DETAIL_FULL ){
  5117         -    pIter->xSetOutputs = fts5IterSetOutputs_Full;
  5118         -  }
  5119         -
  5120         -  else{
  5121         -    assert( pConfig->eDetail==FTS5_DETAIL_COLUMNS );
  5122         -    if( pConfig->nCol<=100 ){
  5123         -      pIter->xSetOutputs = fts5IterSetOutputs_Col100;
  5124         -      sqlite3Fts5BufferSize(pRc, &pIter->poslist, pConfig->nCol);
  5125         -    }else{
  5126         -      pIter->xSetOutputs = fts5IterSetOutputs_Col;
  5127         -    }
  5128         -  }
  5129         -}
  5130         -
  5131   5099   /*
  5132   5100   ** Open a new iterator to iterate though all rowid that match the 
  5133   5101   ** specified token or token prefix.
  5134   5102   */
  5135   5103   int sqlite3Fts5IndexQuery(
  5136   5104     Fts5Index *p,                   /* FTS index to query */
  5137   5105     const char *pToken, int nToken, /* Token (or prefix) to query for */
................................................................................
  5174   5142       }
  5175   5143   
  5176   5144       if( iIdx<=pConfig->nPrefix ){
  5177   5145         /* Straight index lookup */
  5178   5146         Fts5Structure *pStruct = fts5StructureRead(p);
  5179   5147         buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx);
  5180   5148         if( pStruct ){
  5181         -        fts5MultiIterNew(p, pStruct, 1, flags, buf.p, nToken+1, -1, 0, &pRet);
         5149  +        fts5MultiIterNew(p, pStruct, flags | FTS5INDEX_QUERY_SKIPEMPTY, 
         5150  +            pColset, buf.p, nToken+1, -1, 0, &pRet
         5151  +        );
  5182   5152           fts5StructureRelease(pStruct);
  5183   5153         }
  5184   5154       }else{
  5185   5155         /* Scan multiple terms in the main index */
  5186   5156         int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0;
  5187   5157         buf.p[0] = FTS5_MAIN_PREFIX;
  5188   5158         fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet);
  5189         -    }
  5190         -
  5191         -    if( p->rc==SQLITE_OK ){
  5192         -      Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst];
  5193         -      pRet->pColset = pColset;
  5194   5159         fts5IterSetOutputCb(&p->rc, pRet);
  5195         -      if( p->rc==SQLITE_OK && pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg);
         5160  +      if( p->rc==SQLITE_OK ){
         5161  +        Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst];
         5162  +        if( p->rc==SQLITE_OK && pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg);
         5163  +      }
  5196   5164       }
         5165  +
  5197   5166       if( p->rc ){
  5198   5167         sqlite3Fts5IterClose(&pRet->base);
  5199   5168         pRet = 0;
  5200   5169         fts5CloseReader(p);
  5201   5170       }
  5202   5171   
  5203   5172       *ppIter = &pRet->base;
................................................................................
  5205   5174     }
  5206   5175     return fts5IndexReturn(p);
  5207   5176   }
  5208   5177   
  5209   5178   /*
  5210   5179   ** Return true if the iterator passed as the only argument is at EOF.
  5211   5180   */
  5212         -int sqlite3Fts5IterEof(Fts5IndexIter *pIter){
  5213         -  assert( ((Fts5Iter*)pIter)->pIndex->rc==SQLITE_OK );
  5214         -  return ((Fts5Iter*)pIter)->bEof;
  5215         -}
  5216         -
  5217   5181   /*
  5218   5182   ** Move to the next matching rowid. 
  5219   5183   */
  5220   5184   int sqlite3Fts5IterNext(Fts5IndexIter *pIndexIter){
  5221   5185     Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
  5222   5186     assert( pIter->pIndex->rc==SQLITE_OK );
  5223   5187     fts5MultiIterNext(pIter->pIndex, pIter, 0, 0);
................................................................................
  5235   5199   
  5236   5200     fts5MultiIterNext(p, pIter, 0, 0);
  5237   5201     if( p->rc==SQLITE_OK ){
  5238   5202       Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
  5239   5203       if( pSeg->pLeaf && pSeg->term.p[0]!=FTS5_MAIN_PREFIX ){
  5240   5204         fts5DataRelease(pSeg->pLeaf);
  5241   5205         pSeg->pLeaf = 0;
  5242         -      pIter->bEof = 1;
         5206  +      pIter->base.bEof = 1;
  5243   5207       }
  5244   5208     }
  5245   5209   
  5246   5210     return fts5IndexReturn(pIter->pIndex);
  5247   5211   }
  5248   5212   
  5249   5213   /*
................................................................................
  5253   5217   */
  5254   5218   int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){
  5255   5219     Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
  5256   5220     fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch);
  5257   5221     return fts5IndexReturn(pIter->pIndex);
  5258   5222   }
  5259   5223   
  5260         -/*
  5261         -** Return the current rowid.
  5262         -*/
  5263         -i64 sqlite3Fts5IterRowid(Fts5IndexIter *pIndexIter){
  5264         -  return fts5MultiIterRowid((Fts5Iter*)pIndexIter);
  5265         -}
  5266         -
  5267   5224   /*
  5268   5225   ** Return the current term.
  5269   5226   */
  5270   5227   const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIndexIter, int *pn){
  5271   5228     int n;
  5272   5229     const char *z = (const char*)fts5MultiIterTerm((Fts5Iter*)pIndexIter, &n);
  5273   5230     *pn = n-1;
................................................................................
  5446   5403   ){
  5447   5404     int eDetail = p->pConfig->eDetail;
  5448   5405     u64 cksum = *pCksum;
  5449   5406     Fts5IndexIter *pIter = 0;
  5450   5407     int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIter);
  5451   5408   
  5452   5409     while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIter) ){
  5453         -    i64 rowid = sqlite3Fts5IterRowid(pIter);
         5410  +    i64 rowid = pIter->iRowid;
  5454   5411   
  5455   5412       if( eDetail==FTS5_DETAIL_NONE ){
  5456   5413         cksum ^= sqlite3Fts5IndexEntryCksum(rowid, 0, 0, iIdx, z, n);
  5457   5414       }else{
  5458   5415         Fts5PoslistReader sReader;
  5459   5416         for(sqlite3Fts5PoslistReaderInit(pIter->pData, pIter->nData, &sReader);
  5460   5417             sReader.bEof==0;
................................................................................
  5778   5735     Fts5Structure *pStruct;         /* Index structure */
  5779   5736   
  5780   5737   #ifdef SQLITE_DEBUG
  5781   5738     /* Used by extra internal tests only run if NDEBUG is not defined */
  5782   5739     u64 cksum3 = 0;                 /* Checksum based on contents of indexes */
  5783   5740     Fts5Buffer term = {0,0,0};      /* Buffer used to hold most recent term */
  5784   5741   #endif
         5742  +  const int flags = FTS5INDEX_QUERY_NOOUTPUT;
  5785   5743     
  5786   5744     /* Load the FTS index structure */
  5787   5745     pStruct = fts5StructureRead(p);
  5788   5746   
  5789   5747     /* Check that the internal nodes of each segment match the leaves */
  5790   5748     if( pStruct ){
  5791   5749       int iLvl, iSeg;
................................................................................
  5806   5764     ** variable cksum2) based on entries extracted from the full-text index
  5807   5765     ** while doing a linear scan of each individual index in turn. 
  5808   5766     **
  5809   5767     ** As each term visited by the linear scans, a separate query for the
  5810   5768     ** same term is performed. cksum3 is calculated based on the entries
  5811   5769     ** extracted by these queries.
  5812   5770     */
  5813         -  for(fts5MultiIterNew(p, pStruct, 0, 0, 0, 0, -1, 0, &pIter);
         5771  +  for(fts5MultiIterNew(p, pStruct, flags, 0, 0, 0, -1, 0, &pIter);
  5814   5772         fts5MultiIterEof(p, pIter)==0;
  5815   5773         fts5MultiIterNext(p, pIter, 0, 0)
  5816   5774     ){
  5817   5775       int n;                      /* Size of term in bytes */
  5818   5776       i64 iPos = 0;               /* Position read from poslist */
  5819   5777       int iOff = 0;               /* Offset within poslist */
  5820   5778       i64 iRowid = fts5MultiIterRowid(pIter);

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

    68     68   } -test {
    69     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         -  INSERT INTO t2 VALUES('m f a jj th q jr ar',   'hj n h h sg j i m');
           75  +  INSERT INTO t2 VALUES('m f a jj th q gi 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');
    77     77     INSERT INTO t2 VALUES('do h h pb p p q fr',    'c rj qs or cr a l i');
    78     78     INSERT INTO t2 VALUES('lk gp t i lq mq qm p',  'h mr g f op ld aj h');
    79     79     INSERT INTO t2 VALUES('ct d sq kc qi k f j',   'sn gh c of g s qt q');
    80     80     INSERT INTO t2 VALUES('d ea d d om mp s ab',   'dm hg l df cm ft pa c');
    81     81     INSERT INTO t2 VALUES('tc dk c jn n t sr ge',  'a a kn bc n i af h');
    82     82     INSERT INTO t2 VALUES('ie ii d i b sa qo rf',  'a h m aq i b m fn');
................................................................................
    91     91     3 { f*  }           {1 3 4 5 6 8 9 10}
    92     92     4 { m OR f }        {1 4 5 8 9 10}
    93     93     5 { sn + gh }       {5}
    94     94     6 { "sn gh" }       {5}
    95     95     7 { NEAR(r a, 5) }  {9}
    96     96     8 { m* f* }         {1 4 6 8 9 10}
    97     97     9 { m* + f* }       {1 8}
           98  +  10 { c NOT p }       {5 6 7 10}
    98     99   } {
    99    100     do_faultsim_test 4.$tn -prep {
   100    101       faultsim_restore_and_reopen
   101    102     } -body "
   102    103       execsql { SELECT rowid FROM t2 WHERE t2 MATCH '$expr' }
   103    104     " -test "
   104    105       faultsim_test_result {[list 0 $res]} {1 {vtable constructor failed: t2}}

Changes to ext/fts5/test/fts5fault2.test.

    12     12   # This file is focused on OOM errors.
    13     13   #
    14     14   
    15     15   source [file join [file dirname [info script]] fts5_common.tcl]
    16     16   source $testdir/malloc_common.tcl
    17     17   set testprefix fts5fault2
    18     18   
    19         -# If SQLITE_ENABLE_FTS3 is defined, omit this file.
           19  +# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
    20     20   ifcapable !fts5 {
    21     21     finish_test
    22     22     return
    23     23   }
    24     24   
    25     25   set doc [string trim [string repeat "x y z " 200]]
    26     26   do_execsql_test 1.0 {

Changes to ext/fts5/test/fts5fault7.test.

    95     95     CREATE VIRTUAL TABLE xy USING fts5(x);
    96     96     INSERT INTO xy(rowid, x) VALUES(1, '1 2 3');
    97     97     INSERT INTO xy(rowid, x) VALUES(2, '2 3 4');
    98     98     INSERT INTO xy(rowid, x) VALUES(3, '3 4 5');
    99     99   }
   100    100   faultsim_save_and_close
   101    101   
   102         -do_faultsim_test 2 -faults oom-* -prep {
          102  +do_faultsim_test 2.1 -faults oom-* -prep {
   103    103     faultsim_restore_and_reopen
   104    104   } -body {
   105    105     db eval { UPDATE OR REPLACE xy SET rowid=3 WHERE rowid = 2 }
   106    106   } -test {
   107    107     faultsim_test_result {0 {}}
   108    108   }
   109    109   
          110  +# Test fault-injection when an empty expression is parsed.
          111  +#
          112  +do_faultsim_test 2.2 -faults oom-* -body {
          113  +  db eval { SELECT * FROM xy('""') }
          114  +} -test {
          115  +  faultsim_test_result {0 {}}
          116  +}
   110    117   
   111    118   finish_test
   112    119   

Changes to ext/fts5/test/fts5fault8.test.

    20     20   ifcapable !fts5 {
    21     21     finish_test
    22     22     return
    23     23   }
    24     24   
    25     25   foreach_detail_mode $testprefix {
    26     26   
    27         -fts5_aux_test_functions db
    28         -do_execsql_test 1.0 {
    29         -  CREATE VIRTUAL TABLE t1 USING fts5(a, b, detail=%DETAIL%);
    30         -  INSERT INTO t1 VALUES('a b c d', '1 2 3 4');
    31         -  INSERT INTO t1 VALUES('a b a b', NULL);
    32         -  INSERT INTO t1 VALUES(NULL, '1 2 1 2');
    33         -}
    34         -
    35         -do_faultsim_test 1 -faults oom-* -body {
    36         -  execsql { 
    37         -    SELECT rowid, fts5_test_poslist(t1) FROM t1 WHERE t1 MATCH 'b OR 2' 
           27  +  fts5_aux_test_functions db
           28  +  do_execsql_test 1.0 {
           29  +    CREATE VIRTUAL TABLE t1 USING fts5(a, b, detail=%DETAIL%);
           30  +    INSERT INTO t1 VALUES('a b c d', '1 2 3 4');
           31  +    INSERT INTO t1 VALUES('a b a b', NULL);
           32  +    INSERT INTO t1 VALUES(NULL, '1 2 1 2');
           33  +  }
           34  +  
           35  +  do_faultsim_test 1 -faults oom-* -body {
           36  +    execsql { 
           37  +      SELECT rowid, fts5_test_poslist(t1) FROM t1 WHERE t1 MATCH 'b OR 2' 
           38  +    }
           39  +  } -test {
           40  +    faultsim_test_result {0 {1 {0.0.1 1.1.1} 2 {0.0.1 0.0.3} 3 {1.1.1 1.1.3}}} \
           41  +                         {1 SQLITE_NOMEM}
    38     42     }
    39         -} -test {
    40         -  faultsim_test_result {0 {1 {0.0.1 1.1.1} 2 {0.0.1 0.0.3} 3 {1.1.1 1.1.3}}} \
    41         -                       {1 SQLITE_NOMEM}
    42         -}
           43  +  
           44  +  do_faultsim_test 2 -faults oom-* -body {
           45  +    execsql { INSERT INTO t1(t1) VALUES('integrity-check') }
           46  +  } -test {
           47  +    faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
           48  +  }
    43     49   
    44         -do_faultsim_test 2 -faults oom-* -body {
    45         -  execsql { 
    46         -    INSERT INTO t1(t1) VALUES('integrity-check');
           50  +  if {[detail_is_none]==0} {
           51  +    do_faultsim_test 3 -faults oom-* -body {
           52  +      execsql { SELECT rowid FROM t1('b:2') }
           53  +    } -test {
           54  +      faultsim_test_result {0 {1 3}} {1 SQLITE_NOMEM}
           55  +    }
    47     56     }
    48         -} -test {
    49         -  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
    50         -}
    51         -
    52         -}
           57  +} ;# foreach_detail_mode...
    53     58   
    54     59   finish_test
    55     60   

Added ext/fts5/test/fts5faultA.test.

            1  +# 2016 February 2
            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  +# This file is focused on OOM errors.
           13  +#
           14  +
           15  +source [file join [file dirname [info script]] fts5_common.tcl]
           16  +source $testdir/malloc_common.tcl
           17  +set testprefix fts5faultA
           18  +
           19  +# If SQLITE_ENABLE_FTS3 is defined, omit this file.
           20  +ifcapable !fts5 {
           21  +  finish_test
           22  +  return
           23  +}
           24  +
           25  +foreach_detail_mode $testprefix {
           26  +  do_execsql_test 1.0 {
           27  +    CREATE VIRTUAL TABLE o1 USING fts5(a, detail=%DETAIL%);
           28  +    INSERT INTO o1(o1, rank) VALUES('pgsz', 32);
           29  +  
           30  +    WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<300 )
           31  +    INSERT INTO o1 SELECT 'A B C' FROM s;
           32  +  
           33  +    INSERT INTO o1 VALUES('A X C');
           34  +  
           35  +    WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<300 )
           36  +    INSERT INTO o1 SELECT 'A B C' FROM s;
           37  +  }
           38  +  
           39  +  do_faultsim_test 1 -faults oom* -prep {
           40  +    sqlite3 db test.db
           41  +  } -body {
           42  +    execsql { SELECT rowid FROM o1('a NOT b') }
           43  +  } -test {
           44  +    faultsim_test_result {0 301}
           45  +  }
           46  +}
           47  +
           48  +do_execsql_test 2.0 {
           49  +  CREATE VIRTUAL TABLE o2 USING fts5(a);
           50  +  
           51  +  INSERT INTO o2 VALUES('A B C');
           52  +  WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<300 )
           53  +  INSERT INTO o2 SELECT group_concat('A B C ') FROM s;
           54  +}
           55  +
           56  +do_faultsim_test 2 -faults oom* -prep {
           57  +  sqlite3 db test.db
           58  +} -body {
           59  +  execsql { SELECT rowid FROM o2('a+b+c NOT xyz') }
           60  +} -test {
           61  +  faultsim_test_result {0 {1 2}}
           62  +}
           63  +finish_test
           64  +

Changes to ext/fts5/test/fts5simple3.test.

    34     34   do_execsql_test 1.2 {
    35     35     SELECT rowid, fts5_test_collist(t1) FROM t1('b:x');
    36     36   } {2 0.1}
    37     37   
    38     38   do_execsql_test 1.3 {
    39     39     SELECT rowid, fts5_test_collist(t1) FROM t1('b:a');
    40     40   } {}
           41  +
           42  +#-------------------------------------------------------------------------
           43  +# Create detail=col and detail=full tables with 998 columns.
           44  +#
           45  +foreach_detail_mode $testprefix {
           46  +  if {[detail_is_none]} continue
           47  +
           48  +  do_test 2.1 {
           49  +    execsql { DROP TABLE IF EXISTS t2 }
           50  +    set cols [list]
           51  +    set vals [list]
           52  +    for {set i 1} {$i <= 998} {incr i} {
           53  +      lappend cols "c$i"
           54  +      lappend vals "'val$i'"
           55  +    }
           56  +    execsql "CREATE VIRTUAL TABLE t2 USING fts5(detail=%DETAIL%,[join $cols ,])"
           57  +  } {}
           58  +  
           59  +  do_test 2.2 {
           60  +    execsql "INSERT INTO t2 VALUES([join $vals ,])"
           61  +  } {}
           62  +  
           63  +  foreach {tn q res} {
           64  +    1 { c1:val1 }     1
           65  +    2 { c300:val300 } 1
           66  +    3 { c300:val1 } {}
           67  +    4 { c1:val300 } {}
           68  +  } {
           69  +    do_execsql_test 2.3.$tn {
           70  +      SELECT rowid FROM t2($q)
           71  +    } $res
           72  +  }
           73  +}
           74  +
           75  +do_execsql_test 3.0 {
           76  +  CREATE VIRTUAL TABLE x3 USING fts5(one);
           77  +  INSERT INTO x3 VALUES('a b c');
           78  +  INSERT INTO x3 VALUES('c b a');
           79  +  INSERT INTO x3 VALUES('o t t');
           80  +  SELECT * FROM x3('x OR y OR z');
           81  +}
    41     82   
    42     83   
    43     84   finish_test
    44     85   

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

     8      8     {100 "SELECT count(*) FROM t1 WHERE t1 MATCH 'enron AND myapps'"}
     9      9     {1   "SELECT count(*) FROM t1 WHERE t1 MATCH 'en* AND my*'"}
    10     10   
    11     11     {1   "SELECT count(*) FROM t1 WHERE t1 MATCH 'c:t*'"}
    12     12     {1   "SELECT count(*) FROM t1 WHERE t1 MATCH 'a:t* OR b:t* OR c:t* OR d:t* OR e:t* OR f:t* OR g:t*'"}
    13     13     {1   "SELECT count(*) FROM t1 WHERE t1 MATCH 'a:t*'"}
    14     14     {2   "SELECT count(*) FROM t1 WHERE t1 MATCH 'c:the'"}
           15  +
           16  +  {2   "SELECT count(*) FROM t1 WHERE t1 MATCH 'd:holmes OR e:holmes OR f:holmes OR g:holmes'" }
           17  +  {2   "SELECT count(*) FROM t1 WHERE t1 MATCH 'd:holmes AND e:holmes AND f:holmes AND g:holmes'" }
           18  +  {4   "SELECT count(*) FROM t1 WHERE t1 MATCH 'd:holmes NOT e:holmes'" }
    15     19   }
    16     20   
    17     21   proc usage {} {
    18     22     global Q
    19     23     puts stderr "Usage: $::argv0 DATABASE QUERY"
    20     24     puts stderr ""
    21     25     for {set i 1} {$i <= [llength $Q]} {incr i} {

Changes to ext/misc/json1.c.

   272    272   ** string.
   273    273   */
   274    274   static void jsonAppendString(JsonString *p, const char *zIn, u32 N){
   275    275     u32 i;
   276    276     if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return;
   277    277     p->zBuf[p->nUsed++] = '"';
   278    278     for(i=0; i<N; i++){
   279         -    char c = zIn[i];
          279  +    unsigned char c = ((unsigned const char*)zIn)[i];
   280    280       if( c=='"' || c=='\\' ){
          281  +      json_simple_escape:
   281    282         if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return;
   282    283         p->zBuf[p->nUsed++] = '\\';
          284  +    }else if( c<=0x1f ){
          285  +      static const char aSpecial[] = {
          286  +         0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0,
          287  +         0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0,   0,   0, 0, 0
          288  +      };
          289  +      assert( sizeof(aSpecial)==32 );
          290  +      assert( aSpecial['\b']=='b' );
          291  +      assert( aSpecial['\f']=='f' );
          292  +      assert( aSpecial['\n']=='n' );
          293  +      assert( aSpecial['\r']=='r' );
          294  +      assert( aSpecial['\t']=='t' );
          295  +      if( aSpecial[c] ){
          296  +        c = aSpecial[c];
          297  +        goto json_simple_escape;
          298  +      }
          299  +      if( (p->nUsed+N+7+i > p->nAlloc) && jsonGrow(p,N+7-i)!=0 ) return;
          300  +      p->zBuf[p->nUsed++] = '\\';
          301  +      p->zBuf[p->nUsed++] = 'u';
          302  +      p->zBuf[p->nUsed++] = '0';
          303  +      p->zBuf[p->nUsed++] = '0';
          304  +      p->zBuf[p->nUsed++] = '0' + (c>>4);
          305  +      c = "0123456789abcdef"[c&0xf];
   283    306       }
   284    307       p->zBuf[p->nUsed++] = c;
   285    308     }
   286    309     p->zBuf[p->nUsed++] = '"';
   287    310     assert( p->nUsed<p->nAlloc );
   288    311   }
   289    312   
................................................................................
   316    339           jsonAppendString(p, z, n);
   317    340         }
   318    341         break;
   319    342       }
   320    343       default: {
   321    344         if( p->bErr==0 ){
   322    345           sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1);
   323         -        p->bErr = 1;
          346  +        p->bErr = 2;
   324    347           jsonReset(p);
   325    348         }
   326    349         break;
   327    350       }
   328    351     }
   329    352   }
   330    353   
................................................................................
  1544   1567   static void jsonArrayFinal(sqlite3_context *ctx){
  1545   1568     JsonString *pStr;
  1546   1569     pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
  1547   1570     if( pStr ){
  1548   1571       pStr->pCtx = ctx;
  1549   1572       jsonAppendChar(pStr, ']');
  1550   1573       if( pStr->bErr ){
  1551         -      sqlite3_result_error_nomem(ctx);
         1574  +      if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx);
  1552   1575         assert( pStr->bStatic );
  1553   1576       }else{
  1554   1577         sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed,
  1555   1578                             pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free);
  1556   1579         pStr->bStatic = 1;
  1557   1580       }
  1558   1581     }else{
................................................................................
  1592   1615   }
  1593   1616   static void jsonObjectFinal(sqlite3_context *ctx){
  1594   1617     JsonString *pStr;
  1595   1618     pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
  1596   1619     if( pStr ){
  1597   1620       jsonAppendChar(pStr, '}');
  1598   1621       if( pStr->bErr ){
  1599         -      sqlite3_result_error_nomem(ctx);
         1622  +      if( pStr->bErr==0 ) sqlite3_result_error_nomem(ctx);
  1600   1623         assert( pStr->bStatic );
  1601   1624       }else{
  1602   1625         sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed,
  1603   1626                             pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free);
  1604   1627         pStr->bStatic = 1;
  1605   1628       }
  1606   1629     }else{

Changes to ext/misc/spellfix.c.

   182    182   **   * Omit K in KN or G in GN at the beginning of a word
   183    183   **
   184    184   ** Space to hold the result is obtained from sqlite3_malloc()
   185    185   **
   186    186   ** Return NULL if memory allocation fails.  
   187    187   */
   188    188   static unsigned char *phoneticHash(const unsigned char *zIn, int nIn){
   189         -  unsigned char *zOut = sqlite3_malloc( nIn + 1 );
          189  +  unsigned char *zOut = sqlite3_malloc64( nIn + 1 );
   190    190     int i;
   191    191     int nOut = 0;
   192    192     char cPrev = 0x77;
   193    193     char cPrevX = 0x77;
   194    194     const unsigned char *aClass = initClass;
   195    195   
   196    196     if( zOut==0 ) return 0;
................................................................................
   409    409     /* A is a prefix of B */
   410    410     if( zA[0]=='*' && zA[1]==0 ) return 0;
   411    411   
   412    412     /* Allocate and initialize the Wagner matrix */
   413    413     if( nB<(sizeof(mStack)*4)/(sizeof(mStack[0])*5) ){
   414    414       m = mStack;
   415    415     }else{
   416         -    m = toFree = sqlite3_malloc( (nB+1)*5*sizeof(m[0])/4 );
          416  +    m = toFree = sqlite3_malloc64( (nB+1)*5*sizeof(m[0])/4 );
   417    417       if( m==0 ) return -3;
   418    418     }
   419    419     cx = (char*)&m[nB+1];
   420    420   
   421    421     /* Compute the Wagner edit distance */
   422    422     m[0] = 0;
   423    423     cx[0] = dc;
................................................................................
   683    683   
   684    684       assert( zFrom!=0 || nFrom==0 );
   685    685       assert( zTo!=0 || nTo==0 );
   686    686       if( nFrom>100 || nTo>100 ) continue;
   687    687       if( iCost<0 ) continue;
   688    688       if( pLang==0 || iLang!=iLangPrev ){
   689    689         EditDist3Lang *pNew;
   690         -      pNew = sqlite3_realloc(p->a, (p->nLang+1)*sizeof(p->a[0]));
          690  +      pNew = sqlite3_realloc64(p->a, (p->nLang+1)*sizeof(p->a[0]));
   691    691         if( pNew==0 ){ rc = SQLITE_NOMEM; break; }
   692    692         p->a = pNew;
   693    693         pLang = &p->a[p->nLang];
   694    694         p->nLang++;
   695    695         pLang->iLang = iLang;
   696    696         pLang->iInsCost = 100;
   697    697         pLang->iDelCost = 100;
................................................................................
   705    705         pLang->iInsCost = iCost;
   706    706       }else if( nFrom==1 && nTo==1 && zFrom[0]=='?' && zTo[0]=='?' ){
   707    707         pLang->iSubCost = iCost;
   708    708       }else{
   709    709         EditDist3Cost *pCost;
   710    710         int nExtra = nFrom + nTo - 4;
   711    711         if( nExtra<0 ) nExtra = 0;
   712         -      pCost = sqlite3_malloc( sizeof(*pCost) + nExtra );
          712  +      pCost = sqlite3_malloc64( sizeof(*pCost) + nExtra );
   713    713         if( pCost==0 ){ rc = SQLITE_NOMEM; break; }
   714    714         pCost->nFrom = nFrom;
   715    715         pCost->nTo = nTo;
   716    716         pCost->iCost = iCost;
   717    717         memcpy(pCost->a, zFrom, nFrom);
   718    718         memcpy(pCost->a + nFrom, zTo, nTo);
   719    719         pCost->pNext = pLang->pCost;
................................................................................
   804    804   ){
   805    805     EditDist3FromString *pStr;
   806    806     EditDist3Cost *p;
   807    807     int i;
   808    808   
   809    809     if( z==0 ) return 0;
   810    810     if( n<0 ) n = (int)strlen(z);
   811         -  pStr = sqlite3_malloc( sizeof(*pStr) + sizeof(pStr->a[0])*n + n + 1 );
          811  +  pStr = sqlite3_malloc64( sizeof(*pStr) + sizeof(pStr->a[0])*n + n + 1 );
   812    812     if( pStr==0 ) return 0;
   813    813     pStr->a = (EditDist3From*)&pStr[1];
   814    814     memset(pStr->a, 0, sizeof(pStr->a[0])*n);
   815    815     pStr->n = n;
   816    816     pStr->z = (char*)&pStr->a[n];
   817    817     memcpy(pStr->z, z, n+1);
   818    818     if( n && z[n-1]=='*' ){
................................................................................
   829    829       memset(pFrom, 0, sizeof(*pFrom));
   830    830       pFrom->nByte = utf8Len((unsigned char)z[i], n-i);
   831    831       for(p=pLang->pCost; p; p=p->pNext){
   832    832         EditDist3Cost **apNew;
   833    833         if( i+p->nFrom>n ) continue;
   834    834         if( matchFrom(p, z+i, n-i)==0 ) continue;
   835    835         if( p->nTo==0 ){
   836         -        apNew = sqlite3_realloc(pFrom->apDel,
          836  +        apNew = sqlite3_realloc64(pFrom->apDel,
   837    837                                   sizeof(*apNew)*(pFrom->nDel+1));
   838    838           if( apNew==0 ) break;
   839    839           pFrom->apDel = apNew;
   840    840           apNew[pFrom->nDel++] = p;
   841    841         }else{
   842         -        apNew = sqlite3_realloc(pFrom->apSubst,
          842  +        apNew = sqlite3_realloc64(pFrom->apSubst,
   843    843                                   sizeof(*apNew)*(pFrom->nSubst+1));
   844    844           if( apNew==0 ) break;
   845    845           pFrom->apSubst = apNew;
   846    846           apNew[pFrom->nSubst++] = p;
   847    847         }
   848    848       }
   849    849       if( p ){
................................................................................
   921    921     n = (f.n+1)*(n2+1);
   922    922     n = (n+1)&~1;
   923    923     nByte = n*sizeof(m[0]) + sizeof(a2[0])*n2;
   924    924     if( nByte<=sizeof(stackSpace) ){
   925    925       m = stackSpace;
   926    926       pToFree = 0;
   927    927     }else{
   928         -    m = pToFree = sqlite3_malloc( nByte );
          928  +    m = pToFree = sqlite3_malloc64( nByte );
   929    929       if( m==0 ) return -1;            /* Out of memory */
   930    930     }
   931    931     a2 = (EditDist3To*)&m[n];
   932    932     memset(a2, 0, sizeof(a2[0])*n2);
   933    933   
   934    934     /* Fill in the a1[] matrix for all characters of the TO string */
   935    935     for(i2=0; i2<n2; i2++){
................................................................................
   936    936       a2[i2].nByte = utf8Len((unsigned char)z2[i2], n2-i2);
   937    937       for(p=pLang->pCost; p; p=p->pNext){
   938    938         EditDist3Cost **apNew;
   939    939         if( p->nFrom>0 ) continue;
   940    940         if( i2+p->nTo>n2 ) continue;
   941    941         if( matchTo(p, z2+i2, n2-i2)==0 ) continue;
   942    942         a2[i2].nIns++;
   943         -      apNew = sqlite3_realloc(a2[i2].apIns, sizeof(*apNew)*a2[i2].nIns);
          943  +      apNew = sqlite3_realloc64(a2[i2].apIns, sizeof(*apNew)*a2[i2].nIns);
   944    944         if( apNew==0 ){
   945    945           res = -1;  /* Out of memory */
   946    946           goto editDist3Abort;
   947    947         }
   948    948         a2[i2].apIns = apNew;
   949    949         a2[i2].apIns[a2[i2].nIns-1] = p;
   950    950       }
................................................................................
  1114   1114   }
  1115   1115   
  1116   1116   /*
  1117   1117   ** Register the editDist3 function with SQLite
  1118   1118   */
  1119   1119   static int editDist3Install(sqlite3 *db){
  1120   1120     int rc;
  1121         -  EditDist3Config *pConfig = sqlite3_malloc( sizeof(*pConfig) );
         1121  +  EditDist3Config *pConfig = sqlite3_malloc64( sizeof(*pConfig) );
  1122   1122     if( pConfig==0 ) return SQLITE_NOMEM;
  1123   1123     memset(pConfig, 0, sizeof(*pConfig));
  1124   1124     rc = sqlite3_create_function_v2(db, "editdist3",
  1125   1125                 2, SQLITE_UTF8, pConfig, editDist3SqlFunc, 0, 0, 0);
  1126   1126     if( rc==SQLITE_OK ){
  1127   1127       rc = sqlite3_create_function_v2(db, "editdist3",
  1128   1128                   3, SQLITE_UTF8, pConfig, editDist3SqlFunc, 0, 0, 0);
................................................................................
  1603   1603   **
  1604   1604   ** The returned string might contain more characters than the input.
  1605   1605   **
  1606   1606   ** Space to hold the returned string comes from sqlite3_malloc() and
  1607   1607   ** should be freed by the caller.
  1608   1608   */
  1609   1609   static unsigned char *transliterate(const unsigned char *zIn, int nIn){
  1610         -  unsigned char *zOut = sqlite3_malloc( nIn*4 + 1 );
         1610  +  unsigned char *zOut = sqlite3_malloc64( nIn*4 + 1 );
  1611   1611     int c, sz, nOut;
  1612   1612     if( zOut==0 ) return 0;
  1613   1613     nOut = 0;
  1614   1614     while( nIn>0 ){
  1615   1615       c = utf8Read(zIn, nIn, &sz);
  1616   1616       zIn += sz;
  1617   1617       nIn -= sz;
................................................................................
  1926   1926     const char *zDbName = argv[1];
  1927   1927     const char *zTableName = argv[2];
  1928   1928     int nDbName;
  1929   1929     int rc = SQLITE_OK;
  1930   1930     int i;
  1931   1931   
  1932   1932     nDbName = (int)strlen(zDbName);
  1933         -  pNew = sqlite3_malloc( sizeof(*pNew) + nDbName + 1);
         1933  +  pNew = sqlite3_malloc64( sizeof(*pNew) + nDbName + 1);
  1934   1934     if( pNew==0 ){
  1935   1935       rc = SQLITE_NOMEM;
  1936   1936     }else{
  1937   1937       memset(pNew, 0, sizeof(*pNew));
  1938   1938       pNew->zDbName = (char*)&pNew[1];
  1939   1939       memcpy(pNew->zDbName, zDbName, nDbName+1);
  1940   1940       pNew->zTableName = sqlite3_mprintf("%s", zTableName);
................................................................................
  2040   2040   
  2041   2041   /*
  2042   2042   ** Resize the cursor to hold up to N rows of content
  2043   2043   */
  2044   2044   static void spellfix1ResizeCursor(spellfix1_cursor *pCur, int N){
  2045   2045     struct spellfix1_row *aNew;
  2046   2046     assert( N>=pCur->nRow );
  2047         -  aNew = sqlite3_realloc(pCur->a, sizeof(pCur->a[0])*N);
         2047  +  aNew = sqlite3_realloc64(pCur->a, sizeof(pCur->a[0])*N);
  2048   2048     if( aNew==0 && N>0 ){
  2049   2049       spellfix1ResetCursor(pCur);
  2050   2050       sqlite3_free(pCur->a);
  2051   2051       pCur->nAlloc = 0;
  2052   2052       pCur->a = 0;
  2053   2053     }else{
  2054   2054       pCur->nAlloc = N;
................................................................................
  2199   2199   
  2200   2200   /*
  2201   2201   ** Open a new fuzzy-search cursor.
  2202   2202   */
  2203   2203   static int spellfix1Open(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
  2204   2204     spellfix1_vtab *p = (spellfix1_vtab*)pVTab;
  2205   2205     spellfix1_cursor *pCur;
  2206         -  pCur = sqlite3_malloc( sizeof(*pCur) );
         2206  +  pCur = sqlite3_malloc64( sizeof(*pCur) );
  2207   2207     if( pCur==0 ) return SQLITE_NOMEM;
  2208   2208     memset(pCur, 0, sizeof(*pCur));
  2209   2209     pCur->pVTab = p;
  2210   2210     *ppCursor = &pCur->base;
  2211   2211     return SQLITE_OK;
  2212   2212   }
  2213   2213   
................................................................................
  2413   2413     int rc;                            /* Result code */
  2414   2414     int idx = 1;                       /* Next available filter parameter */
  2415   2415     spellfix1_vtab *p = pCur->pVTab;   /* The virtual table that owns pCur */
  2416   2416     MatchQuery x;                      /* For passing info to RunQuery() */
  2417   2417   
  2418   2418     /* Load the cost table if we have not already done so */
  2419   2419     if( p->zCostTable!=0 && p->pConfig3==0 ){
  2420         -    p->pConfig3 = sqlite3_malloc( sizeof(p->pConfig3[0]) );
         2420  +    p->pConfig3 = sqlite3_malloc64( sizeof(p->pConfig3[0]) );
  2421   2421       if( p->pConfig3==0 ) return SQLITE_NOMEM;
  2422   2422       memset(p->pConfig3, 0, sizeof(p->pConfig3[0]));
  2423   2423       rc = editDist3ConfigLoad(p->pConfig3, p->db, p->zCostTable);
  2424   2424       if( rc ) return rc;
  2425   2425     }
  2426   2426     memset(&x, 0, sizeof(x));
  2427   2427     x.iScope = 3;  /* Default scope if none specified by "WHERE scope=N" */

Changes to src/alter.c.

   691    691     */
   692    692     if( pDflt ){
   693    693       sqlite3_value *pVal = 0;
   694    694       int rc;
   695    695       rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal);
   696    696       assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
   697    697       if( rc!=SQLITE_OK ){
   698         -      db->mallocFailed = 1;
          698  +      assert( db->mallocFailed = 1 );
   699    699         return;
   700    700       }
   701    701       if( !pVal ){
   702    702         sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default");
   703    703         return;
   704    704       }
   705    705       sqlite3ValueFree(pVal);
................................................................................
   799    799     pNew->nCol = pTab->nCol;
   800    800     assert( pNew->nCol>0 );
   801    801     nAlloc = (((pNew->nCol-1)/8)*8)+8;
   802    802     assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 );
   803    803     pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc);
   804    804     pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName);
   805    805     if( !pNew->aCol || !pNew->zName ){
   806         -    db->mallocFailed = 1;
          806  +    assert( db->mallocFailed );
   807    807       goto exit_begin_add_column;
   808    808     }
   809    809     memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
   810    810     for(i=0; i<pNew->nCol; i++){
   811    811       Column *pCol = &pNew->aCol[i];
   812    812       pCol->zName = sqlite3DbStrDup(db, pCol->zName);
   813    813       pCol->zColl = 0;

Changes to src/analyze.c.

   309    309   
   310    310   /* Initialize the BLOB value of a ROWID
   311    311   */
   312    312   #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
   313    313   static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){
   314    314     assert( db!=0 );
   315    315     if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid);
   316         -  p->u.aRowid = sqlite3DbMallocRaw(db, n);
          316  +  p->u.aRowid = sqlite3DbMallocRawNN(db, n);
   317    317     if( p->u.aRowid ){
   318    318       p->nRowid = n;
   319    319       memcpy(p->u.aRowid, pData, n);
   320    320     }else{
   321    321       p->nRowid = 0;
   322    322     }
   323    323   }
................................................................................
  1111   1111       VdbeCoverage(v);
  1112   1112       sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng);
  1113   1113       addrNextRow = sqlite3VdbeCurrentAddr(v);
  1114   1114   
  1115   1115       if( nColTest>0 ){
  1116   1116         int endDistinctTest = sqlite3VdbeMakeLabel(v);
  1117   1117         int *aGotoChng;               /* Array of jump instruction addresses */
  1118         -      aGotoChng = sqlite3DbMallocRaw(db, sizeof(int)*nColTest);
         1118  +      aGotoChng = sqlite3DbMallocRawNN(db, sizeof(int)*nColTest);
  1119   1119         if( aGotoChng==0 ) continue;
  1120   1120   
  1121   1121         /*
  1122   1122         **  next_row:
  1123   1123         **   regChng = 0
  1124   1124         **   if( idx(0) != regPrev(0) ) goto chng_addr_0
  1125   1125         **   regChng = 1
................................................................................
  1519   1519       int nCol = pIndex->nKeyCol+1;
  1520   1520   #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  1521   1521       /* Index.aiRowEst may already be set here if there are duplicate 
  1522   1522       ** sqlite_stat1 entries for this index. In that case just clobber
  1523   1523       ** the old data with the new instead of allocating a new array.  */
  1524   1524       if( pIndex->aiRowEst==0 ){
  1525   1525         pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(sizeof(tRowcnt) * nCol);
  1526         -      if( pIndex->aiRowEst==0 ) pInfo->db->mallocFailed = 1;
         1526  +      if( pIndex->aiRowEst==0 ) sqlite3OomFault(pInfo->db);
  1527   1527       }
  1528   1528       aiRowEst = pIndex->aiRowEst;
  1529   1529   #endif
  1530   1530       pIndex->bUnordered = 0;
  1531   1531       decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex);
  1532   1532       if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0];
  1533   1533     }else{
................................................................................
  1666   1666   ){
  1667   1667     int rc;                       /* Result codes from subroutines */
  1668   1668     sqlite3_stmt *pStmt = 0;      /* An SQL statement being run */
  1669   1669     char *zSql;                   /* Text of the SQL statement */
  1670   1670     Index *pPrevIdx = 0;          /* Previous index in the loop */
  1671   1671     IndexSample *pSample;         /* A slot in pIdx->aSample[] */
  1672   1672   
  1673         -  assert( db->lookaside.bEnabled==0 );
         1673  +  assert( db->lookaside.bDisable );
  1674   1674     zSql = sqlite3MPrintf(db, zSql1, zDb);
  1675   1675     if( !zSql ){
  1676   1676       return SQLITE_NOMEM;
  1677   1677     }
  1678   1678     rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
  1679   1679     sqlite3DbFree(db, zSql);
  1680   1680     if( rc ) return rc;
................................................................................
  1780   1780   /*
  1781   1781   ** Load content from the sqlite_stat4 and sqlite_stat3 tables into 
  1782   1782   ** the Index.aSample[] arrays of all indices.
  1783   1783   */
  1784   1784   static int loadStat4(sqlite3 *db, const char *zDb){
  1785   1785     int rc = SQLITE_OK;             /* Result codes from subroutines */
  1786   1786   
  1787         -  assert( db->lookaside.bEnabled==0 );
         1787  +  assert( db->lookaside.bDisable );
  1788   1788     if( sqlite3FindTable(db, "sqlite_stat4", zDb) ){
  1789   1789       rc = loadStatTbl(db, 0,
  1790   1790         "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx", 
  1791   1791         "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4",
  1792   1792         zDb
  1793   1793       );
  1794   1794     }
................................................................................
  1862   1862       sqlite3DbFree(db, zSql);
  1863   1863     }
  1864   1864   
  1865   1865   
  1866   1866     /* Load the statistics from the sqlite_stat4 table. */
  1867   1867   #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  1868   1868     if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){
  1869         -    int lookasideEnabled = db->lookaside.bEnabled;
  1870         -    db->lookaside.bEnabled = 0;
         1869  +    db->lookaside.bDisable++;
  1871   1870       rc = loadStat4(db, sInfo.zDatabase);
  1872         -    db->lookaside.bEnabled = lookasideEnabled;
         1871  +    db->lookaside.bDisable--;
  1873   1872     }
  1874   1873     for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
  1875   1874       Index *pIdx = sqliteHashData(i);
  1876   1875       sqlite3_free(pIdx->aiRowEst);
  1877   1876       pIdx->aiRowEst = 0;
  1878   1877     }
  1879   1878   #endif
  1880   1879   
  1881   1880     if( rc==SQLITE_NOMEM ){
  1882         -    db->mallocFailed = 1;
         1881  +    sqlite3OomFault(db);
  1883   1882     }
  1884   1883     return rc;
  1885   1884   }
  1886   1885   
  1887   1886   
  1888   1887   #endif /* SQLITE_OMIT_ANALYZE */

Changes to src/attach.c.

   105    105       }
   106    106     }
   107    107   
   108    108     /* Allocate the new entry in the db->aDb[] array and initialize the schema
   109    109     ** hash tables.
   110    110     */
   111    111     if( db->aDb==db->aDbStatic ){
   112         -    aNew = sqlite3DbMallocRaw(db, sizeof(db->aDb[0])*3 );
          112  +    aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 );
   113    113       if( aNew==0 ) return;
   114    114       memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
   115    115     }else{
   116    116       aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
   117    117       if( aNew==0 ) return;
   118    118     }
   119    119     db->aDb = aNew;
................................................................................
   123    123     /* Open the database file. If the btree is successfully opened, use
   124    124     ** it to obtain the database schema. At this point the schema may
   125    125     ** or may not be initialized.
   126    126     */
   127    127     flags = db->openFlags;
   128    128     rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr);
   129    129     if( rc!=SQLITE_OK ){
   130         -    if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
          130  +    if( rc==SQLITE_NOMEM ) sqlite3OomFault(db);
   131    131       sqlite3_result_error(context, zErr, -1);
   132    132       sqlite3_free(zErr);
   133    133       return;
   134    134     }
   135    135     assert( pVfs );
   136    136     flags |= SQLITE_OPEN_MAIN_DB;
   137    137     rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags);
................................................................................
   152    152       }
   153    153       sqlite3BtreeEnter(aNew->pBt);
   154    154       pPager = sqlite3BtreePager(aNew->pBt);
   155    155       sqlite3PagerLockingMode(pPager, db->dfltLockMode);
   156    156       sqlite3BtreeSecureDelete(aNew->pBt,
   157    157                                sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) );
   158    158   #ifndef SQLITE_OMIT_PAGER_PRAGMAS
   159         -    sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK));
          159  +    sqlite3BtreeSetPagerFlags(aNew->pBt,
          160  +                      PAGER_SYNCHRONOUS_FULL | (db->flags & PAGER_FLAGS_MASK));
   160    161   #endif
   161    162       sqlite3BtreeLeave(aNew->pBt);
   162    163     }
   163    164     aNew->safety_level = 3;
   164    165     aNew->zName = sqlite3DbStrDup(db, zName);
   165    166     if( rc==SQLITE_OK && aNew->zName==0 ){
   166    167       rc = SQLITE_NOMEM;
................................................................................
   225    226         sqlite3BtreeClose(db->aDb[iDb].pBt);
   226    227         db->aDb[iDb].pBt = 0;
   227    228         db->aDb[iDb].pSchema = 0;
   228    229       }
   229    230       sqlite3ResetAllSchemasOfConnection(db);
   230    231       db->nDb = iDb;
   231    232       if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
   232         -      db->mallocFailed = 1;
          233  +      sqlite3OomFault(db);
   233    234         sqlite3DbFree(db, zErrDyn);
   234    235         zErrDyn = sqlite3MPrintf(db, "out of memory");
   235    236       }else if( zErrDyn==0 ){
   236    237         zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile);
   237    238       }
   238    239       goto attach_error;
   239    240     }

Changes to src/btree.c.

  2340   2340         MUTEX_LOGIC( sqlite3_mutex *mutexShared; )
  2341   2341         pBt->nRef = 1;
  2342   2342         MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);)
  2343   2343         if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){
  2344   2344           pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST);
  2345   2345           if( pBt->mutex==0 ){
  2346   2346             rc = SQLITE_NOMEM;
  2347         -          db->mallocFailed = 0;
  2348   2347             goto btree_open_out;
  2349   2348           }
  2350   2349         }
  2351   2350         sqlite3_mutex_enter(mutexShared);
  2352   2351         pBt->pNext = GLOBAL(BtShared*,sqlite3SharedCacheList);
  2353   2352         GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt;
  2354   2353         sqlite3_mutex_leave(mutexShared);

Changes to src/build.c.

    74     74       p = &pToplevel->aTableLock[pToplevel->nTableLock++];
    75     75       p->iDb = iDb;
    76     76       p->iTab = iTab;
    77     77       p->isWriteLock = isWriteLock;
    78     78       p->zName = zName;
    79     79     }else{
    80     80       pToplevel->nTableLock = 0;
    81         -    pToplevel->db->mallocFailed = 1;
           81  +    sqlite3OomFault(pToplevel->db);
    82     82     }
    83     83   }
    84     84   
    85     85   /*
    86     86   ** Code an OP_TableLock instruction for each table locked by the
    87     87   ** statement (configured by calls to sqlite3TableLock()).
    88     88   */
................................................................................
   922    922         sqlite3ErrorMsg(pParse, "there is already an index named %s", zName);
   923    923         goto begin_table_error;
   924    924       }
   925    925     }
   926    926   
   927    927     pTable = sqlite3DbMallocZero(db, sizeof(Table));
   928    928     if( pTable==0 ){
   929         -    db->mallocFailed = 1;
          929  +    assert( db->mallocFailed );
   930    930       pParse->rc = SQLITE_NOMEM;
   931    931       pParse->nErr++;
   932    932       goto begin_table_error;
   933    933     }
   934    934     pTable->zName = zName;
   935    935     pTable->iPKey = -1;
   936    936     pTable->pSchema = db->aDb[iDb].pSchema;
................................................................................
  1551   1551       zSep = "\n  ";
  1552   1552       zSep2 = ",\n  ";
  1553   1553       zEnd = "\n)";
  1554   1554     }
  1555   1555     n += 35 + 6*p->nCol;
  1556   1556     zStmt = sqlite3DbMallocRaw(0, n);
  1557   1557     if( zStmt==0 ){
  1558         -    db->mallocFailed = 1;
         1558  +    sqlite3OomFault(db);
  1559   1559       return 0;
  1560   1560     }
  1561   1561     sqlite3_snprintf(n, zStmt, "CREATE TABLE ");
  1562   1562     k = sqlite3Strlen30(zStmt);
  1563   1563     identPut(zStmt, &k, p->zName);
  1564   1564     zStmt[k++] = '(';
  1565   1565     for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){
................................................................................
  2034   2034     if( db->init.busy ){
  2035   2035       Table *pOld;
  2036   2036       Schema *pSchema = p->pSchema;
  2037   2037       assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
  2038   2038       pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p);
  2039   2039       if( pOld ){
  2040   2040         assert( p==pOld );  /* Malloc must have failed inside HashInsert() */
  2041         -      db->mallocFailed = 1;
         2041  +      sqlite3OomFault(db);
  2042   2042         return;
  2043   2043       }
  2044   2044       pParse->pNewTable = 0;
  2045   2045       db->flags |= SQLITE_InternChanges;
  2046   2046   
  2047   2047   #ifndef SQLITE_OMIT_ALTERTABLE
  2048   2048       if( !p->pSelect ){
................................................................................
  2138   2138   int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
  2139   2139     Table *pSelTab;   /* A fake table from which we get the result set */
  2140   2140     Select *pSel;     /* Copy of the SELECT that implements the view */
  2141   2141     int nErr = 0;     /* Number of errors encountered */
  2142   2142     int n;            /* Temporarily holds the number of cursors assigned */
  2143   2143     sqlite3 *db = pParse->db;  /* Database connection for malloc errors */
  2144   2144     sqlite3_xauth xAuth;       /* Saved xAuth pointer */
  2145         -  u8 bEnabledLA;             /* Saved db->lookaside.bEnabled state */
  2146   2145   
  2147   2146     assert( pTable );
  2148   2147   
  2149   2148   #ifndef SQLITE_OMIT_VIRTUALTABLE
  2150   2149     if( sqlite3VtabCallConnect(pParse, pTable) ){
  2151   2150       return SQLITE_ERROR;
  2152   2151     }
................................................................................
  2184   2183     ** Note that the call to sqlite3ResultSetOfSelect() will expand any
  2185   2184     ** "*" elements in the results set of the view and will assign cursors
  2186   2185     ** to the elements of the FROM clause.  But we do not want these changes
  2187   2186     ** to be permanent.  So the computation is done on a copy of the SELECT
  2188   2187     ** statement that defines the view.
  2189   2188     */
  2190   2189     assert( pTable->pSelect );
  2191         -  bEnabledLA = db->lookaside.bEnabled;
  2192   2190     if( pTable->pCheck ){
  2193         -    db->lookaside.bEnabled = 0;
         2191  +    db->lookaside.bDisable++;
  2194   2192       sqlite3ColumnsFromExprList(pParse, pTable->pCheck, 
  2195   2193                                  &pTable->nCol, &pTable->aCol);
         2194  +    db->lookaside.bDisable--;
  2196   2195     }else{
  2197   2196       pSel = sqlite3SelectDup(db, pTable->pSelect, 0);
  2198   2197       if( pSel ){
  2199   2198         n = pParse->nTab;
  2200   2199         sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
  2201   2200         pTable->nCol = -1;
  2202         -      db->lookaside.bEnabled = 0;
         2201  +      db->lookaside.bDisable++;
  2203   2202   #ifndef SQLITE_OMIT_AUTHORIZATION
  2204   2203         xAuth = db->xAuth;
  2205   2204         db->xAuth = 0;
  2206   2205         pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
  2207   2206         db->xAuth = xAuth;
  2208   2207   #else
  2209   2208         pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
  2210   2209   #endif
         2210  +      db->lookaside.bDisable--;
  2211   2211         pParse->nTab = n;
  2212   2212         if( pSelTab ){
  2213   2213           assert( pTable->aCol==0 );
  2214   2214           pTable->nCol = pSelTab->nCol;
  2215   2215           pTable->aCol = pSelTab->aCol;
  2216   2216           pSelTab->nCol = 0;
  2217   2217           pSelTab->aCol = 0;
................................................................................
  2222   2222           nErr++;
  2223   2223         }
  2224   2224         sqlite3SelectDelete(db, pSel);
  2225   2225       } else {
  2226   2226         nErr++;
  2227   2227       }
  2228   2228     }
  2229         -  db->lookaside.bEnabled = bEnabledLA;
  2230   2229     pTable->pSchema->schemaFlags |= DB_UnresetViews;
  2231   2230   #endif /* SQLITE_OMIT_VIEW */
  2232   2231     return nErr;  
  2233   2232   }
  2234   2233   #endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */
  2235   2234   
  2236   2235   #ifndef SQLITE_OMIT_VIEW
................................................................................
  2688   2687     pFKey->aAction[1] = (u8)((flags >> 8 ) & 0xff);    /* ON UPDATE action */
  2689   2688   
  2690   2689     assert( sqlite3SchemaMutexHeld(db, 0, p->pSchema) );
  2691   2690     pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash, 
  2692   2691         pFKey->zTo, (void *)pFKey
  2693   2692     );
  2694   2693     if( pNextTo==pFKey ){
  2695         -    db->mallocFailed = 1;
         2694  +    sqlite3OomFault(db);
  2696   2695       goto fk_end;
  2697   2696     }
  2698   2697     if( pNextTo ){
  2699   2698       assert( pNextTo->pPrevTo==0 );
  2700   2699       pFKey->pNextTo = pNextTo;
  2701   2700       pNextTo->pPrevTo = pFKey;
  2702   2701     }
................................................................................
  3270   3269     if( db->init.busy ){
  3271   3270       Index *p;
  3272   3271       assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
  3273   3272       p = sqlite3HashInsert(&pIndex->pSchema->idxHash, 
  3274   3273                             pIndex->zName, pIndex);
  3275   3274       if( p ){
  3276   3275         assert( p==pIndex );  /* Malloc must have failed */
  3277         -      db->mallocFailed = 1;
         3276  +      sqlite3OomFault(db);
  3278   3277         goto exit_create_index;
  3279   3278       }
  3280   3279       db->flags |= SQLITE_InternChanges;
  3281   3280       if( pTblName!=0 ){
  3282   3281         pIndex->tnum = db->init.newTnum;
  3283   3282       }
  3284   3283     }
................................................................................
  3699   3698     sqlite3 *db,        /* Connection to notify of malloc failures */
  3700   3699     SrcList *pList,     /* Append to this SrcList. NULL creates a new SrcList */
  3701   3700     Token *pTable,      /* Table to append */
  3702   3701     Token *pDatabase    /* Database of the table */
  3703   3702   ){
  3704   3703     struct SrcList_item *pItem;
  3705   3704     assert( pDatabase==0 || pTable!=0 );  /* Cannot have C without B */
         3705  +  assert( db!=0 );
  3706   3706     if( pList==0 ){
  3707         -    pList = sqlite3DbMallocRaw(db, sizeof(SrcList) );
         3707  +    pList = sqlite3DbMallocRawNN(db, sizeof(SrcList) );
  3708   3708       if( pList==0 ) return 0;
  3709   3709       pList->nAlloc = 1;
  3710   3710       pList->nSrc = 0;
  3711   3711     }
  3712   3712     pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc);
  3713   3713     if( db->mallocFailed ){
  3714   3714       sqlite3SrcListDelete(db, pList);
................................................................................
  3988   3988           "file for storing temporary tables");
  3989   3989         pParse->rc = rc;
  3990   3990         return 1;
  3991   3991       }
  3992   3992       db->aDb[1].pBt = pBt;
  3993   3993       assert( db->aDb[1].pSchema );
  3994   3994       if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){
  3995         -      db->mallocFailed = 1;
         3995  +      sqlite3OomFault(db);
  3996   3996         return 1;
  3997   3997       }
  3998   3998     }
  3999   3999     return 0;
  4000   4000   }
  4001   4001   
  4002   4002   /*
................................................................................
  4363   4363   
  4364   4364     if( pWith ){
  4365   4365       int nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte);
  4366   4366       pNew = sqlite3DbRealloc(db, pWith, nByte);
  4367   4367     }else{
  4368   4368       pNew = sqlite3DbMallocZero(db, sizeof(*pWith));
  4369   4369     }
  4370         -  assert( zName!=0 || pNew==0 );
  4371         -  assert( db->mallocFailed==0 || pNew==0 );
         4370  +  assert( (pNew!=0 && zName!=0) || db->mallocFailed );
  4372   4371   
  4373         -  if( pNew==0 ){
         4372  +  if( db->mallocFailed ){
  4374   4373       sqlite3ExprListDelete(db, pArglist);
  4375   4374       sqlite3SelectDelete(db, pQuery);
  4376   4375       sqlite3DbFree(db, zName);
  4377   4376       pNew = pWith;
  4378   4377     }else{
  4379   4378       pNew->a[pNew->nCte].pSelect = pQuery;
  4380   4379       pNew->a[pNew->nCte].pCols = pArglist;

Changes to src/callback.c.

   173    173   
   174    174         /* If a malloc() failure occurred in sqlite3HashInsert(), it will 
   175    175         ** return the pColl pointer to be deleted (because it wasn't added
   176    176         ** to the hash table).
   177    177         */
   178    178         assert( pDel==0 || pDel==pColl );
   179    179         if( pDel!=0 ){
   180         -        db->mallocFailed = 1;
          180  +        sqlite3OomFault(db);
   181    181           sqlite3DbFree(db, pDel);
   182    182           pColl = 0;
   183    183         }
   184    184       }
   185    185     }
   186    186     return pColl;
   187    187   }
................................................................................
   461    461     Schema * p;
   462    462     if( pBt ){
   463    463       p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear);
   464    464     }else{
   465    465       p = (Schema *)sqlite3DbMallocZero(0, sizeof(Schema));
   466    466     }
   467    467     if( !p ){
   468         -    db->mallocFailed = 1;
          468  +    sqlite3OomFault(db);
   469    469     }else if ( 0==p->file_format ){
   470    470       sqlite3HashInit(&p->tblHash);
   471    471       sqlite3HashInit(&p->idxHash);
   472    472       sqlite3HashInit(&p->trigHash);
   473    473       sqlite3HashInit(&p->fkeyHash);
   474    474       p->enc = SQLITE_UTF8;
   475    475     }
   476    476     return p;
   477    477   }

Changes to src/date.c.

   963    963     testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH] );
   964    964     if( n<sizeof(zBuf) ){
   965    965       z = zBuf;
   966    966     }else if( n>(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ){
   967    967       sqlite3_result_error_toobig(context);
   968    968       return;
   969    969     }else{
   970         -    z = sqlite3DbMallocRaw(db, (int)n);
          970  +    z = sqlite3DbMallocRawNN(db, (int)n);
   971    971       if( z==0 ){
   972    972         sqlite3_result_error_nomem(context);
   973    973         return;
   974    974       }
   975    975     }
   976    976     computeJD(&x);
   977    977     computeYMD_HMS(&x);

Changes to src/delete.c.

   435    435       }
   436    436     
   437    437       if( eOnePass!=ONEPASS_OFF ){
   438    438         /* For ONEPASS, no need to store the rowid/primary-key. There is only
   439    439         ** one, so just keep it in its register(s) and fall through to the
   440    440         ** delete code.  */
   441    441         nKey = nPk; /* OP_Found will use an unpacked key */
   442         -      aToOpen = sqlite3DbMallocRaw(db, nIdx+2);
          442  +      aToOpen = sqlite3DbMallocRawNN(db, nIdx+2);
   443    443         if( aToOpen==0 ){
   444    444           sqlite3WhereEnd(pWInfo);
   445    445           goto delete_from_cleanup;
   446    446         }
   447    447         memset(aToOpen, 1, nIdx+1);
   448    448         aToOpen[nIdx+1] = 0;
   449    449         if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0;

Changes to src/expr.c.

   449    449     const Token *pToken,    /* Token argument.  Might be NULL */
   450    450     int dequote             /* True to dequote */
   451    451   ){
   452    452     Expr *pNew;
   453    453     int nExtra = 0;
   454    454     int iValue = 0;
   455    455   
          456  +  assert( db!=0 );
   456    457     if( pToken ){
   457    458       if( op!=TK_INTEGER || pToken->z==0
   458    459             || sqlite3GetInt32(pToken->z, &iValue)==0 ){
   459    460         nExtra = pToken->n+1;
   460    461         assert( iValue>=0 );
   461    462       }
   462    463     }
   463         -  pNew = sqlite3DbMallocRaw(db, sizeof(Expr)+nExtra);
          464  +  pNew = sqlite3DbMallocRawNN(db, sizeof(Expr)+nExtra);
   464    465     if( pNew ){
   465    466       memset(pNew, 0, sizeof(Expr));
   466    467       pNew->op = (u8)op;
   467    468       pNew->iAgg = -1;
   468    469       if( pToken ){
   469    470         if( nExtra==0 ){
   470    471           pNew->flags |= EP_IntValue;
................................................................................
   695    696         }
   696    697         if( x==0 ) x = pExpr->iColumn = (ynVar)(++pParse->nVar);
   697    698       }
   698    699       if( x>0 ){
   699    700         if( x>pParse->nzVar ){
   700    701           char **a;
   701    702           a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0]));
   702         -        if( a==0 ) return;  /* Error reported through db->mallocFailed */
          703  +        if( a==0 ){
          704  +          assert( db->mallocFailed ); /* Error reported through mallocFailed */
          705  +          return;
          706  +        }
   703    707           pParse->azVar = a;
   704    708           memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0]));
   705    709           pParse->nzVar = x;
   706    710         }
   707    711         if( z[0]!='?' || pParse->azVar[x-1]==0 ){
   708    712           sqlite3DbFree(db, pParse->azVar[x-1]);
   709    713           pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n);
................................................................................
   850    854   ** (if applicable), and the copies of the p->pLeft and p->pRight expressions,
   851    855   ** if any. Before returning, *pzBuffer is set to the first byte past the
   852    856   ** portion of the buffer copied into by this function.
   853    857   */
   854    858   static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
   855    859     Expr *pNew = 0;                      /* Value to return */
   856    860     assert( flags==0 || flags==EXPRDUP_REDUCE );
          861  +  assert( db!=0 );
   857    862     if( p ){
   858    863       const int isReduced = (flags&EXPRDUP_REDUCE);
   859    864       u8 *zAlloc;
   860    865       u32 staticFlag = 0;
   861    866   
   862    867       assert( pzBuffer==0 || isReduced );
   863    868   
   864    869       /* Figure out where to write the new Expr structure. */
   865    870       if( pzBuffer ){
   866    871         zAlloc = *pzBuffer;
   867    872         staticFlag = EP_Static;
   868    873       }else{
   869         -      zAlloc = sqlite3DbMallocRaw(db, dupedExprSize(p, flags));
          874  +      zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, flags));
   870    875       }
   871    876       pNew = (Expr *)zAlloc;
   872    877   
   873    878       if( pNew ){
   874    879         /* Set nNewSize to the size allocated for the structure pointed to
   875    880         ** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or
   876    881         ** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed
................................................................................
   985    990     assert( flags==0 || flags==EXPRDUP_REDUCE );
   986    991     return exprDup(db, p, flags, 0);
   987    992   }
   988    993   ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
   989    994     ExprList *pNew;
   990    995     struct ExprList_item *pItem, *pOldItem;
   991    996     int i;
          997  +  assert( db!=0 );
   992    998     if( p==0 ) return 0;
   993         -  pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) );
          999  +  pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) );
   994   1000     if( pNew==0 ) return 0;
   995   1001     pNew->nExpr = i = p->nExpr;
   996   1002     if( (flags & EXPRDUP_REDUCE)==0 ) for(i=1; i<p->nExpr; i+=i){}
   997         -  pNew->a = pItem = sqlite3DbMallocRaw(db,  i*sizeof(p->a[0]) );
         1003  +  pNew->a = pItem = sqlite3DbMallocRawNN(db,  i*sizeof(p->a[0]) );
   998   1004     if( pItem==0 ){
   999   1005       sqlite3DbFree(db, pNew);
  1000   1006       return 0;
  1001   1007     } 
  1002   1008     pOldItem = p->a;
  1003   1009     for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
  1004   1010       Expr *pOldExpr = pOldItem->pExpr;
................................................................................
  1021   1027   */
  1022   1028   #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \
  1023   1029    || !defined(SQLITE_OMIT_SUBQUERY)
  1024   1030   SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
  1025   1031     SrcList *pNew;
  1026   1032     int i;
  1027   1033     int nByte;
         1034  +  assert( db!=0 );
  1028   1035     if( p==0 ) return 0;
  1029   1036     nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0);
  1030         -  pNew = sqlite3DbMallocRaw(db, nByte );
         1037  +  pNew = sqlite3DbMallocRawNN(db, nByte );
  1031   1038     if( pNew==0 ) return 0;
  1032   1039     pNew->nSrc = pNew->nAlloc = p->nSrc;
  1033   1040     for(i=0; i<p->nSrc; i++){
  1034   1041       struct SrcList_item *pNewItem = &pNew->a[i];
  1035   1042       struct SrcList_item *pOldItem = &p->a[i];
  1036   1043       Table *pTab;
  1037   1044       pNewItem->pSchema = pOldItem->pSchema;
................................................................................
  1060   1067       pNewItem->colUsed = pOldItem->colUsed;
  1061   1068     }
  1062   1069     return pNew;
  1063   1070   }
  1064   1071   IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){
  1065   1072     IdList *pNew;
  1066   1073     int i;
         1074  +  assert( db!=0 );
  1067   1075     if( p==0 ) return 0;
  1068         -  pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) );
         1076  +  pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) );
  1069   1077     if( pNew==0 ) return 0;
  1070   1078     pNew->nId = p->nId;
  1071         -  pNew->a = sqlite3DbMallocRaw(db, p->nId*sizeof(p->a[0]) );
         1079  +  pNew->a = sqlite3DbMallocRawNN(db, p->nId*sizeof(p->a[0]) );
  1072   1080     if( pNew->a==0 ){
  1073   1081       sqlite3DbFree(db, pNew);
  1074   1082       return 0;
  1075   1083     }
  1076   1084     /* Note that because the size of the allocation for p->a[] is not
  1077   1085     ** necessarily a power of two, sqlite3IdListAppend() may not be called
  1078   1086     ** on the duplicate created by this function. */
................................................................................
  1082   1090       pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
  1083   1091       pNewItem->idx = pOldItem->idx;
  1084   1092     }
  1085   1093     return pNew;
  1086   1094   }
  1087   1095   Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
  1088   1096     Select *pNew, *pPrior;
         1097  +  assert( db!=0 );
  1089   1098     if( p==0 ) return 0;
  1090         -  pNew = sqlite3DbMallocRaw(db, sizeof(*p) );
         1099  +  pNew = sqlite3DbMallocRawNN(db, sizeof(*p) );
  1091   1100     if( pNew==0 ) return 0;
  1092   1101     pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags);
  1093   1102     pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags);
  1094   1103     pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags);
  1095   1104     pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags);
  1096   1105     pNew->pHaving = sqlite3ExprDup(db, p->pHaving, flags);
  1097   1106     pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, flags);
................................................................................
  1129   1138   */
  1130   1139   ExprList *sqlite3ExprListAppend(
  1131   1140     Parse *pParse,          /* Parsing context */
  1132   1141     ExprList *pList,        /* List to which to append. Might be NULL */
  1133   1142     Expr *pExpr             /* Expression to be appended. Might be NULL */
  1134   1143   ){
  1135   1144     sqlite3 *db = pParse->db;
         1145  +  assert( db!=0 );
  1136   1146     if( pList==0 ){
  1137         -    pList = sqlite3DbMallocRaw(db, sizeof(ExprList) );
         1147  +    pList = sqlite3DbMallocRawNN(db, sizeof(ExprList) );
  1138   1148       if( pList==0 ){
  1139   1149         goto no_mem;
  1140   1150       }
  1141   1151       pList->nExpr = 0;
  1142         -    pList->a = sqlite3DbMallocRaw(db, sizeof(pList->a[0]));
         1152  +    pList->a = sqlite3DbMallocRawNN(db, sizeof(pList->a[0]));
  1143   1153       if( pList->a==0 ) goto no_mem;
  1144   1154     }else if( (pList->nExpr & (pList->nExpr-1))==0 ){
  1145   1155       struct ExprList_item *a;
  1146   1156       assert( pList->nExpr>0 );
  1147   1157       a = sqlite3DbRealloc(db, pList->a, pList->nExpr*2*sizeof(pList->a[0]));
  1148   1158       if( a==0 ){
  1149   1159         goto no_mem;

Changes to src/fkey.c.

   215    215       */
   216    216       if( pParent->iPKey>=0 ){
   217    217         if( !zKey ) return 0;
   218    218         if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zName, zKey) ) return 0;
   219    219       }
   220    220     }else if( paiCol ){
   221    221       assert( nCol>1 );
   222         -    aiCol = (int *)sqlite3DbMallocRaw(pParse->db, nCol*sizeof(int));
          222  +    aiCol = (int *)sqlite3DbMallocRawNN(pParse->db, nCol*sizeof(int));
   223    223       if( !aiCol ) return 1;
   224    224       *paiCol = aiCol;
   225    225     }
   226    226   
   227    227     for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){
   228    228       if( pIdx->nKeyCol==nCol && IsUniqueIndex(pIdx) ){ 
   229    229         /* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number
................................................................................
  1161   1161     Trigger *pTrigger;              /* Trigger definition to return */
  1162   1162     int iAction = (pChanges!=0);    /* 1 for UPDATE, 0 for DELETE */
  1163   1163   
  1164   1164     action = pFKey->aAction[iAction];
  1165   1165     pTrigger = pFKey->apTrigger[iAction];
  1166   1166   
  1167   1167     if( action!=OE_None && !pTrigger ){
  1168         -    u8 enableLookaside;           /* Copy of db->lookaside.bEnabled */
  1169   1168       char const *zFrom;            /* Name of child table */
  1170   1169       int nFrom;                    /* Length in bytes of zFrom */
  1171   1170       Index *pIdx = 0;              /* Parent key index for this FK */
  1172   1171       int *aiCol = 0;               /* child table cols -> parent key cols */
  1173   1172       TriggerStep *pStep = 0;        /* First (only) step of trigger program */
  1174   1173       Expr *pWhere = 0;             /* WHERE clause of trigger step */
  1175   1174       ExprList *pList = 0;          /* Changes list if ON UPDATE CASCADE */
................................................................................
  1270   1269             pWhere,
  1271   1270             0, 0, 0, 0, 0, 0
  1272   1271         );
  1273   1272         pWhere = 0;
  1274   1273       }
  1275   1274   
  1276   1275       /* Disable lookaside memory allocation */
  1277         -    enableLookaside = db->lookaside.bEnabled;
  1278         -    db->lookaside.bEnabled = 0;
         1276  +    db->lookaside.bDisable++;
  1279   1277   
  1280   1278       pTrigger = (Trigger *)sqlite3DbMallocZero(db, 
  1281   1279           sizeof(Trigger) +         /* struct Trigger */
  1282   1280           sizeof(TriggerStep) +     /* Single step in trigger program */
  1283   1281           nFrom + 1                 /* Space for pStep->zTarget */
  1284   1282       );
  1285   1283       if( pTrigger ){
................................................................................
  1293   1291         if( pWhen ){
  1294   1292           pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0, 0);
  1295   1293           pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE);
  1296   1294         }
  1297   1295       }
  1298   1296   
  1299   1297       /* Re-enable the lookaside buffer, if it was disabled earlier. */
  1300         -    db->lookaside.bEnabled = enableLookaside;
         1298  +    db->lookaside.bDisable--;
  1301   1299   
  1302   1300       sqlite3ExprDelete(db, pWhere);
  1303   1301       sqlite3ExprDelete(db, pWhen);
  1304   1302       sqlite3ExprListDelete(db, pList);
  1305   1303       sqlite3SelectDelete(db, pSelect);
  1306   1304       if( db->mallocFailed==1 ){
  1307   1305         fkTriggerDelete(db, pTrigger);

Changes to src/func.c.

  1611   1611   ** of the built-in functions above are part of the global function set.
  1612   1612   ** This routine only deals with those that are not global.
  1613   1613   */
  1614   1614   void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
  1615   1615     int rc = sqlite3_overload_function(db, "MATCH", 2);
  1616   1616     assert( rc==SQLITE_NOMEM || rc==SQLITE_OK );
  1617   1617     if( rc==SQLITE_NOMEM ){
  1618         -    db->mallocFailed = 1;
         1618  +    sqlite3OomFault(db);
  1619   1619     }
  1620   1620   }
  1621   1621   
  1622   1622   /*
  1623   1623   ** Set the LIKEOPT flag on the 2-argument function with the given name.
  1624   1624   */
  1625   1625   static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){

Changes to src/insert.c.

    79     79       ** sqliteDeleteIndex() when the Index structure itself is cleaned
    80     80       ** up.
    81     81       */
    82     82       int n;
    83     83       Table *pTab = pIdx->pTable;
    84     84       pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1);
    85     85       if( !pIdx->zColAff ){
    86         -      db->mallocFailed = 1;
           86  +      sqlite3OomFault(db);
    87     87         return 0;
    88     88       }
    89     89       for(n=0; n<pIdx->nColumn; n++){
    90     90         i16 x = pIdx->aiColumn[n];
    91     91         if( x>=0 ){
    92     92           pIdx->zColAff[n] = pTab->aCol[x].affinity;
    93     93         }else if( x==XN_ROWID ){
................................................................................
   130    130   void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
   131    131     int i;
   132    132     char *zColAff = pTab->zColAff;
   133    133     if( zColAff==0 ){
   134    134       sqlite3 *db = sqlite3VdbeDb(v);
   135    135       zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol+1);
   136    136       if( !zColAff ){
   137         -      db->mallocFailed = 1;
          137  +      sqlite3OomFault(db);
   138    138         return;
   139    139       }
   140    140   
   141    141       for(i=0; i<pTab->nCol; i++){
   142    142         zColAff[i] = pTab->aCol[i].affinity;
   143    143       }
   144    144       do{
................................................................................
   226    226     if( pTab->tabFlags & TF_Autoincrement ){
   227    227       Parse *pToplevel = sqlite3ParseToplevel(pParse);
   228    228       AutoincInfo *pInfo;
   229    229   
   230    230       pInfo = pToplevel->pAinc;
   231    231       while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; }
   232    232       if( pInfo==0 ){
   233         -      pInfo = sqlite3DbMallocRaw(pParse->db, sizeof(*pInfo));
          233  +      pInfo = sqlite3DbMallocRawNN(pParse->db, sizeof(*pInfo));
   234    234         if( pInfo==0 ) return 0;
   235    235         pInfo->pNext = pToplevel->pAinc;
   236    236         pToplevel->pAinc = pInfo;
   237    237         pInfo->pTab = pTab;
   238    238         pInfo->iDb = iDb;
   239    239         pToplevel->nMem++;                  /* Register to hold name of table */
   240    240         pInfo->regCtr = ++pToplevel->nMem;  /* Max rowid register */
................................................................................
   250    250   ** register used by the autoincrement tracker.  
   251    251   */
   252    252   void sqlite3AutoincrementBegin(Parse *pParse){
   253    253     AutoincInfo *p;            /* Information about an AUTOINCREMENT */
   254    254     sqlite3 *db = pParse->db;  /* The database connection */
   255    255     Db *pDb;                   /* Database only autoinc table */
   256    256     int memId;                 /* Register holding max rowid */
   257         -  int addr;                  /* A VDBE address */
   258    257     Vdbe *v = pParse->pVdbe;   /* VDBE under construction */
   259    258   
   260    259     /* This routine is never called during trigger-generation.  It is
   261    260     ** only called from the top-level */
   262    261     assert( pParse->pTriggerTab==0 );
   263    262     assert( sqlite3IsToplevel(pParse) );
   264    263   
   265    264     assert( v );   /* We failed long ago if this is not so */
   266    265     for(p = pParse->pAinc; p; p = p->pNext){
          266  +    static const int iLn = VDBE_OFFSET_LINENO(2);
          267  +    static const VdbeOpList autoInc[] = {
          268  +      /* 0  */ {OP_Null,    0,  0, 0},
          269  +      /* 1  */ {OP_Rewind,  0,  9, 0},
          270  +      /* 2  */ {OP_Column,  0,  0, 0},
          271  +      /* 3  */ {OP_Ne,      0,  7, 0},
          272  +      /* 4  */ {OP_Rowid,   0,  0, 0},
          273  +      /* 5  */ {OP_Column,  0,  1, 0},
          274  +      /* 6  */ {OP_Goto,    0,  9, 0},
          275  +      /* 7  */ {OP_Next,    0,  2, 0},
          276  +      /* 8  */ {OP_Integer, 0,  0, 0},
          277  +      /* 9  */ {OP_Close,   0,  0, 0} 
          278  +    };
          279  +    VdbeOp *aOp;
   267    280       pDb = &db->aDb[p->iDb];
   268    281       memId = p->regCtr;
   269    282       assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) );
   270    283       sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead);
   271         -    sqlite3VdbeAddOp3(v, OP_Null, 0, memId, memId+1);
   272         -    addr = sqlite3VdbeCurrentAddr(v);
   273    284       sqlite3VdbeLoadString(v, memId-1, p->pTab->zName);
   274         -    sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9); VdbeCoverage(v);
   275         -    sqlite3VdbeAddOp3(v, OP_Column, 0, 0, memId);
   276         -    sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId); VdbeCoverage(v);
   277         -    sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
   278         -    sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1);
   279         -    sqlite3VdbeAddOp3(v, OP_Column, 0, 1, memId);
   280         -    sqlite3VdbeGoto(v, addr+9);
   281         -    sqlite3VdbeAddOp2(v, OP_Next, 0, addr+2); VdbeCoverage(v);
   282         -    sqlite3VdbeAddOp2(v, OP_Integer, 0, memId);
   283         -    sqlite3VdbeAddOp0(v, OP_Close);
          285  +    aOp = sqlite3VdbeAddOpList(v, ArraySize(autoInc), autoInc, iLn);
          286  +    if( aOp==0 ) break;
          287  +    aOp[0].p2 = memId;
          288  +    aOp[0].p3 = memId+1;
          289  +    aOp[2].p3 = memId;
          290  +    aOp[3].p1 = memId-1;
          291  +    aOp[3].p3 = memId;
          292  +    aOp[3].p5 = SQLITE_JUMPIFNULL;
          293  +    aOp[4].p2 = memId+1;
          294  +    aOp[5].p3 = memId;
          295  +    aOp[8].p2 = memId;
   284    296     }
   285    297   }
   286    298   
   287    299   /*
   288    300   ** Update the maximum rowid for an autoincrement calculation.
   289    301   **
   290         -** This routine should be called when the top of the stack holds a
          302  +** This routine should be called when the regRowid register holds a
   291    303   ** new rowid that is about to be inserted.  If that new rowid is
   292    304   ** larger than the maximum rowid in the memId memory cell, then the
   293         -** memory cell is updated.  The stack is unchanged.
          305  +** memory cell is updated.
   294    306   */
   295    307   static void autoIncStep(Parse *pParse, int memId, int regRowid){
   296    308     if( memId>0 ){
   297    309       sqlite3VdbeAddOp2(pParse->pVdbe, OP_MemMax, memId, regRowid);
   298    310     }
   299    311   }
   300    312   
................................................................................
   301    313   /*
   302    314   ** This routine generates the code needed to write autoincrement
   303    315   ** maximum rowid values back into the sqlite_sequence register.
   304    316   ** Every statement that might do an INSERT into an autoincrement
   305    317   ** table (either directly or through triggers) needs to call this
   306    318   ** routine just before the "exit" code.
   307    319   */
   308         -void sqlite3AutoincrementEnd(Parse *pParse){
          320  +static SQLITE_NOINLINE void autoIncrementEnd(Parse *pParse){
   309    321     AutoincInfo *p;
   310    322     Vdbe *v = pParse->pVdbe;
   311    323     sqlite3 *db = pParse->db;
   312    324   
   313    325     assert( v );
   314    326     for(p = pParse->pAinc; p; p = p->pNext){
          327  +    static const int iLn = VDBE_OFFSET_LINENO(2);
          328  +    static const VdbeOpList autoIncEnd[] = {
          329  +      /* 0 */ {OP_NotNull,     0, 2, 0},
          330  +      /* 1 */ {OP_NewRowid,    0, 0, 0},
          331  +      /* 2 */ {OP_MakeRecord,  0, 2, 0},
          332  +      /* 3 */ {OP_Insert,      0, 0, 0},
          333  +      /* 4 */ {OP_Close,       0, 0, 0}
          334  +    };
          335  +    VdbeOp *aOp;
   315    336       Db *pDb = &db->aDb[p->iDb];
   316         -    int addr1;
   317    337       int iRec;
   318    338       int memId = p->regCtr;
   319    339   
   320    340       iRec = sqlite3GetTempReg(pParse);
   321    341       assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) );
   322    342       sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
   323         -    addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); VdbeCoverage(v);
   324         -    sqlite3VdbeAddOp2(v, OP_NewRowid, 0, memId+1);
   325         -    sqlite3VdbeJumpHere(v, addr1);
   326         -    sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec);
   327         -    sqlite3VdbeAddOp3(v, OP_Insert, 0, iRec, memId+1);
   328         -    sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
   329         -    sqlite3VdbeAddOp0(v, OP_Close);
          343  +    aOp = sqlite3VdbeAddOpList(v, ArraySize(autoIncEnd), autoIncEnd, iLn);
          344  +    if( aOp==0 ) break;
          345  +    aOp[0].p1 = memId+1;
          346  +    aOp[1].p2 = memId+1;
          347  +    aOp[2].p1 = memId-1;
          348  +    aOp[2].p3 = iRec;
          349  +    aOp[3].p2 = iRec;
          350  +    aOp[3].p3 = memId+1;
          351  +    aOp[3].p5 = OPFLAG_APPEND;
   330    352       sqlite3ReleaseTempReg(pParse, iRec);
   331    353     }
   332    354   }
          355  +void sqlite3AutoincrementEnd(Parse *pParse){
          356  +  if( pParse->pAinc ) autoIncrementEnd(pParse);
          357  +}
   333    358   #else
   334    359   /*
   335    360   ** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines
   336    361   ** above are all no-ops
   337    362   */
   338    363   # define autoIncBegin(A,B,C) (0)
   339    364   # define autoIncStep(A,B,C)
................................................................................
   758    783     }
   759    784   
   760    785     /* If this is not a view, open the table and and all indices */
   761    786     if( !isView ){
   762    787       int nIdx;
   763    788       nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0,
   764    789                                         &iDataCur, &iIdxCur);
   765         -    aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1));
          790  +    aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+1));
   766    791       if( aRegIdx==0 ){
   767    792         goto insert_cleanup;
   768    793       }
   769    794       for(i=0; i<nIdx; i++){
   770    795         aRegIdx[i] = ++pParse->nMem;
   771    796       }
   772    797     }

Changes to src/legacy.c.

    91     91             callbackIsInit = 1;
    92     92           }
    93     93           if( rc==SQLITE_ROW ){
    94     94             azVals = &azCols[nCol];
    95     95             for(i=0; i<nCol; i++){
    96     96               azVals[i] = (char *)sqlite3_column_text(pStmt, i);
    97     97               if( !azVals[i] && sqlite3_column_type(pStmt, i)!=SQLITE_NULL ){
    98         -              db->mallocFailed = 1;
           98  +              sqlite3OomFault(db);
    99     99                 goto exec_out;
   100    100               }
   101    101             }
   102    102           }
   103    103           if( xCallback(pArg, nCol, azVals, azCols) ){
   104    104             /* EVIDENCE-OF: R-38229-40159 If the callback function to
   105    105             ** sqlite3_exec() returns non-zero, then sqlite3_exec() will

Changes to src/main.c.

   697    697       p = (LookasideSlot*)pStart;
   698    698       for(i=cnt-1; i>=0; i--){
   699    699         p->pNext = db->lookaside.pFree;
   700    700         db->lookaside.pFree = p;
   701    701         p = (LookasideSlot*)&((u8*)p)[sz];
   702    702       }
   703    703       db->lookaside.pEnd = p;
   704         -    db->lookaside.bEnabled = 1;
          704  +    db->lookaside.bDisable = 0;
   705    705       db->lookaside.bMalloced = pBuf==0 ?1:0;
   706    706     }else{
   707    707       db->lookaside.pStart = db;
   708    708       db->lookaside.pEnd = db;
   709         -    db->lookaside.bEnabled = 0;
          709  +    db->lookaside.bDisable = 1;
   710    710       db->lookaside.bMalloced = 0;
   711    711     }
   712    712   #endif /* SQLITE_OMIT_LOOKASIDE */
   713    713     return SQLITE_OK;
   714    714   }
   715    715   
   716    716   /*
................................................................................
  2211   2211         z = sqlite3_value_text16(db->pErr);
  2212   2212       }
  2213   2213       /* A malloc() may have failed within the call to sqlite3_value_text16()
  2214   2214       ** above. If this is the case, then the db->mallocFailed flag needs to
  2215   2215       ** be cleared before returning. Do this directly, instead of via
  2216   2216       ** sqlite3ApiExit(), to avoid setting the database handle error message.
  2217   2217       */
  2218         -    db->mallocFailed = 0;
         2218  +    sqlite3OomClear(db);
  2219   2219     }
  2220   2220     sqlite3_mutex_leave(db->mutex);
  2221   2221     return z;
  2222   2222   }
  2223   2223   #endif /* SQLITE_OMIT_UTF16 */
  2224   2224   
  2225   2225   /*
................................................................................
  2938   2938     db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, sqlite3StrBINARY, 0);
  2939   2939     assert( db->pDfltColl!=0 );
  2940   2940   
  2941   2941     /* Parse the filename/URI argument. */
  2942   2942     db->openFlags = flags;
  2943   2943     rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
  2944   2944     if( rc!=SQLITE_OK ){
  2945         -    if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
         2945  +    if( rc==SQLITE_NOMEM ) sqlite3OomFault(db);
  2946   2946       sqlite3ErrorWithMsg(db, rc, zErrMsg ? "%s" : 0, zErrMsg);
  2947   2947       sqlite3_free(zErrMsg);
  2948   2948       goto opendb_out;
  2949   2949     }
  2950   2950   
  2951   2951     /* Open the backend database driver */
  2952   2952     rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0,

Changes to src/malloc.c.

   571    571   }
   572    572   
   573    573   /*
   574    574   ** Allocate and zero memory.  If the allocation fails, make
   575    575   ** the mallocFailed flag in the connection pointer.
   576    576   */
   577    577   void *sqlite3DbMallocZero(sqlite3 *db, u64 n){
   578         -  void *p = sqlite3DbMallocRaw(db, n);
   579         -  if( p ){
   580         -    memset(p, 0, (size_t)n);
   581         -  }
          578  +  void *p;
          579  +  testcase( db==0 );
          580  +  p = sqlite3DbMallocRaw(db, n);
          581  +  if( p ) memset(p, 0, (size_t)n);
          582  +  return p;
          583  +}
          584  +
          585  +
          586  +/* Finish the work of sqlite3DbMallocRawNN for the unusual and
          587  +** slower case when the allocation cannot be fulfilled using lookaside.
          588  +*/
          589  +static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n){
          590  +  void *p;
          591  +  assert( db!=0 );
          592  +  p = sqlite3Malloc(n);
          593  +  if( !p ) sqlite3OomFault(db);
          594  +  sqlite3MemdebugSetType(p, 
          595  +         (db->lookaside.bDisable==0) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP);
   582    596     return p;
   583    597   }
   584    598   
   585    599   /*
   586    600   ** Allocate memory, either lookaside (if possible) or heap.  
   587    601   ** If the allocation fails, set the mallocFailed flag in
   588    602   ** the connection pointer.
................................................................................
   596    610   **
   597    611   **         int *a = (int*)sqlite3DbMallocRaw(db, 100);
   598    612   **         int *b = (int*)sqlite3DbMallocRaw(db, 200);
   599    613   **         if( b ) a[10] = 9;
   600    614   **
   601    615   ** In other words, if a subsequent malloc (ex: "b") worked, it is assumed
   602    616   ** that all prior mallocs (ex: "a") worked too.
          617  +**
          618  +** The sqlite3MallocRawNN() variant guarantees that the "db" parameter is
          619  +** not a NULL pointer.
   603    620   */
   604         -static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n);
   605    621   void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){
   606         -  assert( db==0 || sqlite3_mutex_held(db->mutex) );
   607         -  assert( db==0 || db->pnBytesFreed==0 );
          622  +  void *p;
          623  +  if( db ) return sqlite3DbMallocRawNN(db, n);
          624  +  p = sqlite3Malloc(n);
          625  +  sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
          626  +  return p;
          627  +}
          628  +void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){
          629  +  assert( db!=0 );
          630  +  assert( sqlite3_mutex_held(db->mutex) );
          631  +  assert( db->pnBytesFreed==0 );
   608    632   #ifndef SQLITE_OMIT_LOOKASIDE
   609         -  if( db ){
   610         -    LookasideSlot *pBuf;
   611         -    if( db->mallocFailed ){
   612         -      return 0;
   613         -    }
   614         -    if( db->lookaside.bEnabled ){
   615         -      if( n>db->lookaside.sz ){
   616         -        db->lookaside.anStat[1]++;
   617         -      }else if( (pBuf = db->lookaside.pFree)==0 ){
   618         -        db->lookaside.anStat[2]++;
   619         -      }else{
   620         -        db->lookaside.pFree = pBuf->pNext;
   621         -        db->lookaside.nOut++;
   622         -        db->lookaside.anStat[0]++;
   623         -        if( db->lookaside.nOut>db->lookaside.mxOut ){
   624         -          db->lookaside.mxOut = db->lookaside.nOut;
   625         -        }
   626         -        return (void*)pBuf;
          633  +  LookasideSlot *pBuf;
          634  +  if( db->lookaside.bDisable==0 ){
          635  +    assert( db->mallocFailed==0 );
          636  +    if( n>db->lookaside.sz ){
          637  +      db->lookaside.anStat[1]++;
          638  +    }else if( (pBuf = db->lookaside.pFree)==0 ){
          639  +      db->lookaside.anStat[2]++;
          640  +    }else{
          641  +      db->lookaside.pFree = pBuf->pNext;
          642  +      db->lookaside.nOut++;
          643  +      db->lookaside.anStat[0]++;
          644  +      if( db->lookaside.nOut>db->lookaside.mxOut ){
          645  +        db->lookaside.mxOut = db->lookaside.nOut;
   627    646         }
          647  +      return (void*)pBuf;
   628    648       }
          649  +  }else if( db->mallocFailed ){
          650  +    return 0;
   629    651     }
   630    652   #else
   631         -  if( db && db->mallocFailed ){
          653  +  if( db->mallocFailed ){
   632    654       return 0;
   633    655     }
   634    656   #endif
   635    657     return dbMallocRawFinish(db, n);
   636    658   }
   637         -static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n){
   638         -  void *p = sqlite3Malloc(n);
   639         -  if( !p && db ){
   640         -    db->mallocFailed = 1;
   641         -  }
   642         -  sqlite3MemdebugSetType(p, 
   643         -         (db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP);
   644         -  return p;
   645         -}
          659  +
          660  +/* Forward declaration */
          661  +static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n);
   646    662   
   647    663   /*
   648    664   ** Resize the block of memory pointed to by p to n bytes. If the
   649    665   ** resize fails, set the mallocFailed flag in the connection object.
   650    666   */
   651    667   void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){
          668  +  assert( db!=0 );
          669  +  if( p==0 ) return sqlite3DbMallocRawNN(db, n);
          670  +  assert( sqlite3_mutex_held(db->mutex) );
          671  +  if( isLookaside(db,p) && n<=db->lookaside.sz ) return p;
          672  +  return dbReallocFinish(db, p, n);
          673  +}
          674  +static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){
   652    675     void *pNew = 0;
   653    676     assert( db!=0 );
   654         -  assert( sqlite3_mutex_held(db->mutex) );
          677  +  assert( p!=0 );
   655    678     if( db->mallocFailed==0 ){
   656         -    if( p==0 ){
   657         -      return sqlite3DbMallocRaw(db, n);
   658         -    }
   659    679       if( isLookaside(db, p) ){
   660         -      if( n<=db->lookaside.sz ){
   661         -        return p;
   662         -      }
   663         -      pNew = sqlite3DbMallocRaw(db, n);
          680  +      pNew = sqlite3DbMallocRawNN(db, n);
   664    681         if( pNew ){
   665    682           memcpy(pNew, p, db->lookaside.sz);
   666    683           sqlite3DbFree(db, p);
   667    684         }
   668    685       }else{
   669    686         assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
   670    687         assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
   671    688         sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
   672    689         pNew = sqlite3_realloc64(p, n);
   673    690         if( !pNew ){
   674         -        db->mallocFailed = 1;
          691  +        sqlite3OomFault(db);
   675    692         }
   676    693         sqlite3MemdebugSetType(pNew,
   677         -            (db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
          694  +            (db->lookaside.bDisable==0 ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
   678    695       }
   679    696     }
   680    697     return pNew;
   681    698   }
   682    699   
   683    700   /*
   684    701   ** Attempt to reallocate p.  If the reallocation fails, then free p
................................................................................
   712    729     if( zNew ){
   713    730       memcpy(zNew, z, n);
   714    731     }
   715    732     return zNew;
   716    733   }
   717    734   char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){
   718    735     char *zNew;
          736  +  assert( db!=0 );
   719    737     if( z==0 ){
   720    738       return 0;
   721    739     }
   722    740     assert( (n&0x7fffffff)==n );
   723         -  zNew = sqlite3DbMallocRaw(db, n+1);
          741  +  zNew = sqlite3DbMallocRawNN(db, n+1);
   724    742     if( zNew ){
   725    743       memcpy(zNew, z, (size_t)n);
   726    744       zNew[n] = 0;
   727    745     }
   728    746     return zNew;
   729    747   }
   730    748   
................................................................................
   731    749   /*
   732    750   ** Free any prior content in *pz and replace it with a copy of zNew.
   733    751   */
   734    752   void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){
   735    753     sqlite3DbFree(db, *pz);
   736    754     *pz = sqlite3DbStrDup(db, zNew);
   737    755   }
          756  +
          757  +/*
          758  +** Call this routine to record the fact that an OOM (out-of-memory) error
          759  +** has happened.  This routine will set db->mallocFailed, and also
          760  +** temporarily disable the lookaside memory allocator and interrupt
          761  +** any running VDBEs.
          762  +*/
          763  +void sqlite3OomFault(sqlite3 *db){
          764  +  if( db->mallocFailed==0 && db->bBenignMalloc==0 ){
          765  +    db->mallocFailed = 1;
          766  +    if( db->nVdbeExec>0 ){
          767  +      db->u1.isInterrupted = 1;
          768  +    }
          769  +    db->lookaside.bDisable++;
          770  +  }
          771  +}
          772  +
          773  +/*
          774  +** This routine reactivates the memory allocator and clears the
          775  +** db->mallocFailed flag as necessary.
          776  +**
          777  +** The memory allocator is not restarted if there are running
          778  +** VDBEs.
          779  +*/
          780  +void sqlite3OomClear(sqlite3 *db){
          781  +  if( db->mallocFailed && db->nVdbeExec==0 ){
          782  +    db->mallocFailed = 0;
          783  +    db->u1.isInterrupted = 0;
          784  +    assert( db->lookaside.bDisable>0 );
          785  +    db->lookaside.bDisable--;
          786  +  }
          787  +}
   738    788   
   739    789   /*
   740    790   ** Take actions at the end of an API call to indicate an OOM error
   741    791   */
   742    792   static SQLITE_NOINLINE int apiOomError(sqlite3 *db){
   743         -  db->mallocFailed = 0;
          793  +  sqlite3OomClear(db);
   744    794     sqlite3Error(db, SQLITE_NOMEM);
   745    795     return SQLITE_NOMEM;
   746    796   }
   747    797   
   748    798   /*
   749    799   ** This function must be called before exiting any API function (i.e. 
   750    800   ** returning control to the user) that has called sqlite3_malloc or

Changes to src/os_unix.c.

  7084   7084       return rc;
  7085   7085     }
  7086   7086   #ifndef SQLITE_DISABLE_DIRSYNC
  7087   7087     if( (dirSync & 1)!=0 ){
  7088   7088       int fd;
  7089   7089       rc = osOpenDirectory(zPath, &fd);
  7090   7090       if( rc==SQLITE_OK ){
  7091         -#if OS_VXWORKS
  7092         -      if( fsync(fd)==-1 )
  7093         -#else
  7094         -      if( fsync(fd) )
  7095         -#endif
  7096         -      {
         7091  +      if( full_fsync(fd,0,0) ){
  7097   7092           rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath);
  7098   7093         }
  7099   7094   #if OSCLOSE_CHECK_CLOSE_IOERR
  7100   7095         if( close(fd)&&!rc ){
  7101   7096           rc = SQLITE_IOERR_DIR_CLOSE;
  7102   7097         }
  7103   7098   #else
................................................................................
  8181   8176                     MAXPATHLEN);
  8182   8177           }else{
  8183   8178             strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN);
  8184   8179           }
  8185   8180           writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]);
  8186   8181           robust_ftruncate(conchFile->h, writeSize);
  8187   8182           rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0);
  8188         -        fsync(conchFile->h);
         8183  +        full_fsync(conchFile->h,0,0);
  8189   8184           /* If we created a new conch file (not just updated the contents of a 
  8190   8185            ** valid conch file), try to match the permissions of the database 
  8191   8186            */
  8192   8187           if( rc==SQLITE_OK && createConch ){
  8193   8188             struct stat buf;
  8194   8189             int err = osFstat(pFile->h, &buf);
  8195   8190             if( err==0 ){

Changes to src/pager.c.

   633    633   struct Pager {
   634    634     sqlite3_vfs *pVfs;          /* OS functions to use for IO */
   635    635     u8 exclusiveMode;           /* Boolean. True if locking_mode==EXCLUSIVE */
   636    636     u8 journalMode;             /* One of the PAGER_JOURNALMODE_* values */
   637    637     u8 useJournal;              /* Use a rollback journal on this file */
   638    638     u8 noSync;                  /* Do not sync the journal if true */
   639    639     u8 fullSync;                /* Do extra syncs of the journal for robustness */
          640  +  u8 extraSync;               /* sync directory after journal delete */
   640    641     u8 ckptSyncFlags;           /* SYNC_NORMAL or SYNC_FULL for checkpoint */
   641    642     u8 walSyncFlags;            /* SYNC_NORMAL or SYNC_FULL for wal writes */
   642    643     u8 syncFlags;               /* SYNC_NORMAL or SYNC_FULL otherwise */
   643    644     u8 tempFile;                /* zFilename is a temporary or immutable file */
   644    645     u8 noLock;                  /* Do not lock (except in WAL mode) */
   645    646     u8 readOnly;                /* True for a read-only database */
   646    647     u8 memDb;                   /* True to inhibit all file I/O */
................................................................................
  1993   1994         int bDelete = (!pPager->tempFile && sqlite3JournalExists(pPager->jfd));
  1994   1995         assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE 
  1995   1996              || pPager->journalMode==PAGER_JOURNALMODE_MEMORY 
  1996   1997              || pPager->journalMode==PAGER_JOURNALMODE_WAL 
  1997   1998         );
  1998   1999         sqlite3OsClose(pPager->jfd);
  1999   2000         if( bDelete ){
  2000         -        rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 
  2001         -                 pPager->fullSync && SQLITE_EXTRA_DURABLE);
         2001  +        rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, pPager->extraSync);
  2002   2002         }
  2003   2003       }
  2004   2004     }
  2005   2005   
  2006   2006   #ifdef SQLITE_CHECK_PAGES
  2007   2007     sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash);
  2008   2008     if( pPager->dbSize==0 && sqlite3PcacheRefCount(pPager->pPCache)>0 ){
................................................................................
  3508   3508   */
  3509   3509   #ifndef SQLITE_OMIT_PAGER_PRAGMAS
  3510   3510   void sqlite3PagerSetFlags(
  3511   3511     Pager *pPager,        /* The pager to set safety level for */
  3512   3512     unsigned pgFlags      /* Various flags */
  3513   3513   ){
  3514   3514     unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK;
  3515         -  assert( level>=1 && level<=3 );
  3516         -  pPager->noSync =  (level==1 || pPager->tempFile) ?1:0;
  3517         -  pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0;
         3515  +  if( pPager->tempFile ){
         3516  +    pPager->noSync = 1;
         3517  +    pPager->fullSync = 0;
         3518  +    pPager->extraSync = 0;
         3519  +  }else{
         3520  +    pPager->noSync =  level==PAGER_SYNCHRONOUS_OFF ?1:0;
         3521  +    pPager->fullSync = level>=PAGER_SYNCHRONOUS_FULL ?1:0;
         3522  +    pPager->extraSync = level==PAGER_SYNCHRONOUS_EXTRA ?1:0;
         3523  +  }
  3518   3524     if( pPager->noSync ){
  3519   3525       pPager->syncFlags = 0;
  3520   3526       pPager->ckptSyncFlags = 0;
  3521   3527     }else if( pgFlags & PAGER_FULLFSYNC ){
  3522   3528       pPager->syncFlags = SQLITE_SYNC_FULL;
  3523   3529       pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
  3524   3530     }else if( pgFlags & PAGER_CKPT_FULLFSYNC ){
................................................................................
  4822   4828     assert( useJournal || pPager->tempFile );
  4823   4829     pPager->noSync = pPager->tempFile;
  4824   4830     pPager->fullSync = pPager->noSync ?0:1;
  4825   4831     pPager->syncFlags = pPager->noSync ? 0 : SQLITE_SYNC_NORMAL;
  4826   4832     pPager->ckptSyncFlags = pPager->syncFlags;
  4827   4833     if( pPager->noSync ){
  4828   4834       assert( pPager->fullSync==0 );
         4835  +    assert( pPager->extraSync==0 );
  4829   4836       assert( pPager->syncFlags==0 );
  4830   4837       assert( pPager->walSyncFlags==0 );
  4831   4838       assert( pPager->ckptSyncFlags==0 );
  4832   4839     }else{
  4833   4840       pPager->fullSync = 1;
         4841  +#if SQLITE_EXTRA_DURABLE
         4842  +    pPager->extraSync = 1;
         4843  +#else
         4844  +    pPager->extraSync = 0;
         4845  +#endif
  4834   4846       pPager->syncFlags = SQLITE_SYNC_NORMAL;
  4835   4847       pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS;
  4836   4848       pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL;
  4837   4849     }
  4838   4850     /* pPager->pFirst = 0; */
  4839   4851     /* pPager->pFirstSynced = 0; */
  4840   4852     /* pPager->pLast = 0; */

Changes to src/pager.h.

    86     86   
    87     87   /*
    88     88   ** Flags for sqlite3PagerSetFlags()
    89     89   */
    90     90   #define PAGER_SYNCHRONOUS_OFF       0x01  /* PRAGMA synchronous=OFF */
    91     91   #define PAGER_SYNCHRONOUS_NORMAL    0x02  /* PRAGMA synchronous=NORMAL */
    92     92   #define PAGER_SYNCHRONOUS_FULL      0x03  /* PRAGMA synchronous=FULL */
    93         -#define PAGER_SYNCHRONOUS_MASK      0x03  /* Mask for three values above */
    94         -#define PAGER_FULLFSYNC             0x04  /* PRAGMA fullfsync=ON */
    95         -#define PAGER_CKPT_FULLFSYNC        0x08  /* PRAGMA checkpoint_fullfsync=ON */
    96         -#define PAGER_CACHESPILL            0x10  /* PRAGMA cache_spill=ON */
    97         -#define PAGER_FLAGS_MASK            0x1c  /* All above except SYNCHRONOUS */
           93  +#define PAGER_SYNCHRONOUS_EXTRA     0x04  /* PRAGMA synchronous=EXTRA */
           94  +#define PAGER_SYNCHRONOUS_MASK      0x07  /* Mask for four values above */
           95  +#define PAGER_FULLFSYNC             0x08  /* PRAGMA fullfsync=ON */
           96  +#define PAGER_CKPT_FULLFSYNC        0x10  /* PRAGMA checkpoint_fullfsync=ON */
           97  +#define PAGER_CACHESPILL            0x20  /* PRAGMA cache_spill=ON */
           98  +#define PAGER_FLAGS_MASK            0x38  /* All above except SYNCHRONOUS */
    98     99   
    99    100   /*
   100    101   ** The remainder of this file contains the declarations of the functions
   101    102   ** that make up the Pager sub-system API. See source code comments for 
   102    103   ** a detailed description of each routine.
   103    104   */
   104    105   

Changes to src/parse.y.

   101    101   */
   102    102   struct TrigEvent { int a; IdList * b; };
   103    103   
   104    104   /*
   105    105   ** An instance of this structure holds the ATTACH key and the key type.
   106    106   */
   107    107   struct AttachKey { int type;  Token key; };
          108  +
          109  +/*
          110  +** Disable lookaside memory allocation for objects that might be
          111  +** shared across database connections.
          112  +*/
          113  +static void disableLookaside(Parse *pParse){
          114  +  pParse->disableLookaside++;
          115  +  pParse->db->lookaside.bDisable++;
          116  +}
   108    117   
   109    118   } // end %include
   110    119   
   111    120   // Input is a single SQL command
   112    121   input ::= cmdlist.
   113    122   cmdlist ::= cmdlist ecmd.
   114    123   cmdlist ::= ecmd.
................................................................................
   152    161   ///////////////////// The CREATE TABLE statement ////////////////////////////
   153    162   //
   154    163   cmd ::= create_table create_table_args.
   155    164   create_table ::= createkw temp(T) TABLE ifnotexists(E) nm(Y) dbnm(Z). {
   156    165      sqlite3StartTable(pParse,&Y,&Z,T,0,0,E);
   157    166   }
   158    167   createkw(A) ::= CREATE(X).  {
   159         -  pParse->db->lookaside.bEnabled = 0;
          168  +  disableLookaside(pParse);
   160    169     A = X;
   161    170   }
   162    171   %type ifnotexists {int}
   163    172   ifnotexists(A) ::= .              {A = 0;}
   164    173   ifnotexists(A) ::= IF NOT EXISTS. {A = 1;}
   165    174   %type temp {int}
   166    175   %ifndef SQLITE_OMIT_TEMPDB
................................................................................
  1503   1512   cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). {
  1504   1513     sqlite3AlterRenameTable(pParse,X,&Z);
  1505   1514   }
  1506   1515   cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column(Y). {
  1507   1516     sqlite3AlterFinishAddColumn(pParse, &Y);
  1508   1517   }
  1509   1518   add_column_fullname ::= fullname(X). {
  1510         -  pParse->db->lookaside.bEnabled = 0;
         1519  +  disableLookaside(pParse);
  1511   1520     sqlite3AlterBeginAddColumn(pParse, X);
  1512   1521   }
  1513   1522   kwcolumn_opt ::= .
  1514   1523   kwcolumn_opt ::= COLUMNKW.
  1515   1524   %endif  SQLITE_OMIT_ALTERTABLE
  1516   1525   
  1517   1526   //////////////////////// CREATE VIRTUAL TABLE ... /////////////////////////////

Changes to src/pragma.c.

    28     28   ** lexicographical order to facility a binary search of the pragma name.
    29     29   ** Do not edit pragma.h directly.  Edit and rerun the script in at 
    30     30   ** ../tool/mkpragmatab.tcl. */
    31     31   #include "pragma.h"
    32     32   
    33     33   /*
    34     34   ** Interpret the given string as a safety level.  Return 0 for OFF,
    35         -** 1 for ON or NORMAL and 2 for FULL.  Return 1 for an empty or 
    36         -** unrecognized string argument.  The FULL option is disallowed
           35  +** 1 for ON or NORMAL, 2 for FULL, and 3 for EXTRA.  Return 1 for an empty or 
           36  +** unrecognized string argument.  The FULL and EXTRA option is disallowed
    37     37   ** if the omitFull parameter it 1.
    38     38   **
    39     39   ** Note that the values returned are one less that the values that
    40     40   ** should be passed into sqlite3BtreeSetSafetyLevel().  The is done
    41     41   ** to support legacy SQL code.  The safety level used to be boolean
    42     42   ** and older scripts may have used numbers 0 for OFF and 1 for ON.
    43     43   */
    44     44   static u8 getSafetyLevel(const char *z, int omitFull, u8 dflt){
    45         -                             /* 123456789 123456789 */
    46         -  static const char zText[] = "onoffalseyestruefull";
    47         -  static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16};
    48         -  static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4};
    49         -  static const u8 iValue[] =  {1, 0, 0, 0, 1, 1, 2};
           45  +                             /* 123456789 123456789 123 */
           46  +  static const char zText[] = "onoffalseyestruextrafull";
           47  +  static const u8 iOffset[] = {0, 1, 2,  4,    9,  12,  15,   20};
           48  +  static const u8 iLength[] = {2, 2, 3,  5,    3,   4,   5,    4};
           49  +  static const u8 iValue[] =  {1, 0, 0,  0,    1,   1,   3,    2};
           50  +                            /* on no off false yes true extra full */
    50     51     int i, n;
    51     52     if( sqlite3Isdigit(*z) ){
    52     53       return (u8)sqlite3Atoi(z);
    53     54     }
    54     55     n = sqlite3Strlen30(z);
    55         -  for(i=0; i<ArraySize(iLength)-omitFull; i++){
    56         -    if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0 ){
           56  +  for(i=0; i<ArraySize(iLength); i++){
           57  +    if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0
           58  +     && (!omitFull || iValue[i]<=1)
           59  +    ){
    57     60         return iValue[i];
    58     61       }
    59     62     }
    60     63     return dflt;
    61     64   }
    62     65   
    63     66   /*
................................................................................
   471    474         returnSingleInt(v, "page_size", size);
   472    475       }else{
   473    476         /* Malloc may fail when setting the page-size, as there is an internal
   474    477         ** buffer that the pager module resizes using sqlite3_realloc().
   475    478         */
   476    479         db->nextPagesize = sqlite3Atoi(zRight);
   477    480         if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,-1,0) ){
   478         -        db->mallocFailed = 1;
          481  +        sqlite3OomFault(db);
   479    482         }
   480    483       }
   481    484       break;
   482    485     }
   483    486   
   484    487     /*
   485    488     **  PRAGMA [schema.]secure_delete
................................................................................
   982    985       }
   983    986       break;
   984    987     }
   985    988   #endif /* SQLITE_ENABLE_LOCKING_STYLE */      
   986    989       
   987    990     /*
   988    991     **   PRAGMA [schema.]synchronous
   989         -  **   PRAGMA [schema.]synchronous=OFF|ON|NORMAL|FULL
          992  +  **   PRAGMA [schema.]synchronous=OFF|ON|NORMAL|FULL|EXTRA
   990    993     **
   991    994     ** Return or set the local value of the synchronous flag.  Changing
   992    995     ** the local value does not make changes to the disk file and the
   993    996     ** default value will be restored the next time the database is
   994    997     ** opened.
   995    998     */
   996    999     case PragTyp_SYNCHRONOUS: {
................................................................................
  1612   1615   #endif /* SQLITE_OMIT_BTREECOUNT */
  1613   1616         } 
  1614   1617       }
  1615   1618       {
  1616   1619         static const int iLn = VDBE_OFFSET_LINENO(2);
  1617   1620         static const VdbeOpList endCode[] = {
  1618   1621           { OP_AddImm,      1, 0,        0},    /* 0 */
  1619         -        { OP_If,          1, 0,        0},    /* 1 */
         1622  +        { OP_If,          1, 4,        0},    /* 1 */
  1620   1623           { OP_String8,     0, 3,        0},    /* 2 */
  1621         -        { OP_ResultRow,   3, 1,        0},
         1624  +        { OP_ResultRow,   3, 1,        0},    /* 3 */
  1622   1625         };
  1623   1626         VdbeOp *aOp;
  1624   1627   
  1625   1628         aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
  1626   1629         if( aOp ){
  1627   1630           aOp[0].p2 = -mxErr;
  1628         -        aOp[1].p2 = sqlite3VdbeCurrentAddr(v);
  1629   1631           aOp[2].p4type = P4_STATIC;
  1630   1632           aOp[2].p4.z = "ok";
  1631   1633         }
  1632   1634       }
  1633   1635     }
  1634   1636     break;
  1635   1637   #endif /* SQLITE_OMIT_INTEGRITY_CHECK */

Changes to src/prepare.c.

    27     27     const char *zObj,    /* Object being parsed at the point of error */
    28     28     const char *zExtra   /* Error information */
    29     29   ){
    30     30     sqlite3 *db = pData->db;
    31     31     if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){
    32     32       char *z;
    33     33       if( zObj==0 ) zObj = "?";
    34         -    z = sqlite3_mprintf("malformed database schema (%s)", zObj);
    35         -    if( z && zExtra ) z = sqlite3_mprintf("%z - %s", z, zExtra);
           34  +    z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj);
           35  +    if( zExtra ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra);
    36     36       sqlite3DbFree(db, *pData->pzErrMsg);
    37     37       *pData->pzErrMsg = z;
    38         -    if( z==0 ) db->mallocFailed = 1;
    39     38     }
    40     39     pData->rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_CORRUPT_BKPT;
    41     40   }
    42     41   
    43     42   /*
    44     43   ** This is the callback routine for the code that initializes the
    45     44   ** database.  See sqlite3Init() below for additional information.
................................................................................
    90     89       db->init.iDb = 0;
    91     90       if( SQLITE_OK!=rc ){
    92     91         if( db->init.orphanTrigger ){
    93     92           assert( iDb==1 );
    94     93         }else{
    95     94           pData->rc = rc;
    96     95           if( rc==SQLITE_NOMEM ){
    97         -          db->mallocFailed = 1;
           96  +          sqlite3OomFault(db);
    98     97           }else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){
    99     98             corruptSchema(pData, argv[0], sqlite3_errmsg(db));
   100     99           }
   101    100         }
   102    101       }
   103    102       sqlite3_finalize(pStmt);
   104    103     }else if( argv[0]==0 || (argv[2]!=0 && argv[2][0]!=0) ){
................................................................................
   335    334     if( openedTransaction ){
   336    335       sqlite3BtreeCommit(pDb->pBt);
   337    336     }
   338    337     sqlite3BtreeLeave(pDb->pBt);
   339    338   
   340    339   error_out:
   341    340     if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
   342         -    db->mallocFailed = 1;
          341  +    sqlite3OomFault(db);
   343    342     }
   344    343     return rc;
   345    344   }
   346    345   
   347    346   /*
   348    347   ** Initialize all database files - the main database file, the file
   349    348   ** used to store temporary tables, and any additional database files
................................................................................
   433    432   
   434    433       /* If there is not already a read-only (or read-write) transaction opened
   435    434       ** on the b-tree database, open one now. If a transaction is opened, it 
   436    435       ** will be closed immediately after reading the meta-value. */
   437    436       if( !sqlite3BtreeIsInReadTrans(pBt) ){
   438    437         rc = sqlite3BtreeBeginTrans(pBt, 0);
   439    438         if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
   440         -        db->mallocFailed = 1;
          439  +        sqlite3OomFault(db);
   441    440         }
   442    441         if( rc!=SQLITE_OK ) return;
   443    442         openedTransaction = 1;
   444    443       }
   445    444   
   446    445       /* Read the schema cookie from the database. If it does not match the 
   447    446       ** value stored as part of the in-memory schema representation,
................................................................................
   496    495   ** Free all memory allocations in the pParse object
   497    496   */
   498    497   void sqlite3ParserReset(Parse *pParse){
   499    498     if( pParse ){
   500    499       sqlite3 *db = pParse->db;
   501    500       sqlite3DbFree(db, pParse->aLabel);
   502    501       sqlite3ExprListDelete(db, pParse->pConstExpr);
          502  +    if( db ){
          503  +      assert( db->lookaside.bDisable >= pParse->disableLookaside );
          504  +      db->lookaside.bDisable -= pParse->disableLookaside;
          505  +    }
          506  +    pParse->disableLookaside = 0;
   503    507     }
   504    508   }
   505    509   
   506    510   /*
   507    511   ** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
   508    512   */
   509    513   static int sqlite3Prepare(
................................................................................
   591    595         pParse->zTail = &zSql[nBytes];
   592    596       }
   593    597     }else{
   594    598       sqlite3RunParser(pParse, zSql, &zErrMsg);
   595    599     }
   596    600     assert( 0==pParse->nQueryLoop );
   597    601   
   598         -  if( db->mallocFailed ){
   599         -    pParse->rc = SQLITE_NOMEM;
   600         -  }
   601    602     if( pParse->rc==SQLITE_DONE ) pParse->rc = SQLITE_OK;
   602    603     if( pParse->checkSchema ){
   603    604       schemaIsValid(pParse);
   604    605     }
   605    606     if( db->mallocFailed ){
   606    607       pParse->rc = SQLITE_NOMEM;
   607    608     }
................................................................................
   715    716     zSql = sqlite3_sql((sqlite3_stmt *)p);
   716    717     assert( zSql!=0 );  /* Reprepare only called for prepare_v2() statements */
   717    718     db = sqlite3VdbeDb(p);
   718    719     assert( sqlite3_mutex_held(db->mutex) );
   719    720     rc = sqlite3LockAndPrepare(db, zSql, -1, 0, p, &pNew, 0);
   720    721     if( rc ){
   721    722       if( rc==SQLITE_NOMEM ){
   722         -      db->mallocFailed = 1;
          723  +      sqlite3OomFault(db);
   723    724       }
   724    725       assert( pNew==0 );
   725    726       return rc;
   726    727     }else{
   727    728       assert( pNew!=0 );
   728    729     }
   729    730     sqlite3VdbeSwap((Vdbe*)pNew, p);

Changes to src/printf.c.

   925    925     assert( db!=0 );
   926    926     sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase),
   927    927                         db->aLimit[SQLITE_LIMIT_LENGTH]);
   928    928     acc.printfFlags = SQLITE_PRINTF_INTERNAL;
   929    929     sqlite3VXPrintf(&acc, zFormat, ap);
   930    930     z = sqlite3StrAccumFinish(&acc);
   931    931     if( acc.accError==STRACCUM_NOMEM ){
   932         -    db->mallocFailed = 1;
          932  +    sqlite3OomFault(db);
   933    933     }
   934    934     return z;
   935    935   }
   936    936   
   937    937   /*
   938    938   ** Print into memory obtained from sqliteMalloc().  Use the internal
   939    939   ** %-conversion extensions.

Changes to src/rowset.c.

   177    177   ** In an OOM situation, the RowSet.db->mallocFailed flag is set and this
   178    178   ** routine returns NULL.
   179    179   */
   180    180   static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){
   181    181     assert( p!=0 );
   182    182     if( p->nFresh==0 ){
   183    183       struct RowSetChunk *pNew;
   184         -    pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew));
          184  +    pNew = sqlite3DbMallocRawNN(p->db, sizeof(*pNew));
   185    185       if( pNew==0 ){
   186    186         return 0;
   187    187       }
   188    188       pNew->pNextChunk = p->pChunk;
   189    189       p->pChunk = pNew;
   190    190       p->pFresh = pNew->aEntry;
   191    191       p->nFresh = ROWSET_ENTRY_PER_CHUNK;

Changes to src/select.c.

   108    108     u16 selFlags,         /* Flag parameters, such as SF_Distinct */
   109    109     Expr *pLimit,         /* LIMIT value.  NULL means not used */
   110    110     Expr *pOffset         /* OFFSET value.  NULL means no offset */
   111    111   ){
   112    112     Select *pNew;
   113    113     Select standin;
   114    114     sqlite3 *db = pParse->db;
   115         -  pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) );
          115  +  pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) );
   116    116     if( pNew==0 ){
   117    117       assert( db->mallocFailed );
   118    118       pNew = &standin;
   119    119     }
   120    120     if( pEList==0 ){
   121    121       pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ASTERISK,0));
   122    122     }
................................................................................
  1012   1012       p->nField = (u16)N;
  1013   1013       p->nXField = (u16)X;
  1014   1014       p->enc = ENC(db);
  1015   1015       p->db = db;
  1016   1016       p->nRef = 1;
  1017   1017       memset(&p[1], 0, nExtra);
  1018   1018     }else{
  1019         -    db->mallocFailed = 1;
         1019  +    sqlite3OomFault(db);
  1020   1020     }
  1021   1021     return p;
  1022   1022   }
  1023   1023   
  1024   1024   /*
  1025   1025   ** Deallocate a KeyInfo object
  1026   1026   */
................................................................................
  1673   1673         }
  1674   1674         zName = sqlite3MPrintf(db, "%.*z:%u", nName, zName, ++cnt);
  1675   1675         if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt);
  1676   1676       }
  1677   1677       pCol->zName = zName;
  1678   1678       sqlite3ColumnPropertiesFromName(0, pCol);
  1679   1679       if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){
  1680         -      db->mallocFailed = 1;
         1680  +      sqlite3OomFault(db);
  1681   1681       }
  1682   1682     }
  1683   1683     sqlite3HashClear(&ht);
  1684   1684     if( db->mallocFailed ){
  1685   1685       for(j=0; j<i; j++){
  1686   1686         sqlite3DbFree(db, aCol[j].zName);
  1687   1687       }
................................................................................
  1760   1760     db->flags = savedFlags;
  1761   1761     pTab = sqlite3DbMallocZero(db, sizeof(Table) );
  1762   1762     if( pTab==0 ){
  1763   1763       return 0;
  1764   1764     }
  1765   1765     /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
  1766   1766     ** is disabled */
  1767         -  assert( db->lookaside.bEnabled==0 );
         1767  +  assert( db->lookaside.bDisable );
  1768   1768     pTab->nRef = 1;
  1769   1769     pTab->zName = 0;
  1770   1770     pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
  1771   1771     sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
  1772   1772     selectAddColumnTypeAndCollation(pParse, pTab, pSelect);
  1773   1773     pTab->iPKey = -1;
  1774   1774     if( db->mallocFailed ){
................................................................................
  2866   2866     /* Compute the comparison permutation and keyinfo that is used with
  2867   2867     ** the permutation used to determine if the next
  2868   2868     ** row of results comes from selectA or selectB.  Also add explicit
  2869   2869     ** collations to the ORDER BY clause terms so that when the subqueries
  2870   2870     ** to the right and the left are evaluated, they use the correct
  2871   2871     ** collation.
  2872   2872     */
  2873         -  aPermute = sqlite3DbMallocRaw(db, sizeof(int)*(nOrderBy + 1));
         2873  +  aPermute = sqlite3DbMallocRawNN(db, sizeof(int)*(nOrderBy + 1));
  2874   2874     if( aPermute ){
  2875   2875       struct ExprList_item *pItem;
  2876   2876       aPermute[0] = nOrderBy;
  2877   2877       for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){
  2878   2878         assert( pItem->u.x.iOrderByCol>0 );
  2879   2879         assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr );
  2880   2880         aPermute[i] = pItem->u.x.iOrderByCol - 1;
................................................................................
  5558   5558             flag = minMaxQuery(&sAggInfo, &pMinMax);
  5559   5559           }
  5560   5560           assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) );
  5561   5561   
  5562   5562           if( flag ){
  5563   5563             pMinMax = sqlite3ExprListDup(db, pMinMax, 0);
  5564   5564             pDel = pMinMax;
  5565         -          if( pMinMax && !db->mallocFailed ){
         5565  +          assert( db->mallocFailed || pMinMax!=0 );
         5566  +          if( !db->mallocFailed ){
  5566   5567               pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0;
  5567   5568               pMinMax->a[0].pExpr->op = TK_COLUMN;
  5568   5569             }
  5569   5570           }
  5570   5571     
  5571   5572           /* This case runs if the aggregate has no GROUP BY clause.  The
  5572   5573           ** processing is much simpler since there is only a single row

Changes to src/sqliteInt.h.

  1001   1001   /* When using a default wal safety level, the safety level should only 
  1002   1002   ** change with the journal mode if the user hasn't manually specified 
  1003   1003   ** pragma synchronous, if they have the defaults shouldn't be applied.
  1004   1004   ** The SQLITE_SAFETYLEVEL_FIXED value is ORed into the Db->safety_level
  1005   1005   ** field when the user has specified a synchronous setting via pragma.
  1006   1006   */
  1007   1007   #define SQLITE_SAFETYLEVEL_FIXED 0x10
  1008         -#define SQLITE_SAFETYLEVEL_VALUE_MASK 0x03
         1008  +#define SQLITE_SAFETYLEVEL_VALUE_MASK 0x07
  1009   1009   #define SQLITE_DbSafetyLevelValue(level) (level&SQLITE_SAFETYLEVEL_VALUE_MASK)
  1010   1010   #define SQLITE_DbSafetyLevelIsFixed(level) (level&SQLITE_SAFETYLEVEL_FIXED)
  1011   1011   
  1012   1012   /*
  1013   1013   ** Each database file to be accessed by the system is an instance
  1014   1014   ** of the following structure.  There are normally two of these structures
  1015   1015   ** in the sqlite.aDb[] array.  aDb[0] is the main database file and
................................................................................
  1100   1100   ** with a particular database connection.  Hence, schema information cannot
  1101   1101   ** be stored in lookaside because in shared cache mode the schema information
  1102   1102   ** is shared by multiple database connections.  Therefore, while parsing
  1103   1103   ** schema information, the Lookaside.bEnabled flag is cleared so that
  1104   1104   ** lookaside allocations are not used to construct the schema objects.
  1105   1105   */
  1106   1106   struct Lookaside {
         1107  +  u32 bDisable;           /* Only operate the lookaside when zero */
  1107   1108     u16 sz;                 /* Size of each buffer in bytes */
  1108         -  u8 bEnabled;            /* False to disable new lookaside allocations */
  1109   1109     u8 bMalloced;           /* True if pStart obtained from sqlite3_malloc() */
  1110   1110     int nOut;               /* Number of buffers currently checked out */
  1111   1111     int mxOut;              /* Highwater mark for nOut */
  1112   1112     int anStat[3];          /* 0: hits.  1: size misses.  2: full misses */
  1113   1113     LookasideSlot *pFree;   /* List of available buffers */
  1114   1114     void *pStart;           /* First byte of available memory space */
  1115   1115     void *pEnd;             /* First byte past end of available space */
................................................................................
  1184   1184     int errCode;                  /* Most recent error code (SQLITE_*) */
  1185   1185     int errMask;                  /* & result codes with this before returning */
  1186   1186     u16 dbOptFlags;               /* Flags to enable/disable optimizations */
  1187   1187     u8 enc;                       /* Text encoding */
  1188   1188     u8 autoCommit;                /* The auto-commit flag. */
  1189   1189     u8 temp_store;                /* 1: file 2: memory 0: default */
  1190   1190     u8 mallocFailed;              /* True if we have seen a malloc failure */
         1191  +  u8 bBenignMalloc;             /* Do not require OOMs if true */
  1191   1192     u8 dfltLockMode;              /* Default locking-mode for attached dbs */
  1192   1193     signed char nextAutovac;      /* Autovac setting after VACUUM if >=0 */
  1193   1194     u8 suppressErr;               /* Do not issue error messages if true */
  1194   1195     u8 vtabOnConflict;            /* Value to return for s3_vtab_on_conflict() */
  1195   1196     u8 isTransactionSavepoint;    /* True if the outermost savepoint is a TS */
  1196   1197     int nextPagesize;             /* Pagesize after VACUUM if >0 */
  1197   1198     u32 magic;                    /* Magic number for detect library misuse */
................................................................................
  1292   1293   #define ENC(db)        ((db)->enc)
  1293   1294   
  1294   1295   /*
  1295   1296   ** Possible values for the sqlite3.flags.
  1296   1297   */
  1297   1298   #define SQLITE_VdbeTrace      0x00000001  /* True to trace VDBE execution */
  1298   1299   #define SQLITE_InternChanges  0x00000002  /* Uncommitted Hash table changes */
  1299         -#define SQLITE_FullFSync      0x00000004  /* Use full fsync on the backend */
  1300         -#define SQLITE_CkptFullFSync  0x00000008  /* Use full fsync for checkpoint */
  1301         -#define SQLITE_CacheSpill     0x00000010  /* OK to spill pager cache */
  1302         -#define SQLITE_FullColNames   0x00000020  /* Show full column names on SELECT */
         1300  +#define SQLITE_FullColNames   0x00000004  /* Show full column names on SELECT */
         1301  +#define SQLITE_FullFSync      0x00000008  /* Use full fsync on the backend */
         1302  +#define SQLITE_CkptFullFSync  0x00000010  /* Use full fsync for checkpoint */
         1303  +#define SQLITE_CacheSpill     0x00000020  /* OK to spill pager cache */
  1303   1304   #define SQLITE_ShortColNames  0x00000040  /* Show short columns names */
  1304   1305   #define SQLITE_CountRows      0x00000080  /* Count rows changed by INSERT, */
  1305   1306                                             /*   DELETE, or UPDATE and return */
  1306   1307                                             /*   the count using a callback. */
  1307   1308   #define SQLITE_NullCallback   0x00000100  /* Invoke the callback once if the */
  1308   1309                                             /*   result set is empty */
  1309   1310   #define SQLITE_SqlTrace       0x00000200  /* Debug print SQL as it executes */
................................................................................
  2647   2648   };
  2648   2649   
  2649   2650   /*
  2650   2651   ** During code generation of statements that do inserts into AUTOINCREMENT 
  2651   2652   ** tables, the following information is attached to the Table.u.autoInc.p
  2652   2653   ** pointer of each autoincrement table to record some side information that
  2653   2654   ** the code generator needs.  We have to keep per-table autoincrement
  2654         -** information in case inserts are down within triggers.  Triggers do not
         2655  +** information in case inserts are done within triggers.  Triggers do not
  2655   2656   ** normally coordinate their activities, but we do need to coordinate the
  2656   2657   ** loading and saving of autoincrement information.
  2657   2658   */
  2658   2659   struct AutoincInfo {
  2659   2660     AutoincInfo *pNext;   /* Next info block in a list of them all */
  2660   2661     Table *pTab;          /* Table this info block refers to */
  2661   2662     int iDb;              /* Index in sqlite3.aDb[] of database holding pTab */
................................................................................
  2739   2740     u8 checkSchema;      /* Causes schema cookie check after an error */
  2740   2741     u8 nested;           /* Number of nested calls to the parser/code generator */
  2741   2742     u8 nTempReg;         /* Number of temporary registers in aTempReg[] */
  2742   2743     u8 isMultiWrite;     /* True if statement may modify/insert multiple rows */
  2743   2744     u8 mayAbort;         /* True if statement may throw an ABORT exception */
  2744   2745     u8 hasCompound;      /* Need to invoke convertCompoundSelectToSubquery() */
  2745   2746     u8 okConstFactor;    /* OK to factor out constants */
         2747  +  u8 disableLookaside; /* Number of times lookaside has been disabled */
  2746   2748     int aTempReg[8];     /* Holding area for temporary registers */
  2747   2749     int nRangeReg;       /* Size of the temporary register block */
  2748   2750     int iRangeReg;       /* First register in temporary register block */
  2749   2751     int nErr;            /* Number of errors seen */
  2750   2752     int nTab;            /* Number of previously allocated VDBE cursors */
  2751   2753     int nMem;            /* Number of memory cells used so far */
  2752   2754     int nSet;            /* Number of sets used so far */
................................................................................
  3231   3233   
  3232   3234   int sqlite3MallocInit(void);
  3233   3235   void sqlite3MallocEnd(void);
  3234   3236   void *sqlite3Malloc(u64);
  3235   3237   void *sqlite3MallocZero(u64);
  3236   3238   void *sqlite3DbMallocZero(sqlite3*, u64);
  3237   3239   void *sqlite3DbMallocRaw(sqlite3*, u64);
         3240  +void *sqlite3DbMallocRawNN(sqlite3*, u64);
  3238   3241   char *sqlite3DbStrDup(sqlite3*,const char*);
  3239   3242   char *sqlite3DbStrNDup(sqlite3*,const char*, u64);
  3240   3243   void *sqlite3Realloc(void*, u64);
  3241   3244   void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64);
  3242   3245   void *sqlite3DbRealloc(sqlite3 *, void *, u64);
  3243   3246   void sqlite3DbFree(sqlite3*, void*);
  3244   3247   int sqlite3MallocSize(void*);
................................................................................
  3783   3786   int sqlite3KeyInfoIsWriteable(KeyInfo*);
  3784   3787   #endif
  3785   3788   int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, 
  3786   3789     void (*)(sqlite3_context*,int,sqlite3_value **),
  3787   3790     void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*),
  3788   3791     FuncDestructor *pDestructor
  3789   3792   );
         3793  +void sqlite3OomFault(sqlite3*);
         3794  +void sqlite3OomClear(sqlite3*);
  3790   3795   int sqlite3ApiExit(sqlite3 *db, int);
  3791   3796   int sqlite3OpenTempDatabase(Parse *);
  3792   3797   
  3793   3798   void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int);
  3794   3799   void sqlite3StrAccumAppend(StrAccum*,const char*,int);
  3795   3800   void sqlite3StrAccumAppendAll(StrAccum*,const char*);
  3796   3801   void sqlite3AppendChar(StrAccum*,int,char);

Changes to src/test_func.c.

   162    162   static void test_agg_errmsg16_step(sqlite3_context *a, int b,sqlite3_value **c){
   163    163   }
   164    164   static void test_agg_errmsg16_final(sqlite3_context *ctx){
   165    165   #ifndef SQLITE_OMIT_UTF16
   166    166     const void *z;
   167    167     sqlite3 * db = sqlite3_context_db_handle(ctx);
   168    168     sqlite3_aggregate_context(ctx, 2048);
   169         -  sqlite3BeginBenignMalloc();
   170    169     z = sqlite3_errmsg16(db);
   171         -  sqlite3EndBenignMalloc();
   172    170     sqlite3_result_text16(ctx, z, -1, SQLITE_TRANSIENT);
   173    171   #endif
   174    172   }
   175    173   
   176    174   /*
   177    175   ** Routines for testing the sqlite3_get_auxdata() and sqlite3_set_auxdata()
   178    176   ** interface.

Changes to src/tokenize.c.

   386    386   */
   387    387   int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
   388    388     int nErr = 0;                   /* Number of errors encountered */
   389    389     int i;                          /* Loop counter */
   390    390     void *pEngine;                  /* The LEMON-generated LALR(1) parser */
   391    391     int tokenType;                  /* type of the next token */
   392    392     int lastTokenParsed = -1;       /* type of the previous token */
   393         -  u8 enableLookaside;             /* Saved value of db->lookaside.bEnabled */
   394    393     sqlite3 *db = pParse->db;       /* The database connection */
   395    394     int mxSqlLen;                   /* Max length of an SQL string */
   396    395   
   397    396     assert( zSql!=0 );
   398    397     mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
   399    398     if( db->nVdbeActive==0 ){
   400    399       db->u1.isInterrupted = 0;
................................................................................
   402    401     pParse->rc = SQLITE_OK;
   403    402     pParse->zTail = zSql;
   404    403     i = 0;
   405    404     assert( pzErrMsg!=0 );
   406    405     /* sqlite3ParserTrace(stdout, "parser: "); */
   407    406     pEngine = sqlite3ParserAlloc(sqlite3Malloc);
   408    407     if( pEngine==0 ){
   409         -    db->mallocFailed = 1;
          408  +    sqlite3OomFault(db);
   410    409       return SQLITE_NOMEM;
   411    410     }
   412    411     assert( pParse->pNewTable==0 );
   413    412     assert( pParse->pNewTrigger==0 );
   414    413     assert( pParse->nVar==0 );
   415    414     assert( pParse->nzVar==0 );
   416    415     assert( pParse->azVar==0 );
   417         -  enableLookaside = db->lookaside.bEnabled;
   418         -  if( db->lookaside.pStart ) db->lookaside.bEnabled = 1;
   419    416     while( zSql[i]!=0 ){
   420    417       assert( i>=0 );
   421    418       pParse->sLastToken.z = &zSql[i];
   422    419       pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType);
   423    420       i += pParse->sLastToken.n;
   424    421       if( i>mxSqlLen ){
   425    422         pParse->rc = SQLITE_TOOBIG;
   426    423         break;
   427    424       }
   428    425       if( tokenType>=TK_SPACE ){
   429    426         assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL );
   430    427         if( db->u1.isInterrupted ){
   431         -        sqlite3ErrorMsg(pParse, "interrupt");
   432    428           pParse->rc = SQLITE_INTERRUPT;
   433    429           break;
   434    430         }
   435    431         if( tokenType==TK_ILLEGAL ){
   436    432           sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"",
   437    433                           &pParse->sLastToken);
   438    434           break;
................................................................................
   459    455     sqlite3_mutex_enter(sqlite3MallocMutex());
   460    456     sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK,
   461    457         sqlite3ParserStackPeak(pEngine)
   462    458     );
   463    459     sqlite3_mutex_leave(sqlite3MallocMutex());
   464    460   #endif /* YYDEBUG */
   465    461     sqlite3ParserFree(pEngine, sqlite3_free);
   466         -  db->lookaside.bEnabled = enableLookaside;
   467    462     if( db->mallocFailed ){
   468    463       pParse->rc = SQLITE_NOMEM;
   469    464     }
   470    465     if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){
   471    466       pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc));
   472    467     }
   473    468     assert( pzErrMsg!=0 );

Changes to src/trigger.c.

   319    319   
   320    320     if( db->init.busy ){
   321    321       Trigger *pLink = pTrig;
   322    322       Hash *pHash = &db->aDb[iDb].pSchema->trigHash;
   323    323       assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
   324    324       pTrig = sqlite3HashInsert(pHash, zName, pTrig);
   325    325       if( pTrig ){
   326         -      db->mallocFailed = 1;
          326  +      sqlite3OomFault(db);
   327    327       }else if( pLink->pSchema==pLink->pTabSchema ){
   328    328         Table *pTab;
   329    329         pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table);
   330    330         assert( pTab!=0 );
   331    331         pLink->pNext = pTab->pTrigger;
   332    332         pTab->pTrigger = pLink;
   333    333       }

Changes to src/update.c.

   193    193       }
   194    194       pParse->nTab++;
   195    195     }
   196    196   
   197    197     /* Allocate space for aXRef[], aRegIdx[], and aToOpen[].  
   198    198     ** Initialize aXRef[] and aToOpen[] to their default values.
   199    199     */
   200         -  aXRef = sqlite3DbMallocRaw(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 );
          200  +  aXRef = sqlite3DbMallocRawNN(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 );
   201    201     if( aXRef==0 ) goto update_cleanup;
   202    202     aRegIdx = aXRef+pTab->nCol;
   203    203     aToOpen = (u8*)(aRegIdx+nIdx);
   204    204     memset(aToOpen, 1, nIdx+1);
   205    205     aToOpen[nIdx+1] = 0;
   206    206     for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
   207    207   

Changes to src/util.c.

  1146   1146   ** binary value has been obtained from malloc and must be freed by
  1147   1147   ** the calling routine.
  1148   1148   */
  1149   1149   void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){
  1150   1150     char *zBlob;
  1151   1151     int i;
  1152   1152   
  1153         -  zBlob = (char *)sqlite3DbMallocRaw(db, n/2 + 1);
         1153  +  zBlob = (char *)sqlite3DbMallocRawNN(db, n/2 + 1);
  1154   1154     n--;
  1155   1155     if( zBlob ){
  1156   1156       for(i=0; i<n; i+=2){
  1157   1157         zBlob[i/2] = (sqlite3HexToInt(z[i])<<4) | sqlite3HexToInt(z[i+1]);
  1158   1158       }
  1159   1159       zBlob[i/2] = 0;
  1160   1160     }

Changes to src/vdbe.c.

   626    626       }
   627    627       if( p->db->flags & SQLITE_VdbeTrace )  printf("VDBE Trace:\n");
   628    628     }
   629    629     sqlite3EndBenignMalloc();
   630    630   #endif
   631    631     for(pOp=&aOp[p->pc]; rc==SQLITE_OK; pOp++){
   632    632       assert( pOp>=aOp && pOp<&aOp[p->nOp]);
   633         -    if( db->mallocFailed ) goto no_mem;
   634    633   #ifdef VDBE_PROFILE
   635    634       start = sqlite3Hwtime();
   636    635   #endif
   637    636       nVmStep++;
   638    637   #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
   639    638       if( p->anExec ) p->anExec[(int)(pOp-aOp)]++;
   640    639   #endif
................................................................................
  1624   1623     sqlite3_context *pCtx;
  1625   1624   
  1626   1625     assert( pOp->p4type==P4_FUNCDEF );
  1627   1626     n = pOp->p5;
  1628   1627     assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
  1629   1628     assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) );
  1630   1629     assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
  1631         -  pCtx = sqlite3DbMallocRaw(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*));
         1630  +  pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*));
  1632   1631     if( pCtx==0 ) goto no_mem;
  1633   1632     pCtx->pOut = 0;
  1634   1633     pCtx->pFunc = pOp->p4.pFunc;
  1635   1634     pCtx->iOp = (int)(pOp - aOp);
  1636   1635     pCtx->pVdbe = p;
  1637   1636     pCtx->argc = n;
  1638   1637     pOp->p4type = P4_FUNCCTX;
................................................................................
  2868   2867         assert( db->autoCommit==0 || db->nVTrans==0 );
  2869   2868         rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN,
  2870   2869                                   db->nStatement+db->nSavepoint);
  2871   2870         if( rc!=SQLITE_OK ) goto abort_due_to_error;
  2872   2871   #endif
  2873   2872   
  2874   2873         /* Create a new savepoint structure. */
  2875         -      pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+nName+1);
         2874  +      pNew = sqlite3DbMallocRawNN(db, sizeof(Savepoint)+nName+1);
  2876   2875         if( pNew ){
  2877   2876           pNew->zName = (char *)&pNew[1];
  2878   2877           memcpy(pNew->zName, zName, nName+1);
  2879   2878       
  2880   2879           /* If there is no open transaction, then mark this as a special
  2881   2880           ** "transaction savepoint". */
  2882   2881           if( db->autoCommit ){
................................................................................
  4957   4956   ** to the row that corresponds to the current row of P1.
  4958   4957   **
  4959   4958   ** This is a deferred seek.  Nothing actually happens until
  4960   4959   ** the cursor is used to read a record.  That way, if no reads
  4961   4960   ** occur, no unnecessary I/O happens.
  4962   4961   **
  4963   4962   ** P4 may be an array of integers (type P4_INTARRAY) containing
  4964         -** one entry for each column in the P3 table.  If array entry a[i]
  4965         -** is non-zero, then reading column (a[i]-1) from cursor P3 is 
         4963  +** one entry for each column in the P3 table.  If array entry a(i)
         4964  +** is non-zero, then reading column a(i)-1 from cursor P3 is 
  4966   4965   ** equivalent to performing the deferred seek and then reading column i 
  4967   4966   ** from P1.  This information is stored in P3 and used to redirect
  4968   4967   ** reads against P3 over to P1, thus possibly avoiding the need to
  4969   4968   ** seek and read cursor P3.
  4970   4969   */
  4971   4970   /* Opcode: IdxRowid P1 P2 * * *
  4972   4971   ** Synopsis: r[P2]=rowid
................................................................................
  5418   5417     int nErr;       /* Number of errors reported */
  5419   5418     char *z;        /* Text of the error report */
  5420   5419     Mem *pnErr;     /* Register keeping track of errors remaining */
  5421   5420   
  5422   5421     assert( p->bIsReader );
  5423   5422     nRoot = pOp->p2;
  5424   5423     assert( nRoot>0 );
  5425         -  aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(nRoot+1) );
         5424  +  aRoot = sqlite3DbMallocRawNN(db, sizeof(int)*(nRoot+1) );
  5426   5425     if( aRoot==0 ) goto no_mem;
  5427   5426     assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
  5428   5427     pnErr = &aMem[pOp->p3];
  5429   5428     assert( (pnErr->flags & MEM_Int)!=0 );
  5430   5429     assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 );
  5431   5430     pIn1 = &aMem[pOp->p1];
  5432   5431     for(j=0; j<nRoot; j++){
................................................................................
  5915   5914     sqlite3_context *pCtx;
  5916   5915   
  5917   5916     assert( pOp->p4type==P4_FUNCDEF );
  5918   5917     n = pOp->p5;
  5919   5918     assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
  5920   5919     assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) );
  5921   5920     assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
  5922         -  pCtx = sqlite3DbMallocRaw(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*));
         5921  +  pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*));
  5923   5922     if( pCtx==0 ) goto no_mem;
  5924   5923     pCtx->pMem = 0;
  5925   5924     pCtx->pFunc = pOp->p4.pFunc;
  5926   5925     pCtx->iOp = (int)(pOp - aOp);
  5927   5926     pCtx->pVdbe = p;
  5928   5927     pCtx->argc = n;
  5929   5928     pOp->p4type = P4_FUNCCTX;
................................................................................
  6782   6781   vdbe_error_halt:
  6783   6782     assert( rc );
  6784   6783     p->rc = rc;
  6785   6784     testcase( sqlite3GlobalConfig.xLog!=0 );
  6786   6785     sqlite3_log(rc, "statement aborts at %d: [%s] %s", 
  6787   6786                      (int)(pOp - aOp), p->zSql, p->zErrMsg);
  6788   6787     sqlite3VdbeHalt(p);
  6789         -  if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
         6788  +  if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db);
  6790   6789     rc = SQLITE_ERROR;
  6791   6790     if( resetSchemaOnFault>0 ){
  6792   6791       sqlite3ResetOneSchema(db, resetSchemaOnFault-1);
  6793   6792     }
  6794   6793   
  6795   6794     /* This is the only way out of this procedure.  We have to
  6796   6795     ** release the mutexes on btrees that were acquired at the
................................................................................
  6812   6811     sqlite3VdbeError(p, "string or blob too big");
  6813   6812     rc = SQLITE_TOOBIG;
  6814   6813     goto vdbe_error_halt;
  6815   6814   
  6816   6815     /* Jump to here if a malloc() fails.
  6817   6816     */
  6818   6817   no_mem:
  6819         -  db->mallocFailed = 1;
         6818  +  sqlite3OomFault(db);
  6820   6819     sqlite3VdbeError(p, "out of memory");
  6821   6820     rc = SQLITE_NOMEM;
  6822   6821     goto vdbe_error_halt;
  6823   6822   
  6824   6823     /* Jump to here for any other kind of fatal error.  The "rc" variable
  6825   6824     ** should hold the error number.
  6826   6825     */
................................................................................
  6833   6832     goto vdbe_error_halt;
  6834   6833   
  6835   6834     /* Jump to here if the sqlite3_interrupt() API sets the interrupt
  6836   6835     ** flag.
  6837   6836     */
  6838   6837   abort_due_to_interrupt:
  6839   6838     assert( db->u1.isInterrupted );
  6840         -  rc = SQLITE_INTERRUPT;
         6839  +  rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_INTERRUPT;
  6841   6840     p->rc = rc;
  6842   6841     sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
  6843   6842     goto vdbe_error_halt;
  6844   6843   }

Changes to src/vdbeapi.c.

   485    485   
   486    486   /* An SQLITE_NOMEM error. */
   487    487   void sqlite3_result_error_nomem(sqlite3_context *pCtx){
   488    488     assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
   489    489     sqlite3VdbeMemSetNull(pCtx->pOut);
   490    490     pCtx->isError = SQLITE_NOMEM;
   491    491     pCtx->fErrorOrAux = 1;
   492         -  pCtx->pOut->db->mallocFailed = 1;
          492  +  sqlite3OomFault(pCtx->pOut->db);
   493    493   }
   494    494   
   495    495   /*
   496    496   ** This function is called after a transaction has been committed. It 
   497    497   ** invokes callbacks registered with sqlite3_wal_hook() as required.
   498    498   */
   499    499   static int doWalCallbacks(sqlite3 *db){
................................................................................
  1113   1113       sqlite3_mutex_enter(db->mutex);
  1114   1114       assert( db->mallocFailed==0 );
  1115   1115       ret = xFunc(&p->aColName[N]);
  1116   1116        /* A malloc may have failed inside of the xFunc() call. If this
  1117   1117       ** is the case, clear the mallocFailed flag and return NULL.
  1118   1118       */
  1119   1119       if( db->mallocFailed ){
  1120         -      db->mallocFailed = 0;
         1120  +      sqlite3OomClear(db);
  1121   1121         ret = 0;
  1122   1122       }
  1123   1123       sqlite3_mutex_leave(db->mutex);
  1124   1124     }
  1125   1125     return ret;
  1126   1126   }
  1127   1127   

Changes to src/vdbeaux.c.

   285    285     int op,             /* The new opcode */
   286    286     int p1,             /* The P1 operand */
   287    287     int p2,             /* The P2 operand */
   288    288     int p3,             /* The P3 operand */
   289    289     const u8 *zP4,      /* The P4 operand */
   290    290     int p4type          /* P4 operand type */
   291    291   ){
   292         -  char *p4copy = sqlite3DbMallocRaw(sqlite3VdbeDb(p), 8);
          292  +  char *p4copy = sqlite3DbMallocRawNN(sqlite3VdbeDb(p), 8);
   293    293     if( p4copy ) memcpy(p4copy, zP4, 8);
   294    294     return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type);
   295    295   }
   296    296   
   297    297   /*
   298    298   ** Add an OP_ParseSchema opcode.  This routine is broken out from
   299    299   ** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees
................................................................................
   642    642     p->aOp = 0;
   643    643     return aOp;
   644    644   }
   645    645   
   646    646   /*
   647    647   ** Add a whole list of operations to the operation stack.  Return a
   648    648   ** pointer to the first operation inserted.
          649  +**
          650  +** Non-zero P2 arguments to jump instructions are automatically adjusted
          651  +** so that the jump target is relative to the first operation inserted.
   649    652   */
   650    653   VdbeOp *sqlite3VdbeAddOpList(
   651    654     Vdbe *p,                     /* Add opcodes to the prepared statement */
   652    655     int nOp,                     /* Number of opcodes to add */
   653    656     VdbeOpList const *aOp,       /* The opcodes to be added */
   654    657     int iLineno                  /* Source-file line number of first opcode */
   655    658   ){
................................................................................
   662    665     }
   663    666     pFirst = pOut = &p->aOp[p->nOp];
   664    667     for(i=0; i<nOp; i++, aOp++, pOut++){
   665    668       pOut->opcode = aOp->opcode;
   666    669       pOut->p1 = aOp->p1;
   667    670       pOut->p2 = aOp->p2;
   668    671       assert( aOp->p2>=0 );
          672  +    if( (sqlite3OpcodeProperty[aOp->opcode] & OPFLG_JUMP)!=0 && aOp->p2>0 ){
          673  +      pOut->p2 += p->nOp;
          674  +    }
   669    675       pOut->p3 = aOp->p3;
   670    676       pOut->p4type = P4_NOTUSED;
   671    677       pOut->p4.p = 0;
   672    678       pOut->p5 = 0;
   673    679   #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
   674    680       pOut->zComment = 0;
   675    681   #endif
................................................................................
  1413   1419   /*
  1414   1420   ** Release an array of N Mem elements
  1415   1421   */
  1416   1422   static void releaseMemArray(Mem *p, int N){
  1417   1423     if( p && N ){
  1418   1424       Mem *pEnd = &p[N];
  1419   1425       sqlite3 *db = p->db;
  1420         -    u8 malloc_failed = db->mallocFailed;
  1421   1426       if( db->pnBytesFreed ){
  1422   1427         do{
  1423   1428           if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc);
  1424   1429         }while( (++p)<pEnd );
  1425   1430         return;
  1426   1431       }
  1427   1432       do{
................................................................................
  1449   1454         }else if( p->szMalloc ){
  1450   1455           sqlite3DbFree(db, p->zMalloc);
  1451   1456           p->szMalloc = 0;
  1452   1457         }
  1453   1458   
  1454   1459         p->flags = MEM_Undefined;
  1455   1460       }while( (++p)<pEnd );
  1456         -    db->mallocFailed = malloc_failed;
  1457   1461     }
  1458   1462   }
  1459   1463   
  1460   1464   /*
  1461   1465   ** Delete a VdbeFrame object and its contents. VdbeFrame objects are
  1462   1466   ** allocated by the OP_Program opcode in sqlite3VdbeExec().
  1463   1467   */
................................................................................
  1510   1514     */
  1511   1515     releaseMemArray(pMem, 8);
  1512   1516     p->pResultSet = 0;
  1513   1517   
  1514   1518     if( p->rc==SQLITE_NOMEM ){
  1515   1519       /* This happens if a malloc() inside a call to sqlite3_column_text() or
  1516   1520       ** sqlite3_column_text16() failed.  */
  1517         -    db->mallocFailed = 1;
         1521  +    sqlite3OomFault(db);
  1518   1522       return SQLITE_ERROR;
  1519   1523     }
  1520   1524   
  1521   1525     /* When the number of output rows reaches nRow, that means the
  1522   1526     ** listing has finished and sqlite3_step() should return SQLITE_DONE.
  1523   1527     ** nRow is the sum of the number of rows in the main program, plus
  1524   1528     ** the sum of the number of rows in all trigger subprograms encountered
................................................................................
  2503   2507     **     SQLITE_INTERRUPT
  2504   2508     **
  2505   2509     ** Then the internal cache might have been left in an inconsistent
  2506   2510     ** state.  We need to rollback the statement transaction, if there is
  2507   2511     ** one, or the complete transaction if there is no statement transaction.
  2508   2512     */
  2509   2513   
  2510         -  if( p->db->mallocFailed ){
         2514  +  if( db->mallocFailed ){
  2511   2515       p->rc = SQLITE_NOMEM;
  2512   2516     }
  2513   2517     if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag);
  2514   2518     closeAllCursors(p);
  2515   2519     if( p->magic!=VDBE_MAGIC_RUN ){
  2516   2520       return SQLITE_OK;
  2517   2521     }
................................................................................
  2664   2668       if( p->bIsReader ) db->nVdbeRead--;
  2665   2669       assert( db->nVdbeActive>=db->nVdbeRead );
  2666   2670       assert( db->nVdbeRead>=db->nVdbeWrite );
  2667   2671       assert( db->nVdbeWrite>=0 );
  2668   2672     }
  2669   2673     p->magic = VDBE_MAGIC_HALT;
  2670   2674     checkActiveVdbeCnt(db);
  2671         -  if( p->db->mallocFailed ){
         2675  +  if( db->mallocFailed ){
  2672   2676       p->rc = SQLITE_NOMEM;
  2673   2677     }
  2674   2678   
  2675   2679     /* If the auto-commit flag is set to true, then any locks that were held
  2676   2680     ** by connection db have now been released. Call sqlite3ConnectionUnlocked() 
  2677   2681     ** to invoke any required unlock-notify callbacks.
  2678   2682     */
................................................................................
  2701   2705   ** This function does not clear the VDBE error code or message, just
  2702   2706   ** copies them to the database handle.
  2703   2707   */
  2704   2708   int sqlite3VdbeTransferError(Vdbe *p){
  2705   2709     sqlite3 *db = p->db;
  2706   2710     int rc = p->rc;
  2707   2711     if( p->zErrMsg ){
  2708         -    u8 mallocFailed = db->mallocFailed;
         2712  +    db->bBenignMalloc++;
  2709   2713       sqlite3BeginBenignMalloc();
  2710   2714       if( db->pErr==0 ) db->pErr = sqlite3ValueNew(db);
  2711   2715       sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
  2712   2716       sqlite3EndBenignMalloc();
  2713         -    db->mallocFailed = mallocFailed;
         2717  +    db->bBenignMalloc--;
  2714   2718       db->errCode = rc;
  2715   2719     }else{
  2716   2720       sqlite3Error(db, rc);
  2717   2721     }
  2718   2722     return rc;
  2719   2723   }
  2720   2724   

Changes to src/vdbeblob.c.

   245    245         ** uses it to implement the blob_read(), blob_write() and 
   246    246         ** blob_bytes() functions.
   247    247         **
   248    248         ** The sqlite3_blob_close() function finalizes the vdbe program,
   249    249         ** which closes the b-tree cursor and (possibly) commits the 
   250    250         ** transaction.
   251    251         */
   252         -      static const int iLn = VDBE_OFFSET_LINENO(4);
          252  +      static const int iLn = VDBE_OFFSET_LINENO(2);
   253    253         static const VdbeOpList openBlob[] = {
   254         -                                    /* addr/ofst */
   255         -        /* {OP_Transaction, 0, 0, 0},  // 0/   inserted separately */
   256         -        {OP_TableLock, 0, 0, 0},       /* 1/0: Acquire a read or write lock */
   257         -        {OP_OpenRead, 0, 0, 0},        /* 2/1: Open a cursor */
   258         -        {OP_Variable, 1, 1, 0},        /* 3/2: Move ?1 into reg[1] */
   259         -        {OP_NotExists, 0, 8, 1},       /* 4/3: Seek the cursor */
   260         -        {OP_Column, 0, 0, 1},          /* 5/4  */
   261         -        {OP_ResultRow, 1, 0, 0},       /* 6/5  */
   262         -        {OP_Goto, 0, 3, 0},            /* 7/6  */
   263         -        {OP_Close, 0, 0, 0},           /* 8/7  */
   264         -        {OP_Halt, 0, 0, 0},            /* 9/8  */
          254  +        {OP_TableLock,      0, 0, 0},  /* 0: Acquire a read or write lock */
          255  +        {OP_OpenRead,       0, 0, 0},  /* 1: Open a cursor */
          256  +        {OP_Variable,       1, 1, 0},  /* 2: Move ?1 into reg[1] */
          257  +        {OP_NotExists,      0, 7, 1},  /* 3: Seek the cursor */
          258  +        {OP_Column,         0, 0, 1},  /* 4  */
          259  +        {OP_ResultRow,      1, 0, 0},  /* 5  */
          260  +        {OP_Goto,           0, 2, 0},  /* 6  */
          261  +        {OP_Close,          0, 0, 0},  /* 7  */
          262  +        {OP_Halt,           0, 0, 0},  /* 8  */
   265    263         };
   266    264         Vdbe *v = (Vdbe *)pBlob->pStmt;
   267    265         int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
   268    266         VdbeOp *aOp;
   269    267   
   270    268         sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, flags, 
   271    269                              pTab->pSchema->schema_cookie,

Changes to src/vdbemem.c.

   112    112   ** pMem->z into the new allocation.  pMem must be either a string or
   113    113   ** blob if bPreserve is true.  If bPreserve is false, any prior content
   114    114   ** in pMem->z is discarded.
   115    115   */
   116    116   SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
   117    117     assert( sqlite3VdbeCheckMemInvariants(pMem) );
   118    118     assert( (pMem->flags&MEM_RowSet)==0 );
          119  +  testcase( pMem->db==0 );
   119    120   
   120    121     /* If the bPreserve flag is set to true, then the memory cell must already
   121    122     ** contain a valid string or blob value.  */
   122    123     assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
   123    124     testcase( bPreserve && pMem->z==0 );
   124    125   
   125    126     assert( pMem->szMalloc==0
................................................................................
   715    716   ** empty boolean index.
   716    717   */
   717    718   void sqlite3VdbeMemSetRowSet(Mem *pMem){
   718    719     sqlite3 *db = pMem->db;
   719    720     assert( db!=0 );
   720    721     assert( (pMem->flags & MEM_RowSet)==0 );
   721    722     sqlite3VdbeMemRelease(pMem);
   722         -  pMem->zMalloc = sqlite3DbMallocRaw(db, 64);
          723  +  pMem->zMalloc = sqlite3DbMallocRawNN(db, 64);
   723    724     if( db->mallocFailed ){
   724    725       pMem->flags = MEM_Null;
   725    726       pMem->szMalloc = 0;
   726    727     }else{
   727    728       assert( pMem->zMalloc );
   728    729       pMem->szMalloc = sqlite3DbMallocSize(db, pMem->zMalloc);
   729    730       pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc, pMem->szMalloc);
................................................................................
  1377   1378     }
  1378   1379   #endif
  1379   1380   
  1380   1381     *ppVal = pVal;
  1381   1382     return rc;
  1382   1383   
  1383   1384   no_mem:
  1384         -  db->mallocFailed = 1;
         1385  +  sqlite3OomFault(db);
  1385   1386     sqlite3DbFree(db, zVal);
  1386   1387     assert( *ppVal==0 );
  1387   1388   #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  1388   1389     if( pCtx==0 ) sqlite3ValueFree(pVal);
  1389   1390   #else
  1390   1391     assert( pCtx==0 ); sqlite3ValueFree(pVal);
  1391   1392   #endif
................................................................................
  1436   1437   
  1437   1438     UNUSED_PARAMETER( argc );
  1438   1439     iSerial = sqlite3VdbeSerialType(argv[0], file_format, &nVal);
  1439   1440     nSerial = sqlite3VarintLen(iSerial);
  1440   1441     db = sqlite3_context_db_handle(context);
  1441   1442   
  1442   1443     nRet = 1 + nSerial + nVal;
  1443         -  aRet = sqlite3DbMallocRaw(db, nRet);
         1444  +  aRet = sqlite3DbMallocRawNN(db, nRet);
  1444   1445     if( aRet==0 ){
  1445   1446       sqlite3_result_error_nomem(context);
  1446   1447     }else{
  1447   1448       aRet[0] = nSerial+1;
  1448   1449       putVarint32(&aRet[1], iSerial);
  1449   1450       sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial);
  1450   1451       sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT);

Changes to src/vtab.c.

    45     45   
    46     46     sqlite3_mutex_enter(db->mutex);
    47     47     nName = sqlite3Strlen30(zName);
    48     48     if( sqlite3HashFind(&db->aModule, zName) ){
    49     49       rc = SQLITE_MISUSE_BKPT;
    50     50     }else{
    51     51       Module *pMod;
    52         -    pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1);
           52  +    pMod = (Module *)sqlite3DbMallocRawNN(db, sizeof(Module) + nName + 1);
    53     53       if( pMod ){
    54     54         Module *pDel;
    55     55         char *zCopy = (char *)(&pMod[1]);
    56     56         memcpy(zCopy, zName, nName+1);
    57     57         pMod->zName = zCopy;
    58     58         pMod->pModule = pModule;
    59     59         pMod->pAux = pAux;
    60     60         pMod->xDestroy = xDestroy;
    61     61         pMod->pEpoTab = 0;
    62     62         pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod);
    63     63         assert( pDel==0 || pDel==pMod );
    64     64         if( pDel ){
    65         -        db->mallocFailed = 1;
           65  +        sqlite3OomFault(db);
    66     66           sqlite3DbFree(db, pDel);
    67     67         }
    68     68       }
    69     69     }
    70     70     rc = sqlite3ApiExit(db, rc);
    71     71     if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux);
    72     72   
................................................................................
   435    435     else {
   436    436       Table *pOld;
   437    437       Schema *pSchema = pTab->pSchema;
   438    438       const char *zName = pTab->zName;
   439    439       assert( sqlite3SchemaMutexHeld(db, 0, pSchema) );
   440    440       pOld = sqlite3HashInsert(&pSchema->tblHash, zName, pTab);
   441    441       if( pOld ){
   442         -      db->mallocFailed = 1;
          442  +      sqlite3OomFault(db);
   443    443         assert( pTab==pOld );  /* Malloc must have failed inside HashInsert() */
   444    444         return;
   445    445       }
   446    446       pParse->pNewTable = 0;
   447    447     }
   448    448   }
   449    449   
................................................................................
   526    526     sCtx.pTab = pTab;
   527    527     sCtx.pVTable = pVTable;
   528    528     sCtx.pPrior = db->pVtabCtx;
   529    529     sCtx.bDeclared = 0;
   530    530     db->pVtabCtx = &sCtx;
   531    531     rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
   532    532     db->pVtabCtx = sCtx.pPrior;
   533         -  if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
          533  +  if( rc==SQLITE_NOMEM ) sqlite3OomFault(db);
   534    534     assert( sCtx.pTab==pTab );
   535    535   
   536    536     if( SQLITE_OK!=rc ){
   537    537       if( zErr==0 ){
   538    538         *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName);
   539    539       }else {
   540    540         *pzErr = sqlite3MPrintf(db, "%s", zErr);
................................................................................
  1084   1084     }
  1085   1085     n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]);
  1086   1086     apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n);
  1087   1087     if( apVtabLock ){
  1088   1088       pToplevel->apVtabLock = apVtabLock;
  1089   1089       pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab;
  1090   1090     }else{
  1091         -    pToplevel->db->mallocFailed = 1;
         1091  +    sqlite3OomFault(pToplevel->db);
  1092   1092     }
  1093   1093   }
  1094   1094   
  1095   1095   /*
  1096   1096   ** Check to see if virtual tale module pMod can be have an eponymous
  1097   1097   ** virtual table instance.  If it can, create one if one does not already
  1098   1098   ** exist. Return non-zero if the eponymous virtual table instance exists

Changes to src/where.c.

   939    939   
   940    940     TRACE_IDX_INPUTS(p);
   941    941     rc = pVtab->pModule->xBestIndex(pVtab, p);
   942    942     TRACE_IDX_OUTPUTS(p);
   943    943   
   944    944     if( rc!=SQLITE_OK ){
   945    945       if( rc==SQLITE_NOMEM ){
   946         -      pParse->db->mallocFailed = 1;
          946  +      sqlite3OomFault(pParse->db);
   947    947       }else if( !pVtab->zErrMsg ){
   948    948         sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc));
   949    949       }else{
   950    950         sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg);
   951    951       }
   952    952     }
   953    953     sqlite3_free(pVtab->zErrMsg);
................................................................................
  1731   1731   /*
  1732   1732   ** Increase the memory allocation for pLoop->aLTerm[] to be at least n.
  1733   1733   */
  1734   1734   static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){
  1735   1735     WhereTerm **paNew;
  1736   1736     if( p->nLSlot>=n ) return SQLITE_OK;
  1737   1737     n = (n+7)&~7;
  1738         -  paNew = sqlite3DbMallocRaw(db, sizeof(p->aLTerm[0])*n);
         1738  +  paNew = sqlite3DbMallocRawNN(db, sizeof(p->aLTerm[0])*n);
  1739   1739     if( paNew==0 ) return SQLITE_NOMEM;
  1740   1740     memcpy(paNew, p->aLTerm, sizeof(p->aLTerm[0])*p->nLSlot);
  1741   1741     if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFree(db, p->aLTerm);
  1742   1742     p->aLTerm = paNew;
  1743   1743     p->nLSlot = n;
  1744   1744     return SQLITE_OK;
  1745   1745   }
................................................................................
  2028   2028       }
  2029   2029       sqlite3DebugPrintf("    add: ");
  2030   2030       whereLoopPrint(pTemplate, pBuilder->pWC);
  2031   2031     }
  2032   2032   #endif
  2033   2033     if( p==0 ){
  2034   2034       /* Allocate a new WhereLoop to add to the end of the list */
  2035         -    *ppPrev = p = sqlite3DbMallocRaw(db, sizeof(WhereLoop));
         2035  +    *ppPrev = p = sqlite3DbMallocRawNN(db, sizeof(WhereLoop));
  2036   2036       if( p==0 ) return SQLITE_NOMEM;
  2037   2037       whereLoopInit(p);
  2038   2038       p->pNextLoop = 0;
  2039   2039     }else{
  2040   2040       /* We will be overwriting WhereLoop p[].  But before we do, first
  2041   2041       ** go through the rest of the list and delete any other entries besides
  2042   2042       ** p[] that are also supplated by pTemplate */
................................................................................
  3525   3525     }else{
  3526   3526       nOrderBy = pWInfo->pOrderBy->nExpr;
  3527   3527     }
  3528   3528   
  3529   3529     /* Allocate and initialize space for aTo, aFrom and aSortCost[] */
  3530   3530     nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
  3531   3531     nSpace += sizeof(LogEst) * nOrderBy;
  3532         -  pSpace = sqlite3DbMallocRaw(db, nSpace);
         3532  +  pSpace = sqlite3DbMallocRawNN(db, nSpace);
  3533   3533     if( pSpace==0 ) return SQLITE_NOMEM;
  3534   3534     aTo = (WherePath*)pSpace;
  3535   3535     aFrom = aTo+mxChoice;
  3536   3536     memset(aFrom, 0, sizeof(aFrom[0]));
  3537   3537     pX = (WhereLoop**)(aFrom+mxChoice);
  3538   3538     for(ii=mxChoice*2, pFrom=aTo; ii>0; ii--, pFrom++, pX += nLoop){
  3539   3539       pFrom->aLoop = pX;

Changes to src/wherecode.c.

   491    491     /* Figure out how many memory cells we will need then allocate them.
   492    492     */
   493    493     regBase = pParse->nMem + 1;
   494    494     nReg = pLoop->u.btree.nEq + nExtraReg;
   495    495     pParse->nMem += nReg;
   496    496   
   497    497     zAff = sqlite3DbStrDup(pParse->db,sqlite3IndexAffinityStr(pParse->db,pIdx));
   498         -  if( !zAff ){
   499         -    pParse->db->mallocFailed = 1;
   500         -  }
          498  +  assert( zAff!=0 || pParse->db->mallocFailed );
   501    499   
   502    500     if( nSkip ){
   503    501       int iIdxCur = pLevel->iIdxCur;
   504    502       sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur);
   505    503       VdbeCoverageIf(v, bRev==0);
   506    504       VdbeCoverageIf(v, bRev!=0);
   507    505       VdbeComment((v, "begin skip-scan on %s", pIdx->zName));

Changes to src/whereexpr.c.

    60     60   static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){
    61     61     WhereTerm *pTerm;
    62     62     int idx;
    63     63     testcase( wtFlags & TERM_VIRTUAL );
    64     64     if( pWC->nTerm>=pWC->nSlot ){
    65     65       WhereTerm *pOld = pWC->a;
    66     66       sqlite3 *db = pWC->pWInfo->pParse->db;
    67         -    pWC->a = sqlite3DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 );
           67  +    pWC->a = sqlite3DbMallocRawNN(db, sizeof(pWC->a[0])*pWC->nSlot*2 );
    68     68       if( pWC->a==0 ){
    69     69         if( wtFlags & TERM_DYNAMIC ){
    70     70           sqlite3ExprDelete(db, p);
    71     71         }
    72     72         pWC->a = pOld;
    73     73         return 0;
    74     74       }
................................................................................
   545    545     indexable = ~(Bitmask)0;
   546    546     chngToIN = ~(Bitmask)0;
   547    547     for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){
   548    548       if( (pOrTerm->eOperator & WO_SINGLE)==0 ){
   549    549         WhereAndInfo *pAndInfo;
   550    550         assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 );
   551    551         chngToIN = 0;
   552         -      pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo));
          552  +      pAndInfo = sqlite3DbMallocRawNN(db, sizeof(*pAndInfo));
   553    553         if( pAndInfo ){
   554    554           WhereClause *pAndWC;
   555    555           WhereTerm *pAndTerm;
   556    556           int j;
   557    557           Bitmask b = 0;
   558    558           pOrTerm->u.pAndInfo = pAndInfo;
   559    559           pOrTerm->wtFlags |= TERM_ANDINFO;
   560    560           pOrTerm->eOperator = WO_AND;
   561    561           pAndWC = &pAndInfo->wc;
   562    562           sqlite3WhereClauseInit(pAndWC, pWC->pWInfo);
   563    563           sqlite3WhereSplit(pAndWC, pOrTerm->pExpr, TK_AND);
   564    564           sqlite3WhereExprAnalyze(pSrc, pAndWC);
   565    565           pAndWC->pOuter = pWC;
   566         -        testcase( db->mallocFailed );
   567    566           if( !db->mallocFailed ){
   568    567             for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){
   569    568               assert( pAndTerm->pExpr );
   570    569               if( allowedOp(pAndTerm->pExpr->op) ){
   571    570                 b |= sqlite3WhereGetMask(&pWInfo->sMaskSet, pAndTerm->leftCursor);
   572    571               }
   573    572             }

Changes to test/fuzzer1.test.

    19     19   
    20     20   ifcapable !vtab {
    21     21     finish_test
    22     22     return
    23     23   }
    24     24   
    25     25   set ::testprefix fuzzer1
    26         -
    27     26   load_static_extension db fuzzer
    28     27   
    29     28   # Check configuration errors.
    30     29   #
    31     30   do_catchsql_test fuzzer1-1.1 {
    32     31     CREATE VIRTUAL TABLE f USING fuzzer;
    33     32   } {1 {fuzzer: wrong number of CREATE VIRTUAL TABLE arguments}}
................................................................................
  1644   1643     DELETE FROM "fuzzer [x] rules table";
  1645   1644     INSERT INTO "fuzzer [x] rules table" VALUES((1<<32)+100, 'x', 'y', 2);
  1646   1645   } 
  1647   1646   do_catchsql_test 5.5.4 {
  1648   1647     CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
  1649   1648   } {1 {fuzzer: ruleset must be between 0 and 2147483647}}
  1650   1649   
  1651         -#-------------------------------------------------------------------------
  1652         -# This test uses a fuzzer table with many rules. There is one rule to
  1653         -# map each possible two character string, where characters are lower-case
  1654         -# letters used in the English language, to all other possible two character
  1655         -# strings. In total, (26^4)-(26^2) mappings (the subtracted term represents
  1656         -# the no-op mappings discarded automatically by the fuzzer).
  1657         -#
  1658         -#
  1659         -do_execsql_test 6.1.1 {
  1660         -  DROP TABLE IF EXISTS x1;
  1661         -  DROP TABLE IF EXISTS x1_rules;
  1662         -  CREATE TABLE x1_rules(ruleset, cFrom, cTo, cost);
  1663         -}
  1664         -puts "This test is slow - perhaps around 7 seconds on an average pc"
  1665         -do_test 6.1.2 {
  1666         -  set LETTERS {a b c d e f g h i j k l m n o p q r s t u v w x y z}
  1667         -  set cost 1
  1668         -  db transaction {
  1669         -    foreach c1 $LETTERS { 
  1670         -      foreach c2 $LETTERS { 
  1671         -        foreach c3 $LETTERS { 
  1672         -          foreach c4 $LETTERS { 
  1673         -            db eval {INSERT INTO x1_rules VALUES(0, $c1||$c2, $c3||$c4, $cost)}
  1674         -            set cost [expr ($cost%1000) + 1]
  1675         -          }
  1676         -        }
  1677         -      }
  1678         -    }
  1679         -    db eval {UPDATE x1_rules SET cost = 20 WHERE cost<20 AND cFrom!='xx'}
  1680         -  }
  1681         -} {}
  1682         -
  1683         -do_execsql_test 6.2 {
  1684         -  SELECT count(*) FROM x1_rules WHERE cTo!=cFrom;
  1685         -} [expr 26*26*26*26 - 26*26]
  1686         -
  1687         -do_execsql_test 6.2.1 {
  1688         -  CREATE VIRTUAL TABLE x1 USING fuzzer(x1_rules);
  1689         -  SELECT word FROM x1 WHERE word MATCH 'xx' LIMIT 10;
  1690         -} {xx hw hx hy hz ia ib ic id ie}
  1691         -do_execsql_test 6.2.2 {
  1692         -  SELECT cTo FROM x1_rules WHERE cFrom='xx' 
  1693         -  ORDER BY cost asc, rowid asc LIMIT 9;
  1694         -} {hw hx hy hz ia ib ic id ie}
  1695         -
  1696   1650   #-------------------------------------------------------------------------
  1697   1651   # Test using different types of quotes with CREATE VIRTUAL TABLE 
  1698   1652   # arguments.
  1699   1653   #
  1700   1654   do_execsql_test 7.1 {
  1701   1655     CREATE TABLE [x2 "rules] (a, b, c, d);
  1702   1656     INSERT INTO [x2 "rules] VALUES(0, 'a', 'b', 5);

Added test/fuzzer2.test.

            1  +# 2016 February 4
            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  +# The focus of the tests is the word-fuzzer virtual table. The tests
           12  +# in this file are slower than those in fuzzer1.test. So this file does
           13  +# not run as part of veryquick.test etc.
           14  +#
           15  +
           16  +set testdir [file dirname $argv0]
           17  +source $testdir/tester.tcl
           18  +
           19  +ifcapable !vtab {
           20  +  finish_test
           21  +  return
           22  +}
           23  +
           24  +set ::testprefix fuzzer2
           25  +load_static_extension db fuzzer
           26  +
           27  +#-------------------------------------------------------------------------
           28  +# This test uses a fuzzer table with many rules. There is one rule to
           29  +# map each possible two character string, where characters are lower-case
           30  +# letters used in the English language, to all other possible two character
           31  +# strings. In total, (26^4)-(26^2) mappings (the subtracted term represents
           32  +# the no-op mappings discarded automatically by the fuzzer).
           33  +#
           34  +#
           35  +do_execsql_test 1.1.1 {
           36  +  DROP TABLE IF EXISTS x1;
           37  +  DROP TABLE IF EXISTS x1_rules;
           38  +  CREATE TABLE x1_rules(ruleset, cFrom, cTo, cost);
           39  +}
           40  +puts "This test is slow - perhaps around 7 seconds on an average pc"
           41  +do_test 1.1.2 {
           42  +  set LETTERS {a b c d e f g h i j k l m n o p q r s t u v w x y z}
           43  +  set cost 1
           44  +  db transaction {
           45  +    foreach c1 $LETTERS { 
           46  +      foreach c2 $LETTERS { 
           47  +        foreach c3 $LETTERS { 
           48  +          foreach c4 $LETTERS { 
           49  +            db eval {INSERT INTO x1_rules VALUES(0, $c1||$c2, $c3||$c4, $cost)}
           50  +            set cost [expr ($cost%1000) + 1]
           51  +          }
           52  +        }
           53  +      }
           54  +    }
           55  +    db eval {UPDATE x1_rules SET cost = 20 WHERE cost<20 AND cFrom!='xx'}
           56  +  }
           57  +} {}
           58  +
           59  +do_execsql_test 1.2 {
           60  +  SELECT count(*) FROM x1_rules WHERE cTo!=cFrom;
           61  +} [expr 26*26*26*26 - 26*26]
           62  +
           63  +do_execsql_test 1.2.1 {
           64  +  CREATE VIRTUAL TABLE x1 USING fuzzer(x1_rules);
           65  +  SELECT word FROM x1 WHERE word MATCH 'xx' LIMIT 10;
           66  +} {xx hw hx hy hz ia ib ic id ie}
           67  +do_execsql_test 1.2.2 {
           68  +  SELECT cTo FROM x1_rules WHERE cFrom='xx' 
           69  +  ORDER BY cost asc, rowid asc LIMIT 9;
           70  +} {hw hx hy hz ia ib ic id ie}
           71  +
           72  +finish_test

Changes to test/json101.test.

   337    337     7.7  0  char(0x20,0x09,0x0a,0x0c,0x0d,0x20)
   338    338   } {
   339    339     do_execsql_test json-$tn.1 \
   340    340       "SELECT json_valid(printf('%s{%s\"x\"%s:%s9%s}%s',
   341    341            $::ws,$::ws,$::ws,$::ws,$::ws,$::ws));" \
   342    342     $isvalid
   343    343   }
          344  +
          345  +# Ticket https://www.sqlite.org/src/info/ad2559db380abf8e
          346  +# Control characters must be escaped in JSON strings.
          347  +#
          348  +do_execsql_test json-8.1 {
          349  +  DROP TABLE IF EXISTS t8;
          350  +  CREATE TABLE t8(a,b);
          351  +  INSERT INTO t8(a) VALUES('abc' || char(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35) || 'xyz');
          352  +  UPDATE t8 SET b=json_array(a);
          353  +  SELECT b FROM t8;
          354  +} {{["abc\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\"#xyz"]}}
          355  +do_execsql_test json-8.2 {
          356  +  SELECT a=json_extract(b,'$[0]') FROM t8;
          357  +} {1}
          358  +
   344    359   
   345    360   finish_test

Changes to test/mmap1.test.

    24     24     db_enter $db
    25     25     array set stats [btree_pager_stats $bt]
    26     26     db_leave $db
    27     27     # puts [array get stats]
    28     28     return $stats(read)
    29     29   }
    30     30   
           31  +# Return a Tcl script that registers a user-defined scalar function 
           32  +# named rblob() with database handle $dbname. The function returns a
           33  +# sequence of pseudo-random blobs based on seed value $seed.
           34  +#
    31     35   proc register_rblob_code {dbname seed} {
    32     36     return [subst -nocommands {
    33     37       set ::rcnt $seed
    34     38       proc rblob {n} {
    35     39         set ::rcnt [expr (([set ::rcnt] << 3) + [set ::rcnt] + 456) & 0xFFFFFFFF]
    36     40         set str [format %.8x [expr [set ::rcnt] ^ 0xbdf20da3]]
    37     41         string range [string repeat [set str] [expr [set n]/4]] 1 [set n]
    38     42       }
    39     43       $dbname func rblob rblob
    40     44     }]
    41     45   }
           46  +
    42     47   
    43     48   # For cases 1.1 and 1.4, the number of pages read using xRead() is 4 on
    44     49   # unix and 9 on windows. The difference is that windows only ever maps
    45     50   # an integer number of OS pages (i.e. creates mappings that are a multiple
    46     51   # of 4KB in size). Whereas on unix any sized mapping may be created.
    47     52   #
    48     53   foreach {t mmap_size nRead c2init} {
................................................................................
   265    270     sqlite3_column_text $::STMT 0
   266    271   } $bbb
   267    272   
   268    273   do_test 5.5 {
   269    274     sqlite3_finalize $::STMT
   270    275   } SQLITE_OK
   271    276   
   272         -#-------------------------------------------------------------------------
   273         -# Test various mmap_size settings.
   274         -#
   275         -foreach {tn1 mmap1 mmap2} {
   276         -     1 6144       167773
   277         -     2 18432      140399
   278         -     3 43008      401302
   279         -     4 92160      253899
   280         -     5 190464          2
   281         -     6 387072     752431
   282         -     7 780288     291143
   283         -     8 1566720    594306
   284         -     9 3139584    829137
   285         -     10 6285312   793963
   286         -     11 12576768 1015590
   287         -} {
   288         -  do_multiclient_test tn {
   289         -    sql1 {
   290         -      CREATE TABLE t1(a PRIMARY KEY);
   291         -      CREATE TABLE t2(x);
   292         -      INSERT INTO t2 VALUES('');
   293         -    }
   294         -
   295         -    code1 [register_rblob_code db  0]
   296         -    code2 [register_rblob_code db2 444]
   297         -
   298         -    sql1 "PRAGMA mmap_size = $mmap1"
   299         -    sql2 "PRAGMA mmap_size = $mmap2"
   300         -
   301         -    do_test $tn1.$tn {
   302         -      for {set i 1} {$i <= 100} {incr i} {
   303         -        if {$i % 2} {
   304         -          set c1 sql1
   305         -            set c2 sql2
   306         -        } else {
   307         -          set c1 sql2
   308         -            set c2 sql1
   309         -        }
   310         -
   311         -        $c1 {
   312         -          INSERT INTO t1 VALUES( rblob(5000) );
   313         -          UPDATE t2 SET x = (SELECT md5sum(a) FROM t1);
   314         -        }
   315         -
   316         -        set res [$c2 {
   317         -            SELECT count(*) FROM t1;
   318         -            SELECT x == (SELECT md5sum(a) FROM t1) FROM t2;
   319         -            PRAGMA integrity_check;
   320         -        }]
   321         -        if {$res != [list $i 1 ok]} {
   322         -          do_test $tn1.$tn.$i {
   323         -            set ::res
   324         -          } [list $i 1 ok]
   325         -        }
   326         -      }
   327         -      set res 1
   328         -    } {1}
   329         -  }
   330         -}
   331         -
   332    277   
   333    278   finish_test

Added test/mmap4.test.

            1  +# 2016 February 04
            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  +# This file tests the effect of the mmap() or mremap() system calls 
           13  +# returning an error on the library. 
           14  +#
           15  +# If either mmap() or mremap() fails, SQLite should log an error 
           16  +# message, then continue accessing the database using read() and 
           17  +# write() exclusively.
           18  +# 
           19  +set testdir [file dirname $argv0]
           20  +source $testdir/tester.tcl
           21  +ifcapable !mmap {
           22  +  finish_test
           23  +  return
           24  +}
           25  +source $testdir/lock_common.tcl
           26  +set testprefix mmap4
           27  +
           28  +# Return a Tcl script that registers a user-defined scalar function 
           29  +# named rblob() with database handle $dbname. The function returns a
           30  +# sequence of pseudo-random blobs based on seed value $seed.
           31  +#
           32  +proc register_rblob_code {dbname seed} {
           33  +  return [subst -nocommands {
           34  +    set ::rcnt $seed
           35  +    proc rblob {n} {
           36  +      set ::rcnt [expr (([set ::rcnt] << 3) + [set ::rcnt] + 456) & 0xFFFFFFFF]
           37  +      set str [format %.8x [expr [set ::rcnt] ^ 0xbdf20da3]]
           38  +      string range [string repeat [set str] [expr [set n]/4]] 1 [set n]
           39  +    }
           40  +    $dbname func rblob rblob
           41  +  }]
           42  +}
           43  +
           44  +#-------------------------------------------------------------------------
           45  +# Test various mmap_size settings.
           46  +#
           47  +foreach {tn1 mmap1 mmap2} {
           48  +     1 6144       167773
           49  +     2 18432      140399
           50  +     3 43008      401302
           51  +     4 92160      253899
           52  +     5 190464          2
           53  +     6 387072     752431
           54  +     7 780288     291143
           55  +     8 1566720    594306
           56  +     9 3139584    829137
           57  +     10 6285312   793963
           58  +     11 12576768 1015590
           59  +} {
           60  +  do_multiclient_test tn {
           61  +    sql1 {
           62  +      CREATE TABLE t1(a PRIMARY KEY);
           63  +      CREATE TABLE t2(x);
           64  +      INSERT INTO t2 VALUES('');
           65  +    }
           66  +
           67  +    code1 [register_rblob_code db  0]
           68  +    code2 [register_rblob_code db2 444]
           69  +
           70  +    sql1 "PRAGMA mmap_size = $mmap1"
           71  +    sql2 "PRAGMA mmap_size = $mmap2"
           72  +
           73  +    do_test $tn1.$tn {
           74  +      for {set i 1} {$i <= 100} {incr i} {
           75  +        if {$i % 2} {
           76  +          set c1 sql1
           77  +            set c2 sql2
           78  +        } else {
           79  +          set c1 sql2
           80  +            set c2 sql1
           81  +        }
           82  +
           83  +        $c1 {
           84  +          INSERT INTO t1 VALUES( rblob(5000) );
           85  +          UPDATE t2 SET x = (SELECT md5sum(a) FROM t1);
           86  +        }
           87  +
           88  +        set res [$c2 {
           89  +            SELECT count(*) FROM t1;
           90  +            SELECT x == (SELECT md5sum(a) FROM t1) FROM t2;
           91  +            PRAGMA integrity_check;
           92  +        }]
           93  +        if {$res != [list $i 1 ok]} {
           94  +          do_test $tn1.$tn.$i {
           95  +            set ::res
           96  +          } [list $i 1 ok]
           97  +        }
           98  +      }
           99  +      set res 1
          100  +    } {1}
          101  +  }
          102  +}
          103  +
          104  +finish_test

Changes to test/permutations.test.

   109    109     speed1.test speed1p.test speed2.test speed3.test speed4.test 
   110    110     speed4p.test sqllimits1.test tkt2686.test thread001.test thread002.test
   111    111     thread003.test thread004.test thread005.test trans2.test vacuum3.test 
   112    112     incrvacuum_ioerr.test autovacuum_crash.test btree8.test shared_err.test
   113    113     vtab_err.test walslow.test walcrash.test walcrash3.test
   114    114     walthread.test rtree3.test indexfault.test securedel2.test
   115    115     sort3.test sort4.test fts4growth.test fts4growth2.test
   116         -  bigsort.test rbu.test
          116  +  bigsort.test rbu.test walprotocol.test mmap4.test fuzzer2.test
          117  +  walcrash2.test e_fkey.test backup.test
          118  +
          119  +  fts4merge.test fts4merge2.test fts4merge4.test fts4check.test
          120  +  fts3cov.test fts3snippet.test fts3corrupt2.test fts3an.test
          121  +  fts3defer.test fts4langid.test fts3sort.test fts5unicode.test
          122  +
          123  +  rtree4.test
   117    124   }]
   118    125   if {[info exists ::env(QUICKTEST_INCLUDE)]} {
   119    126     set allquicktests [concat $allquicktests $::env(QUICKTEST_INCLUDE)]
   120    127   }
   121    128   if {[info exists ::env(QUICKTEST_OMIT)]} {
   122    129     foreach x [split $::env(QUICKTEST_OMIT) ,] {
   123    130       regsub -all \\y$x\\y $allquicktests {} allquicktests
................................................................................
   146    153   lappend ::testsuitelist xxx
   147    154   
   148    155   test_suite "veryquick" -prefix "" -description {
   149    156     "Very" quick test suite. Runs in minutes on a workstation.
   150    157     This test suite is the same as the "quick" tests, except that some files
   151    158     that test malloc and IO errors are omitted.
   152    159   } -files [
   153         -  test_set $allquicktests -exclude *malloc* *ioerr* *fault* *bigfile*
          160  +  test_set $allquicktests -exclude *malloc* *ioerr* *fault* *bigfile* *_err*
   154    161   ]
   155    162   
   156    163   test_suite "extraquick" -prefix "" -description {
   157    164     "Extra" quick test suite. Runs in a few minutes on a workstation.
   158    165     This test suite is the same as the "veryquick" tests, except that
   159    166     slower tests are omitted.
   160    167   } -files [
   161         -  test_set $allquicktests -exclude *malloc* *ioerr* *fault* *bigfile* \
          168  +  test_set $allquicktests -exclude *malloc* *ioerr* *fault* *bigfile* *_err* \
   162    169        wal3.test fts4merge* sort2.test mmap1.test walcrash* \
   163    170        percentile.test where8m.test walcksum.test savepoint3.test \
   164    171        fuzzer1.test fuzzer3.test fts3expr3.test
   165    172   ]
   166    173   
   167    174   test_suite "mmap" -prefix "mm-" -description {
   168    175     Similar to veryquick. Except with memory mapping enabled.
................................................................................
   172    179     test_set $allquicktests -exclude *malloc* *ioerr* *fault* -include malloc.test
   173    180   ]
   174    181   
   175    182   test_suite "valgrind" -prefix "" -description {
   176    183     Run the "veryquick" test suite with a couple of multi-process tests (that
   177    184     fail under valgrind) omitted.
   178    185   } -files [
   179         -  test_set $allquicktests -exclude *malloc* *ioerr* *fault* wal.test \
          186  +  test_set $allquicktests -exclude *malloc* *ioerr* *fault* *_err* wal.test \
   180    187                 shell*.test crash8.test atof1.test selectG.test \
   181    188                 tkt-fc62af4523.test numindex1.test
   182    189   ] -initialize {
   183    190     set ::G(valgrind) 1
   184    191   } -shutdown {
   185    192     unset -nocomplain ::G(valgrind)
   186    193   }
   187    194   
   188    195   test_suite "valgrind-nolookaside" -prefix "" -description {
   189    196     Run the "veryquick" test suite with a couple of multi-process tests (that
   190    197     fail under valgrind) omitted.
   191    198   } -files [
   192         -  test_set $allquicktests -exclude *malloc* *ioerr* *fault* wal.test atof1.test
          199  +  test_set $allquicktests -exclude *malloc* *ioerr* *fault* *_err* \
          200  +      wal.test atof1.test
   193    201   ] -initialize {
   194    202     set ::G(valgrind) 1
   195    203     catch {db close}
   196    204     sqlite3_shutdown
   197    205     sqlite3_config_lookaside 0 0
   198    206     sqlite3_initialize
   199    207     autoinstall_test_functions
................................................................................
   262    270   ]
   263    271   
   264    272   test_suite "nofaultsim" -prefix "" -description {
   265    273     "Very" quick test suite. Runs in less than 5 minutes on a workstation. 
   266    274     This test suite is the same as the "quick" tests, except that some files
   267    275     that test malloc and IO errors are omitted.
   268    276   } -files [
   269         -  test_set $allquicktests -exclude *malloc* *ioerr* *fault*
          277  +  test_set $allquicktests -exclude *malloc* *ioerr* *fault* *_err*
   270    278   ] -initialize {
   271    279     catch {db close}
   272    280     sqlite3_shutdown
   273    281     install_malloc_faultsim 0
   274    282     sqlite3_initialize
   275    283     autoinstall_test_functions
   276    284   } -shutdown {

Changes to test/pragma.test.

   182    182     execsql {
   183    183       PRAGMA synchronous=NORMAL;
   184    184       PRAGMA cache_size;
   185    185       PRAGMA default_cache_size;
   186    186       PRAGMA synchronous;
   187    187     }
   188    188   } {123 123 1}
   189         -do_test pragma-1.11 {
          189  +do_test pragma-1.11.1 {
          190  +  execsql {
          191  +    PRAGMA synchronous=EXTRA;
          192  +    PRAGMA cache_size;
          193  +    PRAGMA default_cache_size;
          194  +    PRAGMA synchronous;
          195  +  }
          196  +} {123 123 3}
          197  +do_test pragma-1.11.2 {
   190    198     execsql {
   191    199       PRAGMA synchronous=FULL;
   192    200       PRAGMA cache_size;
   193    201       PRAGMA default_cache_size;
   194    202       PRAGMA synchronous;
   195    203     }
   196    204   } {123 123 2}
................................................................................
   220    228     }
   221    229   } {2}
   222    230   do_test pragma-1.14.1 {
   223    231     execsql {
   224    232       PRAGMA synchronous=4;
   225    233       PRAGMA synchronous;
   226    234     }
   227         -} {0}
          235  +} {4}
   228    236   do_test pragma-1.14.2 {
   229    237     execsql {
   230    238       PRAGMA synchronous=3;
   231    239       PRAGMA synchronous;
   232    240     }
   233         -} {0}
          241  +} {3}
   234    242   do_test pragma-1.14.3 {
          243  +  execsql {
          244  +    PRAGMA synchronous=8;
          245  +    PRAGMA synchronous;
          246  +  }
          247  +} {0}
          248  +do_test pragma-1.14.4 {
   235    249     execsql {
   236    250       PRAGMA synchronous=10;
   237    251       PRAGMA synchronous;
   238    252     }
   239    253   } {2}
   240    254   } ;# ifcapable pager_pragmas
   241    255   

Name change from test/savepoint3.test to test/savepointfault.test.

     5      5   #
     6      6   #    May you do good and not evil.
     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   #
    12         -# $Id: savepoint3.test,v 1.5 2009/06/05 17:09:12 drh Exp $
    13     12   
    14     13   set testdir [file dirname $argv0]
    15     14   source $testdir/tester.tcl
    16     15   
    17     16   source $testdir/malloc_common.tcl
    18     17   
    19         -do_malloc_test savepoint3-1 -sqlprep {
           18  +set testprefix savepointfault
           19  +
           20  +do_malloc_test 1 -sqlprep {
    20     21     CREATE TABLE t1(a, b, c);
    21     22     INSERT INTO t1 VALUES(1, 2, 3);
    22     23   } -sqlbody {
    23     24     SAVEPOINT one;
    24     25       INSERT INTO t1 VALUES(4, 5, 6);
    25     26       SAVEPOINT two;
    26     27         DELETE FROM t1;
    27     28       ROLLBACK TO two;
    28     29     RELEASE one;
    29     30   }
    30     31   
    31         -do_malloc_test savepoint3-2 -sqlprep {
           32  +do_malloc_test 2 -sqlprep {
    32     33     PRAGMA cache_size = 10;
    33     34     CREATE TABLE t1(a, b, c);
    34     35     INSERT INTO t1 VALUES(randstr(400,400), randstr(400,400), randstr(400,400));
    35     36     INSERT INTO t1 SELECT 
    36     37       randstr(400,400), randstr(400,400), randstr(400,400) FROM t1;
    37     38     INSERT INTO t1 
    38     39       SELECT randstr(400,400), randstr(400,400), randstr(400,400) FROM t1;
................................................................................
    55     56       SAVEPOINT two;
    56     57         DELETE FROM t1 WHERE rowid > 10;
    57     58       ROLLBACK TO two;
    58     59     ROLLBACK TO one;
    59     60     RELEASE one;
    60     61   }
    61     62   
    62         -do_ioerr_test savepoint3.3 -sqlprep {
           63  +do_ioerr_test 3 -sqlprep {
    63     64     CREATE TABLE t1(a, b, c);
    64     65     INSERT INTO t1 VALUES(1, randstr(1000,1000), randstr(1000,1000));
    65     66     INSERT INTO t1 VALUES(2, randstr(1000,1000), randstr(1000,1000));
    66     67   } -sqlbody {
    67     68     BEGIN;
    68     69       UPDATE t1 SET a = 3 WHERE a = 1;
    69     70       SAVEPOINT one;
................................................................................
    75     76       RELEASE one;
    76     77     }
    77     78   }
    78     79   
    79     80   # The following test does a really big savepoint rollback. One involving
    80     81   # more than 4000 pages. The idea is to get a specific sqlite3BitvecSet()
    81     82   # operation in pagerPlaybackSavepoint() to fail.
    82         -#do_malloc_test savepoint3-4 -sqlprep {
           83  +#do_malloc_test 4 -sqlprep {
    83     84   #  BEGIN;
    84     85   #    CREATE TABLE t1(a, b);
    85     86   #    CREATE INDEX i1 ON t1(a);
    86     87   #    CREATE INDEX i2 ON t1(b);
    87     88   #    INSERT INTO t1 VALUES(randstr(500,500), randstr(500,500));        --     1
    88     89   #    INSERT INTO t1 VALUES(randstr(500,500), randstr(500,500));        --     2
    89     90   #    INSERT INTO t1 SELECT randstr(500,500), randstr(500,500) FROM t1; --     4
................................................................................
   103    104   #} -sqlbody {
   104    105   #    ROLLBACK TO abc;
   105    106   #}
   106    107   
   107    108   
   108    109   # Cause a specific malloc in savepoint rollback code to fail.
   109    110   #
   110         -do_malloc_test savepoint3-4 -start 7 -sqlprep {
          111  +do_malloc_test 4 -start 7 -sqlprep {
   111    112     PRAGMA auto_vacuum = incremental;
   112    113     PRAGMA cache_size = 1000;
   113    114   
   114    115     CREATE TABLE t1(a, b);
   115    116     CREATE TABLE t2(a, b);
   116    117     CREATE TABLE t3(a, b);
   117    118     INSERT INTO t1 VALUES(1, randstr(500,500));

Changes to test/sort.test.

   487    487     SELECT a, b FROM t10 ORDER BY a;
   488    488   } [db eval {SELECT a, b FROM t10 ORDER BY a, b}]
   489    489   do_execsql_test sort-13.3 {
   490    490     PRAGMA cache_size = 5;
   491    491     SELECT a, b FROM t10 ORDER BY a;
   492    492   } [db eval {SELECT a, b FROM t10 ORDER BY a, b}]
   493    493   
   494         -#-------------------------------------------------------------------------
   495         -# Sort some large ( > 4KiB) records.
   496         -#
   497         -proc cksum {x} {
   498         -  set i1 1
   499         -  set i2 2
   500         -  binary scan $x c* L
   501         -  foreach {a b} $L {
   502         -    set i1 [expr (($i2<<3) + $a) & 0x7FFFFFFF]
   503         -    set i2 [expr (($i1<<3) + $b) & 0x7FFFFFFF]
   504         -  }
   505         -  list $i1 $i2
   506         -}
   507         -db func cksum cksum
   508         -
   509         -do_execsql_test sort-14.0 {
   510         -  PRAGMA cache_size = 5;
   511         -  CREATE TABLE t11(a, b);
   512         -  INSERT INTO t11 VALUES(randomblob(5000), NULL);
   513         -  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --2
   514         -  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --3
   515         -  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --4
   516         -  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --5
   517         -  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --6
   518         -  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --7
   519         -  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --8
   520         -  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --9
   521         -  UPDATE t11 SET b = cksum(a);
   522         -}
   523         -
   524         -foreach {tn mmap_limit} {
   525         -  1 0
   526         -  2 1000000
   527         -} {
   528         -  do_test sort-14.$tn {
   529         -    sqlite3_test_control SQLITE_TESTCTRL_SORTER_MMAP db $mmap_limit
   530         -    set prev ""
   531         -    db eval { SELECT * FROM t11 ORDER BY b } {
   532         -      if {$b != [cksum $a]} {error "checksum failed"}
   533         -      if {[string compare $b $prev] < 0} {error "sort failed"}
   534         -      set prev $b
   535         -    }
   536         -    set {} {}
   537         -  } {}
   538         -}
   539         -
   540    494   #-------------------------------------------------------------------------
   541    495   #
   542    496   foreach {tn mmap_limit nWorker tmpstore coremutex fakeheap softheaplimit} {
   543    497             1          0       3     file      true    false             0
   544    498             2          0       3     file      true     true             0
   545    499             3          0       0     file      true    false             0
   546    500             4    1000000       3     file      true    false             0

Changes to test/sort2.test.

    27     27     1 { }
    28     28     2 {
    29     29       catch { db close }
    30     30       reset_db
    31     31       catch { db eval {PRAGMA threads=7} }
    32     32     }
    33     33   } {
    34         -
    35     34     eval $script
    36     35   
    37     36     do_execsql_test $tn.1 {
    38     37       PRAGMA cache_size = 5;
    39     38       WITH r(x,y) AS (
    40     39         SELECT 1, randomblob(100)
    41     40         UNION ALL
................................................................................
    63     62     
    64     63     do_execsql_test $tn.2.3 {
    65     64       CREATE UNIQUE INDEX i2 ON t1(a);
    66     65     }
    67     66     
    68     67     do_execsql_test $tn.2.4 { PRAGMA integrity_check } {ok}
    69     68     
    70         -  do_execsql_test $tn.3 {
    71         -    PRAGMA cache_size = 5;
    72         -    WITH r(x,y) AS (
    73         -      SELECT 1, randomblob(100)
    74         -      UNION ALL
    75         -      SELECT x+1, randomblob(100) FROM r
    76         -      LIMIT 1000000
    77         -    )
    78         -    SELECT count(x), length(y) FROM r GROUP BY (x%5)
    79         -  } {
    80         -    200000 100 200000 100 200000 100 200000 100 200000 100
           69  +  # Because it uses so much data, this test can take 12-13 seconds even on
           70  +  # a modern workstation. So it is omitted from "veryquick" and other
           71  +  # permutations.test tests.
           72  +  if {[isquick]==0} {
           73  +    do_execsql_test $tn.3 {
           74  +      PRAGMA cache_size = 5;
           75  +      WITH r(x,y) AS (
           76  +          SELECT 1, randomblob(100)
           77  +          UNION ALL
           78  +          SELECT x+1, randomblob(100) FROM r
           79  +          LIMIT 1000000
           80  +          )
           81  +        SELECT count(x), length(y) FROM r GROUP BY (x%5)
           82  +    } {
           83  +      200000 100 200000 100 200000 100 200000 100 200000 100
           84  +    }
    81     85     }
    82     86   }
    83     87   
    84     88   finish_test

Changes to test/sort3.test.

    14     14   # configured to use mmap(), but the temporary files generated by the
    15     15   # sorter are too large to be completely mapped.
    16     16   #
    17     17   
    18     18   set testdir [file dirname $argv0]
    19     19   source $testdir/tester.tcl
    20     20   set testprefix sort3
           21  +
           22  +#-------------------------------------------------------------------------
           23  +# Sort some large ( > 4KiB) records.
           24  +#
           25  +proc cksum {x} {
           26  +  set i1 1
           27  +  set i2 2
           28  +  binary scan $x c* L
           29  +  foreach {a b} $L {
           30  +    set i1 [expr (($i2<<3) + $a) & 0x7FFFFFFF]
           31  +    set i2 [expr (($i1<<3) + $b) & 0x7FFFFFFF]
           32  +  }
           33  +  list $i1 $i2
           34  +}
           35  +db func cksum cksum
           36  +
           37  +do_execsql_test 1.0 {
           38  +  PRAGMA cache_size = 5;
           39  +  CREATE TABLE t11(a, b);
           40  +  INSERT INTO t11 VALUES(randomblob(5000), NULL);
           41  +  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --2
           42  +  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --3
           43  +  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --4
           44  +  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --5
           45  +  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --6
           46  +  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --7
           47  +  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --8
           48  +  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --9
           49  +  UPDATE t11 SET b = cksum(a);
           50  +}
           51  +
           52  +foreach {tn mmap_limit} {
           53  +  1 0
           54  +  2 1000000
           55  +} {
           56  +  do_test 1.$tn {
           57  +    sqlite3_test_control SQLITE_TESTCTRL_SORTER_MMAP db $mmap_limit
           58  +    set prev ""
           59  +    db eval { SELECT * FROM t11 ORDER BY b } {
           60  +      if {$b != [cksum $a]} {error "checksum failed"}
           61  +      if {[string compare $b $prev] < 0} {error "sort failed"}
           62  +      set prev $b
           63  +    }
           64  +    set {} {}
           65  +  } {}
           66  +}
           67  +
    21     68   
    22     69   # Sort roughly 20MB of data. Once with a mmap limit of 5MB and once without.
    23     70   #
    24     71   foreach {itest limit} {
    25     72     1 5000000
    26     73     2 0x7FFFFFFF
    27     74   } {
    28     75     sqlite3_test_control SQLITE_TESTCTRL_SORTER_MMAP db $limit
    29         -  do_execsql_test 1.$itest {
           76  +  do_execsql_test 2.$itest {
    30     77       WITH r(x,y) AS (
    31     78           SELECT 1, randomblob(1000)
    32     79           UNION ALL
    33     80           SELECT x+1, randomblob(1000) FROM r
    34     81           LIMIT 20000
    35     82       )
    36     83       SELECT count(*), sum(length(y)) FROM r GROUP BY (x%5);
................................................................................
    42     89       4000 4000000
    43     90     }
    44     91   }
    45     92   
    46     93   # Sort more than 2GB of data. At one point this was causing a problem.
    47     94   # This test might take one minute or more to run.
    48     95   #
    49         -do_execsql_test 2 {
           96  +do_execsql_test 3 {
    50     97     PRAGMA cache_size = 20000;
    51     98     WITH r(x,y) AS (
    52     99       SELECT 1, randomblob(1000)
    53    100       UNION ALL
    54    101       SELECT x+1, randomblob(1000) FROM r
    55    102       LIMIT 2200000
    56    103     )

Changes to test/sync.test.

     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.
    12     12   #
    13     13   # This file implements tests to verify that fsync is disabled when
    14     14   # pragma synchronous=off even for multi-database commits.
    15     15   #
    16         -# $Id: sync.test,v 1.6 2007/10/09 08:29:33 danielk1977 Exp $
    17     16   
    18     17   set testdir [file dirname $argv0]
    19     18   source $testdir/tester.tcl
    20     19   
    21     20   #
    22     21   # These tests are only applicable when pager pragma are
    23     22   # enabled. Also, since every test uses an ATTACHed database, they
................................................................................
    29     28   }
    30     29   
    31     30   set sqlite_sync_count 0
    32     31   proc cond_incr_sync_count {adj} {
    33     32     global sqlite_sync_count
    34     33     if {$::tcl_platform(platform) == "windows"} {
    35     34       incr sqlite_sync_count $adj
    36         -  } {
           35  +  } else {
    37     36       ifcapable !dirsync {
    38     37         incr sqlite_sync_count $adj
    39     38       }
    40     39     }
    41     40   }
    42     41   
    43     42   do_test sync-1.1 {
................................................................................
    60     59         PRAGMA main.synchronous=on;
    61     60         PRAGMA db2.synchronous=on;
    62     61         BEGIN;
    63     62         INSERT INTO t1 VALUES(1,2);
    64     63         INSERT INTO t2 VALUES(3,4);
    65     64         COMMIT;
    66     65       }
    67         -    cond_incr_sync_count 3
           66  +    cond_incr_sync_count 4
    68     67       set sqlite_sync_count
    69         -  } 8
           68  +  } 9
    70     69   }
    71     70   do_test sync-1.3 {
    72     71     set sqlite_sync_count 0
    73     72     execsql {
    74     73       PRAGMA main.synchronous=full;
    75     74       PRAGMA db2.synchronous=full;
    76     75       BEGIN;
    77     76       INSERT INTO t1 VALUES(3,4);
    78     77       INSERT INTO t2 VALUES(5,6);
    79     78       COMMIT;
    80     79     }
    81         -  cond_incr_sync_count 3
           80  +  cond_incr_sync_count 4
    82     81     set sqlite_sync_count
    83         -} 10
           82  +} 11
    84     83   ifcapable pager_pragmas {
    85     84     do_test sync-1.4 {
    86     85       set sqlite_sync_count 0
    87     86       execsql {
    88     87         PRAGMA main.synchronous=off;
    89     88         PRAGMA db2.synchronous=off;
    90     89         BEGIN;

Changes to test/tester.tcl.

  1942   1942       return 0
  1943   1943     }
  1944   1944     if { [path_is_dos "."] } {
  1945   1945       return 0
  1946   1946     }
  1947   1947     return 1
  1948   1948   }
         1949  +
         1950  +proc isquick {} {
         1951  +  set ret 0
         1952  +  catch {set ret $::G(isquick)}
         1953  +  set ret
         1954  +}
  1949   1955   
  1950   1956   #-------------------------------------------------------------------------
  1951   1957   #
  1952   1958   proc slave_test_script {script} {
  1953   1959   
  1954   1960     # Create the interpreter used to run the test script.
  1955   1961     interp create tinterp

Changes to test/wal.test.

   845    845   } {B 2}
   846    846   db2 close
   847    847   ifcapable enable_persist_wal {
   848    848     file_control_persist_wal db 0
   849    849   }
   850    850   db close
   851    851   
   852         -#-------------------------------------------------------------------------
   853         -# Test large log summaries.
   854         -#
   855         -# In this case "large" usually means a log file that requires a wal-index
   856         -# mapping larger than 64KB (the default initial allocation). A 64KB wal-index
   857         -# is large enough for a log file that contains approximately 13100 frames.
   858         -# So the following tests create logs containing at least this many frames.
   859         -#
   860         -# wal-13.1.*: This test case creates a very large log file within the
   861         -#             file-system (around 200MB). The log file does not contain
   862         -#             any valid frames. Test that the database file can still be
   863         -#             opened and queried, and that the invalid log file causes no 
   864         -#             problems.
   865         -#
   866         -# wal-13.2.*: Test that a process may create a large log file and query
   867         -#             the database (including the log file that it itself created).
   868         -#
   869         -# wal-13.3.*: Test that if a very large log file is created, and then a
   870         -#             second connection is opened on the database file, it is possible
   871         -#             to query the database (and the very large log) using the
   872         -#             second connection.
   873         -#
   874         -# wal-13.4.*: Same test as wal-13.3.*. Except in this case the second
   875         -#             connection is opened by an external process.
   876         -#
   877         -do_test wal-13.1.1 {
   878         -  list [file exists test.db] [file exists test.db-wal]
   879         -} {1 0}
   880         -do_test wal-13.1.2 {
   881         -  set fd [open test.db-wal w]
   882         -  seek $fd [expr 200*1024*1024]
   883         -  puts $fd ""
   884         -  close $fd
   885         -  sqlite3 db test.db
   886         -  execsql { SELECT * FROM t2 }
   887         -} {B 2}
   888         -do_test wal-13.1.3 {
   889         -  ifcapable enable_persist_wal {
   890         -    file_control_persist_wal db 0
   891         -  }
   892         -  db close
   893         -  file exists test.db-wal
   894         -} {0}
   895         -
   896         -do_test wal-13.2.1 {
   897         -  sqlite3 db test.db
   898         -  execsql { SELECT count(*) FROM t2 }
   899         -} {1}
   900         -do_test wal-13.2.2 {
   901         -  db function blob blob
   902         -  for {set i 0} {$i < 16} {incr i} {
   903         -    execsql { INSERT INTO t2 SELECT blob(400), blob(400) FROM t2 }
   904         -  }
   905         -  execsql { SELECT count(*) FROM t2 }
   906         -} [expr int(pow(2, 16))]
   907         -do_test wal-13.2.3 {
   908         -  expr [file size test.db-wal] > [wal_file_size 33000 1024]
   909         -} 1
   910         -
   911         -do_multiclient_test tn {
   912         -  incr tn 2
   913         -
   914         -  do_test wal-13.$tn.0 {
   915         -    sql1 {
   916         -      PRAGMA journal_mode = WAL;
   917         -      CREATE TABLE t1(x);
   918         -      INSERT INTO t1 SELECT randomblob(800);
   919         -    }
   920         -    sql1 { SELECT count(*) FROM t1 }
   921         -  } {1}
   922         -
   923         -  for {set ii 1} {$ii<16} {incr ii} {
   924         -    do_test wal-13.$tn.$ii.a {
   925         -      sql2 { INSERT INTO t1 SELECT randomblob(800) FROM t1 }
   926         -      sql2 { SELECT count(*) FROM t1 }
   927         -    } [expr (1<<$ii)]
   928         -    do_test wal-13.$tn.$ii.b {
   929         -      sql1 { SELECT count(*) FROM t1 }
   930         -    } [expr (1<<$ii)]
   931         -    do_test wal-13.$tn.$ii.c {
   932         -      sql1 { SELECT count(*) FROM t1 }
   933         -    } [expr (1<<$ii)]
   934         -    do_test wal-13.$tn.$ii.d {
   935         -      sql1 { PRAGMA integrity_check }
   936         -    } {ok}
   937         -  }
   938         -}
   939         -
   940    852   #-------------------------------------------------------------------------
   941    853   # Check a fun corruption case has been fixed.
   942    854   #
   943    855   # The problem was that after performing a checkpoint using a connection
   944    856   # that had an out-of-date pager-cache, the next time the connection was
   945    857   # used it did not realize the cache was out-of-date and proceeded to
   946    858   # operate with an inconsistent cache. Leading to corruption.

Changes to test/wal3.test.

    58     58         INSERT INTO t1 SELECT a_string(800) FROM t1;             /* 1024 */
    59     59         INSERT INTO t1 SELECT a_string(800) FROM t1;             /* 2048 */
    60     60         INSERT INTO t1 SELECT a_string(800) FROM t1 LIMIT 1970;  /* 4018 */
    61     61       COMMIT;
    62     62       PRAGMA cache_size = 10;
    63     63     }
    64     64     set x [wal_frame_count test.db-wal 1024]
    65         -  if {$::G(perm:name)=="memsubsys1"} {
           65  +  if {[permutation]=="memsubsys1"} {
    66     66       if {$x==4251 || $x==4290} {set x 4056}
    67     67     }
    68     68     set x
    69     69   } 4056
    70     70   
    71     71   for {set i 1} {$i < 50} {incr i} {
    72     72   
................................................................................
   243    243       set ::syncs
   244    244     } $usecount
   245    245   
   246    246     db close
   247    247     T delete
   248    248   }
   249    249   
   250         -#-------------------------------------------------------------------------
   251         -# When recovering the contents of a WAL file, a process obtains the WRITER
   252         -# lock, then locks all other bytes before commencing recovery. If it fails
   253         -# to lock all other bytes (because some other process is holding a read
   254         -# lock) it should retry up to 100 times. Then return SQLITE_PROTOCOL to the 
   255         -# caller. Test this (test case wal3-4.3).
   256         -#
   257         -# Also test the effect of hitting an SQLITE_BUSY while attempting to obtain
   258         -# the WRITER lock (should be the same). Test case wal3-4.4.
   259         -# 
   260         -proc lock_callback {method filename handle lock} {
   261         -  lappend ::locks $lock
   262         -}
   263         -do_test wal3-4.1 {
   264         -  testvfs T
   265         -  T filter xShmLock 
   266         -  T script lock_callback
   267         -  set ::locks [list]
   268         -  sqlite3 db test.db -vfs T
   269         -  execsql { SELECT * FROM x }
   270         -  lrange $::locks 0 3
   271         -} [list {0 1 lock exclusive} {1 7 lock exclusive}      \
   272         -        {1 7 unlock exclusive} {0 1 unlock exclusive}  \
   273         -]
   274         -do_test wal3-4.2 {
   275         -  db close
   276         -  set ::locks [list]
   277         -  sqlite3 db test.db -vfs T
   278         -  execsql { SELECT * FROM x }
   279         -  lrange $::locks 0 3
   280         -} [list {0 1 lock exclusive} {1 7 lock exclusive}      \
   281         -        {1 7 unlock exclusive} {0 1 unlock exclusive}  \
   282         -]
   283         -proc lock_callback {method filename handle lock} {
   284         -  if {$lock == "1 7 lock exclusive"} { return SQLITE_BUSY }
   285         -  return SQLITE_OK
   286         -}
   287         -puts "# Warning: This next test case causes SQLite to call xSleep(1) 100 times."
   288         -puts "# Normally this equates to a 100ms delay, but if SQLite is built on unix"
   289         -puts "# without HAVE_USLEEP defined, it may be 100 seconds."
   290         -do_test wal3-4.3 {
   291         -  db close
   292         -  set ::locks [list]
   293         -  sqlite3 db test.db -vfs T
   294         -  catchsql { SELECT * FROM x }
   295         -} {1 {locking protocol}}
   296         -
   297         -puts "# Warning: Same again!"
   298         -proc lock_callback {method filename handle lock} {
   299         -  if {$lock == "0 1 lock exclusive"} { return SQLITE_BUSY }
   300         -  return SQLITE_OK
   301         -}
   302         -do_test wal3-4.4 {
   303         -  db close
   304         -  set ::locks [list]
   305         -  sqlite3 db test.db -vfs T
   306         -  catchsql { SELECT * FROM x }
   307         -} {1 {locking protocol}}
   308         -db close
   309         -T delete
   310         -
   311    250   
   312    251   #-------------------------------------------------------------------------
   313    252   # Only one client may run recovery at a time. Test this mechanism.
   314    253   #
   315    254   # When client-2 tries to open a read transaction while client-1 is 
   316    255   # running recovery, it fails to obtain a lock on an aReadMark[] slot
   317    256   # (because they are all locked by recovery). It then tries to obtain
................................................................................
   622    561     set ::locks
   623    562   } {{5 1 lock shared} {5 1 unlock shared} {4 1 lock shared} {4 1 unlock shared}}
   624    563   
   625    564   db close
   626    565   db2 close
   627    566   T delete
   628    567   
   629         -#-------------------------------------------------------------------------
   630         -# 
   631         -do_test wal3-8.1 {
   632         -  forcedelete test.db test.db-journal test.db wal
   633         -  sqlite3 db test.db
   634         -  sqlite3 db2 test.db
   635         -  execsql {
   636         -    PRAGMA auto_vacuum = off;
   637         -    PRAGMA journal_mode = WAL;
   638         -    CREATE TABLE b(c);
   639         -    INSERT INTO b VALUES('Tehran');
   640         -    INSERT INTO b VALUES('Qom');
   641         -    INSERT INTO b VALUES('Markazi');
   642         -    PRAGMA wal_checkpoint;
   643         -  }
   644         -} {wal 0 5 5}
   645         -do_test wal3-8.2 {
   646         -  execsql { SELECT * FROM b }
   647         -} {Tehran Qom Markazi}
   648         -do_test wal3-8.3 {
   649         -  db eval { SELECT * FROM b } {
   650         -    db eval { INSERT INTO b VALUES('Qazvin') }
   651         -    set r [db2 eval { SELECT * FROM b }]
   652         -    break
   653         -  }
   654         -  set r
   655         -} {Tehran Qom Markazi Qazvin}
   656         -do_test wal3-8.4 {
   657         -  execsql {
   658         -    INSERT INTO b VALUES('Gilan');
   659         -    INSERT INTO b VALUES('Ardabil');
   660         -  }
   661         -} {}
   662         -db2 close
   663         -
   664         -faultsim_save_and_close
   665         -testvfs T -default 1
   666         -faultsim_restore_and_reopen
   667         -T filter xShmLock
   668         -T script lock_callback
   669         -
   670         -proc lock_callback {method file handle spec} {
   671         -  if {$spec == "1 7 unlock exclusive"} {
   672         -    T filter {}
   673         -    set ::r [catchsql { SELECT * FROM b } db2]
   674         -  }
   675         -}
   676         -sqlite3 db test.db
   677         -sqlite3 db2 test.db
   678         -do_test wal3-8.5 {
   679         -  execsql { SELECT * FROM b }
   680         -} {Tehran Qom Markazi Qazvin Gilan Ardabil}
   681         -do_test wal3-8.6 {
   682         -  set ::r
   683         -} {1 {locking protocol}}
   684         -
   685         -db close
   686         -db2 close
   687         -
   688         -faultsim_restore_and_reopen
   689         -sqlite3 db2 test.db
   690         -T filter xShmLock
   691         -T script lock_callback
   692         -proc lock_callback {method file handle spec} {
   693         -  if {$spec == "1 7 unlock exclusive"} {
   694         -    T filter {}
   695         -    set ::r [catchsql { SELECT * FROM b } db2]
   696         -  }
   697         -}
   698         -unset ::r
   699         -do_test wal3-8.5 {
   700         -  execsql { SELECT * FROM b }
   701         -} {Tehran Qom Markazi Qazvin Gilan Ardabil}
   702         -do_test wal3-8.6 {
   703         -  set ::r
   704         -} {1 {locking protocol}}
   705         -
   706         -db close
   707         -db2 close
   708         -T delete
   709    568   
   710    569   #-------------------------------------------------------------------------
   711    570   # When a connection opens a read-lock on the database, it searches for
   712    571   # an aReadMark[] slot that is already set to the mxFrame value for the
   713    572   # new transaction. If it cannot find one, it attempts to obtain an 
   714    573   # exclusive lock on an aReadMark[] slot for the purposes of modifying
   715    574   # the value, then drops back to a shared-lock for the duration of the

Changes to test/walcksum.test.

   331    331       PRAGMA integrity_check;
   332    332       SELECT count(*) FROM t1;
   333    333     } db2
   334    334   } {ok 256}
   335    335   catch { db close }
   336    336   catch { db2 close }
   337    337   
   338         -#-------------------------------------------------------------------------
   339         -# Test case walcksum-3.* tests that the checksum calculation detects single 
   340         -# byte changes to frame or frame-header data and considers the frame
   341         -# invalid as a result.
   342         -#
   343         -do_test walcksum-3.1 {
   344         -  forcedelete test.db test.db-wal test.db-journal
   345         -  sqlite3 db test.db
   346         -
   347         -  execsql {
   348         -    PRAGMA synchronous = NORMAL;
   349         -    PRAGMA page_size = 1024;
   350         -    CREATE TABLE t1(a, b);
   351         -    INSERT INTO t1 VALUES(1, randomblob(300));
   352         -    INSERT INTO t1 VALUES(2, randomblob(300));
   353         -    PRAGMA journal_mode = WAL;
   354         -    INSERT INTO t1 VALUES(3, randomblob(300));
   355         -  }
   356         -
   357         -  file size test.db-wal
   358         -} [wal_file_size 1 1024]
   359         -do_test walcksum-3.2 {
   360         -  forcecopy test.db-wal test2.db-wal
   361         -  forcecopy test.db test2.db
   362         -  sqlite3 db2 test2.db
   363         -  execsql { SELECT a FROM t1 } db2
   364         -} {1 2 3}
   365         -db2 close
   366         -forcecopy test.db test2.db
   367         -
   368         -
   369         -foreach incr {1 2 3 20 40 60 80 100 120 140 160 180 200 220 240 253 254 255} {
   370         -  do_test walcksum-3.3.$incr {
   371         -    set FAIL 0
   372         -    for {set iOff 0} {$iOff < [wal_file_size 1 1024]} {incr iOff} {
   373         -
   374         -      forcecopy test.db-wal test2.db-wal
   375         -      set fd [open test2.db-wal r+]
   376         -      fconfigure $fd -encoding binary
   377         -      fconfigure $fd -translation binary
   378         -  
   379         -      seek $fd $iOff
   380         -      binary scan [read $fd 1] c x
   381         -      seek $fd $iOff
   382         -      puts -nonewline $fd [binary format c [expr {($x+$incr)&0xFF}]]
   383         -      close $fd
   384         -    
   385         -      sqlite3 db2 test2.db
   386         -      if { [execsql { SELECT a FROM t1 } db2] != "1 2" } {set FAIL 1}
   387         -      db2 close
   388         -    }
   389         -    set FAIL
   390         -  } {0}
   391         -}
   392    338     
   393    339   finish_test

Added test/walprotocol.test.

            1  +# 2016 February 4
            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 regression tests for SQLite library.  The
           12  +# focus of this file is testing the operation of the library in
           13  +# "PRAGMA journal_mode=WAL" mode.
           14  +#
           15  +# More specifically, it tests "locking protocol" errors - errors that
           16  +# may be caused if one or more SQLite clients does not follow the expected
           17  +# locking protocol when accessing a wal-mode database. These tests take
           18  +# quite a while to run.
           19  +#
           20  +
           21  +set testdir [file dirname $argv0]
           22  +source $testdir/tester.tcl
           23  +source $testdir/lock_common.tcl
           24  +source $testdir/wal_common.tcl
           25  +ifcapable !wal {finish_test ; return }
           26  +
           27  +set testprefix walprotocol
           28  +
           29  +#-------------------------------------------------------------------------
           30  +# When recovering the contents of a WAL file, a process obtains the WRITER
           31  +# lock, then locks all other bytes before commencing recovery. If it fails
           32  +# to lock all other bytes (because some other process is holding a read
           33  +# lock) it should retry up to 100 times. Then return SQLITE_PROTOCOL to the 
           34  +# caller. Test this (test case 1.3).
           35  +#
           36  +# Also test the effect of hitting an SQLITE_BUSY while attempting to obtain
           37  +# the WRITER lock (should be the same). Test case 1.4.
           38  +# 
           39  +do_execsql_test 1.0 {
           40  +  PRAGMA journal_mode = wal;
           41  +  CREATE TABLE x(y);
           42  +  INSERT INTO x VALUES('z');
           43  +} {wal}
           44  +
           45  +proc lock_callback {method filename handle lock} {
           46  +  lappend ::locks $lock
           47  +}
           48  +do_test 1.1 {
           49  +  testvfs T
           50  +  T filter xShmLock 
           51  +  T script lock_callback
           52  +  set ::locks [list]
           53  +  sqlite3 db test.db -vfs T
           54  +  execsql { SELECT * FROM x }
           55  +  lrange $::locks 0 3
           56  +} [list {0 1 lock exclusive} {1 7 lock exclusive}      \
           57  +        {1 7 unlock exclusive} {0 1 unlock exclusive}  \
           58  +]
           59  +do_test 1.2 {
           60  +  db close
           61  +  set ::locks [list]
           62  +  sqlite3 db test.db -vfs T
           63  +  execsql { SELECT * FROM x }
           64  +  lrange $::locks 0 3
           65  +} [list {0 1 lock exclusive} {1 7 lock exclusive}      \
           66  +        {1 7 unlock exclusive} {0 1 unlock exclusive}  \
           67  +]
           68  +proc lock_callback {method filename handle lock} {
           69  +  if {$lock == "1 7 lock exclusive"} { return SQLITE_BUSY }
           70  +  return SQLITE_OK
           71  +}
           72  +puts "# Warning: This next test case causes SQLite to call xSlee(1) 100 times."
           73  +puts "# Normally this equates to a delay of roughly 10 seconds, but if SQLite"
           74  +puts "# is built on unix without HAVE_USLEEP defined, it may be much longer."
           75  +do_test 1.3 {
           76  +  db close
           77  +  set ::locks [list]
           78  +  sqlite3 db test.db -vfs T
           79  +  catchsql { SELECT * FROM x }
           80  +} {1 {locking protocol}}
           81  +
           82  +puts "# Warning: Same again!"
           83  +proc lock_callback {method filename handle lock} {
           84  +  if {$lock == "0 1 lock exclusive"} { return SQLITE_BUSY }
           85  +  return SQLITE_OK
           86  +}
           87  +do_test 1.4 {
           88  +  db close
           89  +  set ::locks [list]
           90  +  sqlite3 db test.db -vfs T
           91  +  catchsql { SELECT * FROM x }
           92  +} {1 {locking protocol}}
           93  +db close
           94  +T delete
           95  +
           96  +#-------------------------------------------------------------------------
           97  +# 
           98  +do_test 2.1 {
           99  +  forcedelete test.db test.db-journal test.db wal
          100  +  sqlite3 db test.db
          101  +  sqlite3 db2 test.db
          102  +  execsql {
          103  +    PRAGMA auto_vacuum = off;
          104  +    PRAGMA journal_mode = WAL;
          105  +    CREATE TABLE b(c);
          106  +    INSERT INTO b VALUES('Tehran');
          107  +    INSERT INTO b VALUES('Qom');
          108  +    INSERT INTO b VALUES('Markazi');
          109  +    PRAGMA wal_checkpoint;
          110  +  }
          111  +} {wal 0 5 5}
          112  +do_test 2.2 {
          113  +  execsql { SELECT * FROM b }
          114  +} {Tehran Qom Markazi}
          115  +do_test 2.3 {
          116  +  db eval { SELECT * FROM b } {
          117  +    db eval { INSERT INTO b VALUES('Qazvin') }
          118  +    set r [db2 eval { SELECT * FROM b }]
          119  +    break
          120  +  }
          121  +  set r
          122  +} {Tehran Qom Markazi Qazvin}
          123  +do_test 2.4 {
          124  +  execsql {
          125  +    INSERT INTO b VALUES('Gilan');
          126  +    INSERT INTO b VALUES('Ardabil');
          127  +  }
          128  +} {}
          129  +db2 close
          130  +
          131  +faultsim_save_and_close
          132  +testvfs T -default 1
          133  +faultsim_restore_and_reopen
          134  +T filter xShmLock
          135  +T script lock_callback
          136  +
          137  +proc lock_callback {method file handle spec} {
          138  +  if {$spec == "1 7 unlock exclusive"} {
          139  +    T filter {}
          140  +    set ::r [catchsql { SELECT * FROM b } db2]
          141  +  }
          142  +}
          143  +sqlite3 db test.db
          144  +sqlite3 db2 test.db
          145  +do_test 2.5 {
          146  +  execsql { SELECT * FROM b }
          147  +} {Tehran Qom Markazi Qazvin Gilan Ardabil}
          148  +do_test 2.6 {
          149  +  set ::r
          150  +} {1 {locking protocol}}
          151  +
          152  +db close
          153  +db2 close
          154  +
          155  +faultsim_restore_and_reopen
          156  +sqlite3 db2 test.db
          157  +T filter xShmLock
          158  +T script lock_callback
          159  +proc lock_callback {method file handle spec} {
          160  +  if {$spec == "1 7 unlock exclusive"} {
          161  +    T filter {}
          162  +    set ::r [catchsql { SELECT * FROM b } db2]
          163  +  }
          164  +}
          165  +unset ::r
          166  +do_test 2.7 {
          167  +  execsql { SELECT * FROM b }
          168  +} {Tehran Qom Markazi Qazvin Gilan Ardabil}
          169  +do_test 2.8 {
          170  +  set ::r
          171  +} {1 {locking protocol}}
          172  +
          173  +db close
          174  +db2 close
          175  +T delete
          176  +
          177  +finish_test

Changes to test/walslow.test.

    12     12   # focus of this file is testing the operation of the library in
    13     13   # "PRAGMA journal_mode=WAL" mode. The tests in this file use 
    14     14   # brute force methods, so may take a while to run.
    15     15   #
    16     16   
    17     17   set testdir [file dirname $argv0]
    18     18   source $testdir/tester.tcl
           19  +source $testdir/wal_common.tcl
           20  +source $testdir/lock_common.tcl
    19     21   
    20     22   ifcapable !wal {finish_test ; return }
    21     23   if ![wal_is_ok] { finish_test; return }
           24  +set testprefix walslow
    22     25   
    23     26   proc reopen_db {} {
    24     27     catch { db close }
    25     28     forcedelete test.db test.db-wal
    26     29     sqlite3 db test.db
    27     30     execsql { PRAGMA journal_mode = wal }
    28     31   }
................................................................................
    66     69       do_test walslow-1.seed=$seed.$iTest.4 {
    67     70         execsql { SELECT count(*) FROM t1 WHERE a!=b } db2
    68     71       } [execsql { SELECT count(*) FROM t1 WHERE a!=b }]
    69     72       db2 close
    70     73     }
    71     74   }
    72     75   
           76  +#-------------------------------------------------------------------------
           77  +# Test case walslow-3.* tests that the checksum calculation detects single 
           78  +# byte changes to frame or frame-header data and considers the frame
           79  +# invalid as a result.
           80  +#
           81  +reset_db
           82  +do_test 3.1 {
           83  +
           84  +  execsql {
           85  +    PRAGMA synchronous = NORMAL;
           86  +    PRAGMA page_size = 1024;
           87  +    CREATE TABLE t1(a, b);
           88  +    INSERT INTO t1 VALUES(1, randomblob(300));
           89  +    INSERT INTO t1 VALUES(2, randomblob(300));
           90  +    PRAGMA journal_mode = WAL;
           91  +    INSERT INTO t1 VALUES(3, randomblob(300));
           92  +  }
           93  +
           94  +  file size test.db-wal
           95  +} [wal_file_size 1 1024]
           96  +do_test 3.2 {
           97  +  forcecopy test.db-wal test2.db-wal
           98  +  forcecopy test.db test2.db
           99  +  sqlite3 db2 test2.db
          100  +  execsql { SELECT a FROM t1 } db2
          101  +} {1 2 3}
          102  +db2 close
          103  +forcecopy test.db test2.db
          104  +
          105  +foreach incr {1 2 3 20 40 60 80 100 120 140 160 180 200 220 240 253 254 255} {
          106  +  do_test 3.3.$incr {
          107  +    set FAIL 0
          108  +    for {set iOff 0} {$iOff < [wal_file_size 1 1024]} {incr iOff} {
          109  +
          110  +      forcecopy test.db-wal test2.db-wal
          111  +      set fd [open test2.db-wal r+]
          112  +      fconfigure $fd -encoding binary
          113  +      fconfigure $fd -translation binary
          114  +  
          115  +      seek $fd $iOff
          116  +      binary scan [read $fd 1] c x
          117  +      seek $fd $iOff
          118  +      puts -nonewline $fd [binary format c [expr {($x+$incr)&0xFF}]]
          119  +      close $fd
          120  +    
          121  +      sqlite3 db2 test2.db
          122  +      if { [execsql { SELECT a FROM t1 } db2] != "1 2" } {set FAIL 1}
          123  +      db2 close
          124  +    }
          125  +    set FAIL
          126  +  } {0}
          127  +}
          128  +
          129  +
          130  +#-------------------------------------------------------------------------
          131  +# Test large log summaries.
          132  +#
          133  +# In this case "large" usually means a log file that requires a wal-index
          134  +# mapping larger than 64KB (the default initial allocation). A 64KB wal-index
          135  +# is large enough for a log file that contains approximately 13100 frames.
          136  +# So the following tests create logs containing at least this many frames.
          137  +#
          138  +# 4.1.*: This test case creates a very large log file within the
          139  +#        file-system (around 200MB). The log file does not contain
          140  +#        any valid frames. Test that the database file can still be
          141  +#        opened and queried, and that the invalid log file causes no 
          142  +#        problems.
          143  +#
          144  +# 4.2.*: Test that a process may create a large log file and query
          145  +#        the database (including the log file that it itself created).
          146  +#
          147  +# 4.3.*: Test that if a very large log file is created, and then a
          148  +#        second connection is opened on the database file, it is possible
          149  +#        to query the database (and the very large log) using the
          150  +#        second connection.
          151  +#
          152  +# 4.4.*: Same test as wal-13.3.*. Except in this case the second
          153  +#        connection is opened by an external process.
          154  +#
          155  +set ::blobcnt 0
          156  +proc blob {nByte} {
          157  +  incr ::blobcnt
          158  +  return [string range [string repeat "${::blobcnt}x" $nByte] 1 $nByte]
          159  +}
          160  +
          161  +reset_db
          162  +do_execsql_test 4.1 {
          163  +  PRAGMA journal_mode = wal;
          164  +  CREATE TABLE t1(x, y);
          165  +  INSERT INTO "t1" VALUES('A',0);
          166  +  CREATE TABLE t2(x, y);
          167  +  INSERT INTO "t2" VALUES('B',2);
          168  +} {wal}
          169  +db close
          170  +
          171  +do_test 4.1.1 {
          172  +  list [file exists test.db] [file exists test.db-wal]
          173  +} {1 0}
          174  +do_test 4.1.2 {
          175  +  set fd [open test.db-wal w]
          176  +  seek $fd [expr 200*1024*1024]
          177  +  puts $fd ""
          178  +  close $fd
          179  +  sqlite3 db test.db
          180  +  execsql { SELECT * FROM t2 }
          181  +} {B 2}
          182  +do_test 4.1.3 {
          183  +  db close
          184  +  file exists test.db-wal
          185  +} {0}
          186  +
          187  +do_test 4.2.1 {
          188  +  sqlite3 db test.db
          189  +  execsql { SELECT count(*) FROM t2 }
          190  +} {1}
          191  +do_test 4.2.2 {
          192  +  db function blob blob
          193  +  for {set i 0} {$i < 16} {incr i} {
          194  +    execsql { INSERT INTO t2 SELECT blob(400), blob(400) FROM t2 }
          195  +  }
          196  +  execsql { SELECT count(*) FROM t2 }
          197  +} [expr int(pow(2, 16))]
          198  +do_test 4.2.3 {
          199  +  expr [file size test.db-wal] > [wal_file_size 33000 1024]
          200  +} 1
          201  +
          202  +do_multiclient_test tn {
          203  +  incr tn 2
          204  +
          205  +  do_test 4.$tn.0 {
          206  +    sql1 {
          207  +      PRAGMA journal_mode = WAL;
          208  +      CREATE TABLE t1(x);
          209  +      INSERT INTO t1 SELECT randomblob(800);
          210  +    }
          211  +    sql1 { SELECT count(*) FROM t1 }
          212  +  } {1}
          213  +
          214  +  for {set ii 1} {$ii<16} {incr ii} {
          215  +    do_test 4.$tn.$ii.a {
          216  +      sql2 { INSERT INTO t1 SELECT randomblob(800) FROM t1 }
          217  +      sql2 { SELECT count(*) FROM t1 }
          218  +    } [expr (1<<$ii)]
          219  +    do_test 4.$tn.$ii.b {
          220  +      sql1 { SELECT count(*) FROM t1 }
          221  +    } [expr (1<<$ii)]
          222  +    do_test 4.$tn.$ii.c {
          223  +      sql1 { SELECT count(*) FROM t1 }
          224  +    } [expr (1<<$ii)]
          225  +    do_test 4.$tn.$ii.d {
          226  +      sql1 { PRAGMA integrity_check }
          227  +    } {ok}
          228  +  }
          229  +}
    73    230   
    74    231   finish_test

Name change from test/where8m.test to test/wherefault.test.

     5      5   #
     6      6   #    May you do good and not evil.
     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library. The focus
    12         -# is testing of where.c. More specifically, the focus is the optimization
    13         -# of WHERE clauses that feature the OR operator.
           12  +# is testing of where.c. More specifically, the focus is on handling OOM
           13  +# errors within the code that optimizes WHERE clauses that feature the 
           14  +# OR operator.
    14     15   #
    15         -# $Id: where8m.test,v 1.3 2009/06/05 17:09:12 drh Exp $
    16     16   
    17     17   set testdir [file dirname $argv0]
    18     18   source $testdir/tester.tcl
    19     19   
    20     20   source $testdir/malloc_common.tcl
    21     21   
    22         -do_malloc_test where8m-1 -sqlprep {
           22  +set testprefix wherefault
           23  +
           24  +do_malloc_test 1 -sqlprep {
    23     25     CREATE TABLE t1(a, b, c);
    24     26     CREATE INDEX i1 ON t1(a);
    25     27     CREATE INDEX i2 ON t1(b);
    26     28   } -sqlbody {
    27     29     SELECT c FROM t1
    28     30     WHERE 
    29     31       a = 2 OR b = 'three' OR a = 4 OR b = 'five' OR a = 6 OR
................................................................................
    33     35     SELECT c FROM t1 WHERE
    34     36       a = 1 OR a = 2 OR a = 3 OR a = 4 OR a = 5 OR a = 6;
    35     37   
    36     38     SELECT c FROM t1 WHERE
    37     39       a BETWEEN 1 AND 3  AND b < 5 AND b > 2 AND c = 4;
    38     40   }
    39     41   
    40         -do_malloc_test where8m-2 -tclprep {
           42  +do_malloc_test 2 -tclprep {
    41     43     db eval {
    42     44       BEGIN;
    43     45       CREATE TABLE t1(a, b, c);
    44     46       CREATE INDEX i1 ON t1(a);
    45     47       CREATE INDEX i2 ON t1(b);
    46     48     }
    47     49     for {set i 0} {$i < 1000} {incr i} {

Changes to tool/build-all-msvc.bat.

   725    725     FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
   726    726       SET VALUE=%%V
   727    727     )
   728    728     ENDLOCAL && SET %2=%VALUE%
   729    729     GOTO :EOF
   730    730   
   731    731   :fn_UnsetVariable
          732  +  SETLOCAL
   732    733     SET VALUE=%1
   733    734     IF DEFINED VALUE (
   734         -    SET %VALUE%=
   735    735       SET VALUE=
   736         -    CALL :fn_ResetErrorLevel
          736  +    ENDLOCAL
          737  +    SET %VALUE%=
          738  +  ) ELSE (
          739  +    ENDLOCAL
   737    740     )
          741  +  CALL :fn_ResetErrorLevel
   738    742     GOTO :EOF
   739    743   
   740    744   :fn_AppendVariable
   741    745     SET __ECHO_CMD=ECHO %%%1%%
   742    746     IF DEFINED %1 (
   743    747       FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
   744    748         SET %1=%%V%~2