/ Check-in [249cd361]
Login

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

Overview
Comment:Update this branch with latest trunk changes.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | schemalint
Files: files | file ages | folders
SHA1: 249cd361b840913794b7cd2f2d42777dcd547a60
User & Date: dan 2016-03-15 09:42:39
Context
2017-03-31
08:00
Update shell6.test to account for the fact that tests are now run in a separate directory. check-in: 1e3622de user: dan tags: schemalint
2016-03-15
09:42
Update this branch with latest trunk changes. check-in: 249cd361 user: dan tags: schemalint
2016-03-14
21:26
Fix the permutations.test script so that it works again. check-in: 9f194f90 user: drh tags: trunk
2016-03-09
08:08
Merge latest trunk changes with this branch. check-in: 59caca43 user: dan tags: schemalint
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to autoconf/Makefile.am.

     2      2   AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE
     3      3   
     4      4   lib_LTLIBRARIES = libsqlite3.la
     5      5   libsqlite3_la_SOURCES = sqlite3.c
     6      6   libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8
     7      7   
     8      8   bin_PROGRAMS = sqlite3
     9         -sqlite3_SOURCES = shell.c sqlite3.c sqlite3.h
    10         -sqlite3_LDADD = @READLINE_LIBS@
            9  +sqlite3_SOURCES = shell.c sqlite3.h
           10  +EXTRA_sqlite3_SOURCES = sqlite3.c
           11  +sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@
    11     12   sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@
    12     13   sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS
    13     14   
    14     15   include_HEADERS = sqlite3.h sqlite3ext.h
    15     16   
    16     17   EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs
    17     18   pkgconfigdir = ${libdir}/pkgconfig
    18     19   pkgconfig_DATA = sqlite3.pc
    19     20   
    20     21   man_MANS = sqlite3.1

Changes to autoconf/configure.ac.

   126    126   #   --enable-static-shell
   127    127   #
   128    128   AC_ARG_ENABLE(static-shell, [AS_HELP_STRING(
   129    129     [--enable-static-shell], 
   130    130     [statically link libsqlite3 into shell tool [default=yes]])], 
   131    131     [], [enable_static_shell=yes])
   132    132   if test x"$enable_static_shell" == "xyes"; then
   133         -  EXTRA_SHELL_OBJ=sqlite3.$OBJEXT
          133  +  EXTRA_SHELL_OBJ=sqlite3-sqlite3.$OBJEXT
   134    134   else
   135    135     EXTRA_SHELL_OBJ=libsqlite3.la
   136    136   fi
   137    137   AC_SUBST(EXTRA_SHELL_OBJ)
   138    138   #-----------------------------------------------------------------------
   139    139   
   140    140   AC_CHECK_FUNCS(posix_fallocate)

Changes to ext/fts3/fts3_write.c.

  3191   3191     }
  3192   3192   
  3193   3193     if( iLevel==FTS3_SEGCURSOR_ALL ){
  3194   3194       /* This call is to merge all segments in the database to a single
  3195   3195       ** segment. The level of the new segment is equal to the numerically
  3196   3196       ** greatest segment level currently present in the database for this
  3197   3197       ** index. The idx of the new segment is always 0.  */
  3198         -    if( csr.nSegment==1 ){
         3198  +    if( csr.nSegment==1 && 0==fts3SegReaderIsPending(csr.apSegment[0]) ){
  3199   3199         rc = SQLITE_DONE;
  3200   3200         goto finished;
  3201   3201       }
  3202   3202       iNewLevel = iMaxLevel;
  3203   3203       bIgnoreEmpty = 1;
  3204   3204   
  3205   3205     }else{

Changes to ext/fts5/fts5Int.h.

   168    168     fts5_tokenizer *pTokApi;
   169    169   
   170    170     /* Values loaded from the %_config table */
   171    171     int iCookie;                    /* Incremented when %_config is modified */
   172    172     int pgsz;                       /* Approximate page size used in %_data */
   173    173     int nAutomerge;                 /* 'automerge' setting */
   174    174     int nCrisisMerge;               /* Maximum allowed segments per level */
          175  +  int nUsermerge;                 /* 'usermerge' setting */
   175    176     int nHashSize;                  /* Bytes of memory for in-memory hash */
   176    177     char *zRank;                    /* Name of rank function */
   177    178     char *zRankArgs;                /* Arguments to rank function */
   178    179   
   179    180     /* If non-NULL, points to sqlite3_vtab.base.zErrmsg. Often NULL. */
   180    181     char **pzErrmsg;
   181    182   
................................................................................
   695    696   Fts5ExprNode *sqlite3Fts5ParseNode(
   696    697     Fts5Parse *pParse,
   697    698     int eType,
   698    699     Fts5ExprNode *pLeft,
   699    700     Fts5ExprNode *pRight,
   700    701     Fts5ExprNearset *pNear
   701    702   );
          703  +
          704  +Fts5ExprNode *sqlite3Fts5ParseImplicitAnd(
          705  +  Fts5Parse *pParse,
          706  +  Fts5ExprNode *pLeft,
          707  +  Fts5ExprNode *pRight
          708  +);
   702    709   
   703    710   Fts5ExprPhrase *sqlite3Fts5ParseTerm(
   704    711     Fts5Parse *pParse, 
   705    712     Fts5ExprPhrase *pPhrase, 
   706    713     Fts5Token *pToken,
   707    714     int bPrefix
   708    715   );

Changes to ext/fts5/fts5_config.c.

    14     14   */
    15     15   
    16     16   
    17     17   #include "fts5Int.h"
    18     18   
    19     19   #define FTS5_DEFAULT_PAGE_SIZE   4050
    20     20   #define FTS5_DEFAULT_AUTOMERGE      4
           21  +#define FTS5_DEFAULT_USERMERGE      4
    21     22   #define FTS5_DEFAULT_CRISISMERGE   16
    22     23   #define FTS5_DEFAULT_HASHSIZE    (1024*1024)
    23     24   
    24     25   /* Maximum allowed page size */
    25     26   #define FTS5_MAX_PAGE_SIZE (128*1024)
    26     27   
    27     28   static int fts5_iswhitespace(char x){
................................................................................
   437    438       memcpy(zOut, zIn, nIn+1);
   438    439       if( fts5_isopenquote(zOut[0]) ){
   439    440         int ii = fts5Dequote(zOut);
   440    441         zRet = &zIn[ii];
   441    442         *pbQuoted = 1;
   442    443       }else{
   443    444         zRet = fts5ConfigSkipBareword(zIn);
   444         -      zOut[zRet-zIn] = '\0';
          445  +      if( zRet ){
          446  +        zOut[zRet-zIn] = '\0';
          447  +      }
   445    448       }
   446    449     }
   447    450   
   448    451     if( zRet==0 ){
   449    452       sqlite3_free(zOut);
   450    453     }else{
   451    454       *pzOut = zOut;
................................................................................
   852    855       if( nAutomerge<0 || nAutomerge>64 ){
   853    856         *pbBadkey = 1;
   854    857       }else{
   855    858         if( nAutomerge==1 ) nAutomerge = FTS5_DEFAULT_AUTOMERGE;
   856    859         pConfig->nAutomerge = nAutomerge;
   857    860       }
   858    861     }
          862  +
          863  +  else if( 0==sqlite3_stricmp(zKey, "usermerge") ){
          864  +    int nUsermerge = -1;
          865  +    if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
          866  +      nUsermerge = sqlite3_value_int(pVal);
          867  +    }
          868  +    if( nUsermerge<2 || nUsermerge>16 ){
          869  +      *pbBadkey = 1;
          870  +    }else{
          871  +      pConfig->nUsermerge = nUsermerge;
          872  +    }
          873  +  }
   859    874   
   860    875     else if( 0==sqlite3_stricmp(zKey, "crisismerge") ){
   861    876       int nCrisisMerge = -1;
   862    877       if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
   863    878         nCrisisMerge = sqlite3_value_int(pVal);
   864    879       }
   865    880       if( nCrisisMerge<0 ){
................................................................................
   899    914     sqlite3_stmt *p = 0;
   900    915     int rc = SQLITE_OK;
   901    916     int iVersion = 0;
   902    917   
   903    918     /* Set default values */
   904    919     pConfig->pgsz = FTS5_DEFAULT_PAGE_SIZE;
   905    920     pConfig->nAutomerge = FTS5_DEFAULT_AUTOMERGE;
          921  +  pConfig->nUsermerge = FTS5_DEFAULT_USERMERGE;
   906    922     pConfig->nCrisisMerge = FTS5_DEFAULT_CRISISMERGE;
   907    923     pConfig->nHashSize = FTS5_DEFAULT_HASHSIZE;
   908    924   
   909    925     zSql = sqlite3Fts5Mprintf(&rc, zSelect, pConfig->zDb, pConfig->zName);
   910    926     if( zSql ){
   911    927       rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &p, 0);
   912    928       sqlite3_free(zSql);

Changes to ext/fts5/fts5_expr.c.

   254    254         }
   255    255         pNew->pIndex = 0;
   256    256         pNew->pConfig = pConfig;
   257    257         pNew->apExprPhrase = sParse.apPhrase;
   258    258         pNew->nPhrase = sParse.nPhrase;
   259    259         sParse.apPhrase = 0;
   260    260       }
          261  +  }else{
          262  +    sqlite3Fts5ParseNodeFree(sParse.pExpr);
   261    263     }
   262    264   
   263    265     sqlite3_free(sParse.apPhrase);
   264    266     *pzErr = sParse.zErr;
   265    267     return sParse.rc;
   266    268   }
   267    269   
................................................................................
  1264   1266     int rc = SQLITE_OK;
  1265   1267     pNode->bEof = 0;
  1266   1268     pNode->bNomatch = 0;
  1267   1269   
  1268   1270     if( Fts5NodeIsString(pNode) ){
  1269   1271       /* Initialize all term iterators in the NEAR object. */
  1270   1272       rc = fts5ExprNearInitAll(pExpr, pNode);
         1273  +  }else if( pNode->xNext==0 ){
         1274  +    pNode->bEof = 1;
  1271   1275     }else{
  1272   1276       int i;
  1273   1277       int nEof = 0;
  1274   1278       for(i=0; i<pNode->nChild && rc==SQLITE_OK; i++){
  1275   1279         Fts5ExprNode *pChild = pNode->apChild[i];
  1276   1280         rc = fts5ExprNodeFirst(pExpr, pNode->apChild[i]);
  1277   1281         assert( pChild->bEof==0 || pChild->bEof==1 );
................................................................................
  1315   1319   ** equal to iFirst.
  1316   1320   **
  1317   1321   ** Return SQLITE_OK if successful, or an SQLite error code otherwise. It
  1318   1322   ** is not considered an error if the query does not match any documents.
  1319   1323   */
  1320   1324   int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){
  1321   1325     Fts5ExprNode *pRoot = p->pRoot;
  1322         -  int rc = SQLITE_OK;
  1323         -  if( pRoot->xNext ){
  1324         -    p->pIndex = pIdx;
  1325         -    p->bDesc = bDesc;
  1326         -    rc = fts5ExprNodeFirst(p, pRoot);
         1326  +  int rc;                         /* Return code */
  1327   1327   
  1328         -    /* If not at EOF but the current rowid occurs earlier than iFirst in
  1329         -    ** the iteration order, move to document iFirst or later. */
  1330         -    if( pRoot->bEof==0 && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 ){
  1331         -      rc = fts5ExprNodeNext(p, pRoot, 1, iFirst);
  1332         -    }
         1328  +  p->pIndex = pIdx;
         1329  +  p->bDesc = bDesc;
         1330  +  rc = fts5ExprNodeFirst(p, pRoot);
  1333   1331   
  1334         -    /* If the iterator is not at a real match, skip forward until it is. */
  1335         -    while( pRoot->bNomatch ){
  1336         -      assert( pRoot->bEof==0 && rc==SQLITE_OK );
  1337         -      rc = fts5ExprNodeNext(p, pRoot, 0, 0);
  1338         -    }
         1332  +  /* If not at EOF but the current rowid occurs earlier than iFirst in
         1333  +  ** the iteration order, move to document iFirst or later. */
         1334  +  if( pRoot->bEof==0 && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 ){
         1335  +    rc = fts5ExprNodeNext(p, pRoot, 1, iFirst);
         1336  +  }
         1337  +
         1338  +  /* If the iterator is not at a real match, skip forward until it is. */
         1339  +  while( pRoot->bNomatch ){
         1340  +    assert( pRoot->bEof==0 && rc==SQLITE_OK );
         1341  +    rc = fts5ExprNodeNext(p, pRoot, 0, 0);
  1339   1342     }
  1340   1343     return rc;
  1341   1344   }
  1342   1345   
  1343   1346   /*
  1344   1347   ** Move to the next document 
  1345   1348   **
................................................................................
  1440   1443     }
  1441   1444   
  1442   1445     if( pRet==0 ){
  1443   1446       assert( pParse->rc!=SQLITE_OK );
  1444   1447       sqlite3Fts5ParseNearsetFree(pNear);
  1445   1448       sqlite3Fts5ParsePhraseFree(pPhrase);
  1446   1449     }else{
         1450  +    if( pRet->nPhrase>0 ){
         1451  +      Fts5ExprPhrase *pLast = pRet->apPhrase[pRet->nPhrase-1];
         1452  +      assert( pLast==pParse->apPhrase[pParse->nPhrase-2] );
         1453  +      if( pPhrase->nTerm==0 ){
         1454  +        fts5ExprPhraseFree(pPhrase);
         1455  +        pRet->nPhrase--;
         1456  +        pParse->nPhrase--;
         1457  +        pPhrase = pLast;
         1458  +      }else if( pLast->nTerm==0 ){
         1459  +        fts5ExprPhraseFree(pLast);
         1460  +        pParse->apPhrase[pParse->nPhrase-2] = pPhrase;
         1461  +        pParse->nPhrase--;
         1462  +        pRet->nPhrase--;
         1463  +      }
         1464  +    }
  1447   1465       pRet->apPhrase[pRet->nPhrase++] = pPhrase;
  1448   1466     }
  1449   1467     return pRet;
  1450   1468   }
  1451   1469   
  1452   1470   typedef struct TokenCtx TokenCtx;
  1453   1471   struct TokenCtx {
................................................................................
  1472   1490     Fts5ExprPhrase *pPhrase = pCtx->pPhrase;
  1473   1491   
  1474   1492     UNUSED_PARAM2(iUnused1, iUnused2);
  1475   1493   
  1476   1494     /* If an error has already occurred, this is a no-op */
  1477   1495     if( pCtx->rc!=SQLITE_OK ) return pCtx->rc;
  1478   1496   
  1479         -  assert( pPhrase==0 || pPhrase->nTerm>0 );
  1480         -  if( pPhrase && (tflags & FTS5_TOKEN_COLOCATED) ){
         1497  +  if( pPhrase && pPhrase->nTerm>0 && (tflags & FTS5_TOKEN_COLOCATED) ){
  1481   1498       Fts5ExprTerm *pSyn;
  1482   1499       int nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1;
  1483   1500       pSyn = (Fts5ExprTerm*)sqlite3_malloc(nByte);
  1484   1501       if( pSyn==0 ){
  1485   1502         rc = SQLITE_NOMEM;
  1486   1503       }else{
  1487   1504         memset(pSyn, 0, nByte);
................................................................................
  1574   1591       rc = sqlite3Fts5Tokenize(pConfig, flags, z, n, &sCtx, fts5ParseTokenize);
  1575   1592     }
  1576   1593     sqlite3_free(z);
  1577   1594     if( rc || (rc = sCtx.rc) ){
  1578   1595       pParse->rc = rc;
  1579   1596       fts5ExprPhraseFree(sCtx.pPhrase);
  1580   1597       sCtx.pPhrase = 0;
  1581         -  }else if( sCtx.pPhrase ){
         1598  +  }else{
  1582   1599   
  1583   1600       if( pAppend==0 ){
  1584   1601         if( (pParse->nPhrase % 8)==0 ){
  1585   1602           int nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
  1586   1603           Fts5ExprPhrase **apNew;
  1587   1604           apNew = (Fts5ExprPhrase**)sqlite3_realloc(pParse->apPhrase, nByte);
  1588   1605           if( apNew==0 ){
................................................................................
  1591   1608             return 0;
  1592   1609           }
  1593   1610           pParse->apPhrase = apNew;
  1594   1611         }
  1595   1612         pParse->nPhrase++;
  1596   1613       }
  1597   1614   
         1615  +    if( sCtx.pPhrase==0 ){
         1616  +      /* This happens when parsing a token or quoted phrase that contains
         1617  +      ** no token characters at all. (e.g ... MATCH '""'). */
         1618  +      sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5ExprPhrase));
         1619  +    }else if( sCtx.pPhrase->nTerm ){
         1620  +      sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = bPrefix;
         1621  +    }
  1598   1622       pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase;
  1599         -    assert( sCtx.pPhrase->nTerm>0 );
  1600         -    sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = bPrefix;
  1601   1623     }
  1602   1624   
  1603   1625     return sCtx.pPhrase;
  1604   1626   }
  1605   1627   
  1606   1628   /*
  1607   1629   ** Create a new FTS5 expression by cloning phrase iPhrase of the
................................................................................
  1689   1711   }
  1690   1712   
  1691   1713   void sqlite3Fts5ParseSetDistance(
  1692   1714     Fts5Parse *pParse, 
  1693   1715     Fts5ExprNearset *pNear,
  1694   1716     Fts5Token *p
  1695   1717   ){
  1696         -  int nNear = 0;
  1697         -  int i;
  1698         -  if( p->n ){
  1699         -    for(i=0; i<p->n; i++){
  1700         -      char c = (char)p->p[i];
  1701         -      if( c<'0' || c>'9' ){
  1702         -        sqlite3Fts5ParseError(
  1703         -            pParse, "expected integer, got \"%.*s\"", p->n, p->p
  1704         -        );
  1705         -        return;
         1718  +  if( pNear ){
         1719  +    int nNear = 0;
         1720  +    int i;
         1721  +    if( p->n ){
         1722  +      for(i=0; i<p->n; i++){
         1723  +        char c = (char)p->p[i];
         1724  +        if( c<'0' || c>'9' ){
         1725  +          sqlite3Fts5ParseError(
         1726  +              pParse, "expected integer, got \"%.*s\"", p->n, p->p
         1727  +              );
         1728  +          return;
         1729  +        }
         1730  +        nNear = nNear * 10 + (p->p[i] - '0');
  1706   1731         }
  1707         -      nNear = nNear * 10 + (p->p[i] - '0');
         1732  +    }else{
         1733  +      nNear = FTS5_DEFAULT_NEARDIST;
  1708   1734       }
  1709         -  }else{
  1710         -    nNear = FTS5_DEFAULT_NEARDIST;
         1735  +    pNear->nNear = nNear;
  1711   1736     }
  1712         -  pNear->nNear = nNear;
  1713   1737   }
  1714   1738   
  1715   1739   /*
  1716   1740   ** The second argument passed to this function may be NULL, or it may be
  1717   1741   ** an existing Fts5Colset object. This function returns a pointer to
  1718   1742   ** a new colset object containing the contents of (p) with new value column
  1719   1743   ** number iCol appended. 
................................................................................
  1892   1916         pRet->eType = eType;
  1893   1917         pRet->pNear = pNear;
  1894   1918         fts5ExprAssignXNext(pRet);
  1895   1919         if( eType==FTS5_STRING ){
  1896   1920           int iPhrase;
  1897   1921           for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
  1898   1922             pNear->apPhrase[iPhrase]->pNode = pRet;
         1923  +          if( pNear->apPhrase[iPhrase]->nTerm==0 ){
         1924  +            pRet->xNext = 0;
         1925  +            pRet->eType = FTS5_EOF;
         1926  +          }
  1899   1927           }
  1900   1928   
  1901   1929           if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL 
  1902         -         && (pNear->nPhrase!=1 || pNear->apPhrase[0]->nTerm!=1)
         1930  +         && (pNear->nPhrase!=1 || pNear->apPhrase[0]->nTerm>1)
  1903   1931           ){
  1904   1932             assert( pParse->rc==SQLITE_OK );
  1905   1933             pParse->rc = SQLITE_ERROR;
  1906   1934             assert( pParse->zErr==0 );
  1907   1935             pParse->zErr = sqlite3_mprintf(
  1908   1936                 "fts5: %s queries are not supported (detail!=full)", 
  1909   1937                 pNear->nPhrase==1 ? "phrase": "NEAR"
................................................................................
  1921   1949   
  1922   1950     if( pRet==0 ){
  1923   1951       assert( pParse->rc!=SQLITE_OK );
  1924   1952       sqlite3Fts5ParseNodeFree(pLeft);
  1925   1953       sqlite3Fts5ParseNodeFree(pRight);
  1926   1954       sqlite3Fts5ParseNearsetFree(pNear);
  1927   1955     }
         1956  +  return pRet;
         1957  +}
         1958  +
         1959  +Fts5ExprNode *sqlite3Fts5ParseImplicitAnd(
         1960  +  Fts5Parse *pParse,              /* Parse context */
         1961  +  Fts5ExprNode *pLeft,            /* Left hand child expression */
         1962  +  Fts5ExprNode *pRight            /* Right hand child expression */
         1963  +){
         1964  +  Fts5ExprNode *pRet = 0;
         1965  +  Fts5ExprNode *pPrev;
         1966  +
         1967  +  if( pParse->rc ){
         1968  +    sqlite3Fts5ParseNodeFree(pLeft);
         1969  +    sqlite3Fts5ParseNodeFree(pRight);
         1970  +  }else{
         1971  +
         1972  +    assert( pLeft->eType==FTS5_STRING 
         1973  +        || pLeft->eType==FTS5_TERM
         1974  +        || pLeft->eType==FTS5_EOF
         1975  +        || pLeft->eType==FTS5_AND
         1976  +    );
         1977  +    assert( pRight->eType==FTS5_STRING 
         1978  +        || pRight->eType==FTS5_TERM 
         1979  +        || pRight->eType==FTS5_EOF 
         1980  +    );
         1981  +
         1982  +    if( pLeft->eType==FTS5_AND ){
         1983  +      pPrev = pLeft->apChild[pLeft->nChild-1];
         1984  +    }else{
         1985  +      pPrev = pLeft;
         1986  +    }
         1987  +    assert( pPrev->eType==FTS5_STRING 
         1988  +        || pPrev->eType==FTS5_TERM 
         1989  +        || pPrev->eType==FTS5_EOF 
         1990  +        );
         1991  +
         1992  +    if( pRight->eType==FTS5_EOF ){
         1993  +      assert( pParse->apPhrase[pParse->nPhrase-1]==pRight->pNear->apPhrase[0] );
         1994  +      sqlite3Fts5ParseNodeFree(pRight);
         1995  +      pRet = pLeft;
         1996  +      pParse->nPhrase--;
         1997  +    }
         1998  +    else if( pPrev->eType==FTS5_EOF ){
         1999  +      Fts5ExprPhrase **ap;
         2000  +
         2001  +      if( pPrev==pLeft ){
         2002  +        pRet = pRight;
         2003  +      }else{
         2004  +        pLeft->apChild[pLeft->nChild-1] = pRight;
         2005  +        pRet = pLeft;
         2006  +      }
         2007  +
         2008  +      ap = &pParse->apPhrase[pParse->nPhrase-1-pRight->pNear->nPhrase];
         2009  +      assert( ap[0]==pPrev->pNear->apPhrase[0] );
         2010  +      memmove(ap, &ap[1], sizeof(Fts5ExprPhrase*)*pRight->pNear->nPhrase);
         2011  +      pParse->nPhrase--;
         2012  +
         2013  +      sqlite3Fts5ParseNodeFree(pPrev);
         2014  +    }
         2015  +    else{
         2016  +      pRet = sqlite3Fts5ParseNode(pParse, FTS5_AND, pLeft, pRight, 0);
         2017  +    }
         2018  +  }
         2019  +
  1928   2020     return pRet;
  1929   2021   }
  1930   2022   
  1931   2023   static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
  1932   2024     int nByte = 0;
  1933   2025     Fts5ExprTerm *p;
  1934   2026     char *zQuoted;
................................................................................
  2058   2150     }
  2059   2151   
  2060   2152     return zRet;
  2061   2153   }
  2062   2154   
  2063   2155   static char *fts5ExprPrint(Fts5Config *pConfig, Fts5ExprNode *pExpr){
  2064   2156     char *zRet = 0;
         2157  +  if( pExpr->eType==0 ){
         2158  +    return sqlite3_mprintf("\"\"");
         2159  +  }else
  2065   2160     if( pExpr->eType==FTS5_STRING || pExpr->eType==FTS5_TERM ){
  2066   2161       Fts5ExprNearset *pNear = pExpr->pNear;
  2067   2162       int i; 
  2068   2163       int iTerm;
  2069   2164   
  2070   2165       if( pNear->pColset ){
  2071   2166         int iCol = pNear->pColset->aiCol[0];
................................................................................
  2118   2213       for(i=0; i<pExpr->nChild; i++){
  2119   2214         char *z = fts5ExprPrint(pConfig, pExpr->apChild[i]);
  2120   2215         if( z==0 ){
  2121   2216           sqlite3_free(zRet);
  2122   2217           zRet = 0;
  2123   2218         }else{
  2124   2219           int e = pExpr->apChild[i]->eType;
  2125         -        int b = (e!=FTS5_STRING && e!=FTS5_TERM);
         2220  +        int b = (e!=FTS5_STRING && e!=FTS5_TERM && e!=FTS5_EOF);
  2126   2221           zRet = fts5PrintfAppend(zRet, "%s%s%z%s", 
  2127   2222               (i==0 ? "" : zOp),
  2128   2223               (b?"(":""), z, (b?")":"")
  2129   2224           );
  2130   2225         }
  2131   2226         if( zRet==0 ) break;
  2132   2227       }

Changes to ext/fts5/fts5_index.c.

  4175   4175     fts5MultiIterFree(pIter);
  4176   4176     fts5BufferFree(&term);
  4177   4177     if( pnRem ) *pnRem -= writer.nLeafWritten;
  4178   4178   }
  4179   4179   
  4180   4180   /*
  4181   4181   ** Do up to nPg pages of automerge work on the index.
         4182  +**
         4183  +** Return true if any changes were actually made, or false otherwise.
  4182   4184   */
  4183         -static void fts5IndexMerge(
         4185  +static int fts5IndexMerge(
  4184   4186     Fts5Index *p,                   /* FTS5 backend object */
  4185   4187     Fts5Structure **ppStruct,       /* IN/OUT: Current structure of index */
  4186         -  int nPg                         /* Pages of work to do */
         4188  +  int nPg,                        /* Pages of work to do */
         4189  +  int nMin                        /* Minimum number of segments to merge */
  4187   4190   ){
  4188   4191     int nRem = nPg;
         4192  +  int bRet = 0;
  4189   4193     Fts5Structure *pStruct = *ppStruct;
  4190   4194     while( nRem>0 && p->rc==SQLITE_OK ){
  4191   4195       int iLvl;                   /* To iterate through levels */
  4192   4196       int iBestLvl = 0;           /* Level offering the most input segments */
  4193   4197       int nBest = 0;              /* Number of input segments on best level */
  4194   4198   
  4195   4199       /* Set iBestLvl to the level to read input segments from. */
................................................................................
  4212   4216       /* If nBest is still 0, then the index must be empty. */
  4213   4217   #ifdef SQLITE_DEBUG
  4214   4218       for(iLvl=0; nBest==0 && iLvl<pStruct->nLevel; iLvl++){
  4215   4219         assert( pStruct->aLevel[iLvl].nSeg==0 );
  4216   4220       }
  4217   4221   #endif
  4218   4222   
  4219         -    if( nBest<p->pConfig->nAutomerge 
  4220         -        && pStruct->aLevel[iBestLvl].nMerge==0 
  4221         -      ){
         4223  +    if( nBest<nMin && pStruct->aLevel[iBestLvl].nMerge==0 ){
  4222   4224         break;
  4223   4225       }
         4226  +    bRet = 1;
  4224   4227       fts5IndexMergeLevel(p, &pStruct, iBestLvl, &nRem);
  4225   4228       if( p->rc==SQLITE_OK && pStruct->aLevel[iBestLvl].nMerge==0 ){
  4226   4229         fts5StructurePromote(p, iBestLvl+1, pStruct);
  4227   4230       }
  4228   4231     }
  4229   4232     *ppStruct = pStruct;
         4233  +  return bRet;
  4230   4234   }
  4231   4235   
  4232   4236   /*
  4233   4237   ** A total of nLeaf leaf pages of data has just been flushed to a level-0
  4234   4238   ** segment. This function updates the write-counter accordingly and, if
  4235   4239   ** necessary, performs incremental merge work.
  4236   4240   **
................................................................................
  4250   4254   
  4251   4255       /* Update the write-counter. While doing so, set nWork. */
  4252   4256       nWrite = pStruct->nWriteCounter;
  4253   4257       nWork = (int)(((nWrite + nLeaf) / p->nWorkUnit) - (nWrite / p->nWorkUnit));
  4254   4258       pStruct->nWriteCounter += nLeaf;
  4255   4259       nRem = (int)(p->nWorkUnit * nWork * pStruct->nLevel);
  4256   4260   
  4257         -    fts5IndexMerge(p, ppStruct, nRem);
         4261  +    fts5IndexMerge(p, ppStruct, nRem, p->pConfig->nAutomerge);
  4258   4262     }
  4259   4263   }
  4260   4264   
  4261   4265   static void fts5IndexCrisismerge(
  4262   4266     Fts5Index *p,                   /* FTS5 backend object */
  4263   4267     Fts5Structure **ppStruct        /* IN/OUT: Current structure of index */
  4264   4268   ){
................................................................................
  4470   4474     if( p->nPendingData ){
  4471   4475       assert( p->pHash );
  4472   4476       p->nPendingData = 0;
  4473   4477       fts5FlushOneHash(p);
  4474   4478     }
  4475   4479   }
  4476   4480   
  4477         -
  4478         -int sqlite3Fts5IndexOptimize(Fts5Index *p){
  4479         -  Fts5Structure *pStruct;
         4481  +static Fts5Structure *fts5IndexOptimizeStruct(
         4482  +  Fts5Index *p, 
         4483  +  Fts5Structure *pStruct
         4484  +){
  4480   4485     Fts5Structure *pNew = 0;
  4481         -  int nSeg = 0;
  4482         -
  4483         -  assert( p->rc==SQLITE_OK );
  4484         -  fts5IndexFlush(p);
  4485         -  pStruct = fts5StructureRead(p);
  4486         -
  4487         -  if( pStruct ){
  4488         -    assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) );
  4489         -    nSeg = pStruct->nSegment;
  4490         -    if( nSeg>1 ){
  4491         -      int nByte = sizeof(Fts5Structure);
  4492         -      nByte += (pStruct->nLevel+1) * sizeof(Fts5StructureLevel);
  4493         -      pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte);
  4494         -    }
  4495         -  }
         4486  +  int nByte = sizeof(Fts5Structure);
         4487  +  int nSeg = pStruct->nSegment;
         4488  +  int i;
         4489  +
         4490  +  /* Figure out if this structure requires optimization. A structure does
         4491  +  ** not require optimization if either:
         4492  +  **
         4493  +  **  + it consists of fewer than two segments, or 
         4494  +  **  + all segments are on the same level, or
         4495  +  **  + all segments except one are currently inputs to a merge operation.
         4496  +  **
         4497  +  ** In the first case, return NULL. In the second, increment the ref-count
         4498  +  ** on *pStruct and return a copy of the pointer to it.
         4499  +  */
         4500  +  if( nSeg<2 ) return 0;
         4501  +  for(i=0; i<pStruct->nLevel; i++){
         4502  +    int nThis = pStruct->aLevel[i].nSeg;
         4503  +    if( nThis==nSeg || (nThis==nSeg-1 && pStruct->aLevel[i].nMerge==nThis) ){
         4504  +      fts5StructureRef(pStruct);
         4505  +      return pStruct;
         4506  +    }
         4507  +    assert( pStruct->aLevel[i].nMerge<=nThis );
         4508  +  }
         4509  +
         4510  +  nByte += (pStruct->nLevel+1) * sizeof(Fts5StructureLevel);
         4511  +  pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte);
         4512  +
  4496   4513     if( pNew ){
  4497   4514       Fts5StructureLevel *pLvl;
  4498   4515       int nByte = nSeg * sizeof(Fts5StructureSegment);
  4499   4516       pNew->nLevel = pStruct->nLevel+1;
  4500   4517       pNew->nRef = 1;
  4501   4518       pNew->nWriteCounter = pStruct->nWriteCounter;
  4502   4519       pLvl = &pNew->aLevel[pStruct->nLevel];
................................................................................
  4516   4533         pNew->nSegment = pLvl->nSeg = nSeg;
  4517   4534       }else{
  4518   4535         sqlite3_free(pNew);
  4519   4536         pNew = 0;
  4520   4537       }
  4521   4538     }
  4522   4539   
         4540  +  return pNew;
         4541  +}
         4542  +
         4543  +int sqlite3Fts5IndexOptimize(Fts5Index *p){
         4544  +  Fts5Structure *pStruct;
         4545  +  Fts5Structure *pNew = 0;
         4546  +
         4547  +  assert( p->rc==SQLITE_OK );
         4548  +  fts5IndexFlush(p);
         4549  +  pStruct = fts5StructureRead(p);
         4550  +
         4551  +  if( pStruct ){
         4552  +    pNew = fts5IndexOptimizeStruct(p, pStruct);
         4553  +  }
         4554  +  fts5StructureRelease(pStruct);
         4555  +
         4556  +  assert( pNew==0 || pNew->nSegment>0 );
  4523   4557     if( pNew ){
  4524         -    int iLvl = pNew->nLevel-1;
         4558  +    int iLvl;
         4559  +    for(iLvl=0; pNew->aLevel[iLvl].nSeg==0; iLvl++){}
  4525   4560       while( p->rc==SQLITE_OK && pNew->aLevel[iLvl].nSeg>0 ){
  4526   4561         int nRem = FTS5_OPT_WORK_UNIT;
  4527   4562         fts5IndexMergeLevel(p, &pNew, iLvl, &nRem);
  4528   4563       }
  4529   4564   
  4530   4565       fts5StructureWrite(p, pNew);
  4531   4566       fts5StructureRelease(pNew);
  4532   4567     }
  4533   4568   
  4534         -  fts5StructureRelease(pStruct);
  4535   4569     return fts5IndexReturn(p); 
  4536   4570   }
  4537   4571   
         4572  +/*
         4573  +** This is called to implement the special "VALUES('merge', $nMerge)"
         4574  +** INSERT command.
         4575  +*/
  4538   4576   int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){
  4539         -  Fts5Structure *pStruct;
  4540         -
  4541         -  pStruct = fts5StructureRead(p);
  4542         -  if( pStruct && pStruct->nLevel ){
  4543         -    fts5IndexMerge(p, &pStruct, nMerge);
  4544         -    fts5StructureWrite(p, pStruct);
         4577  +  Fts5Structure *pStruct = fts5StructureRead(p);
         4578  +  if( pStruct ){
         4579  +    int nMin = p->pConfig->nUsermerge;
         4580  +    if( nMerge<0 ){
         4581  +      Fts5Structure *pNew = fts5IndexOptimizeStruct(p, pStruct);
         4582  +      fts5StructureRelease(pStruct);
         4583  +      pStruct = pNew;
         4584  +      nMin = 2;
         4585  +      nMerge = nMerge*-1;
         4586  +    }
         4587  +    if( pStruct && pStruct->nLevel ){
         4588  +      if( fts5IndexMerge(p, &pStruct, nMerge, nMin) ){
         4589  +        fts5StructureWrite(p, pStruct);
         4590  +      }
         4591  +    }
         4592  +    fts5StructureRelease(pStruct);
  4545   4593     }
  4546         -  fts5StructureRelease(pStruct);
  4547         -
  4548   4594     return fts5IndexReturn(p);
  4549   4595   }
  4550   4596   
  4551   4597   static void fts5AppendRowid(
  4552   4598     Fts5Index *p,
  4553   4599     i64 iDelta,
  4554   4600     Fts5Iter *pUnused,

Changes to ext/fts5/fts5_main.c.

  1507   1507         pTab->base.zErrMsg = sqlite3_mprintf(
  1508   1508             "cannot %s contentless fts5 table: %s", 
  1509   1509             (nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName
  1510   1510         );
  1511   1511         rc = SQLITE_ERROR;
  1512   1512       }
  1513   1513   
  1514         -    /* Case 1: DELETE */
         1514  +    /* DELETE */
  1515   1515       else if( nArg==1 ){
  1516   1516         i64 iDel = sqlite3_value_int64(apVal[0]);  /* Rowid to delete */
  1517   1517         rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0);
  1518   1518       }
  1519   1519   
  1520         -    /* Case 2: INSERT */
         1520  +    /* INSERT */
  1521   1521       else if( eType0!=SQLITE_INTEGER ){     
  1522   1522         /* If this is a REPLACE, first remove the current entry (if any) */
  1523   1523         if( eConflict==SQLITE_REPLACE 
  1524   1524          && sqlite3_value_type(apVal[1])==SQLITE_INTEGER 
  1525   1525         ){
  1526   1526           i64 iNew = sqlite3_value_int64(apVal[1]);  /* Rowid to delete */
  1527   1527           rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
  1528   1528         }
  1529   1529         fts5StorageInsert(&rc, pTab, apVal, pRowid);
  1530   1530       }
  1531   1531   
  1532         -    /* Case 2: UPDATE */
         1532  +    /* UPDATE */
  1533   1533       else{
  1534   1534         i64 iOld = sqlite3_value_int64(apVal[0]);  /* Old rowid */
  1535   1535         i64 iNew = sqlite3_value_int64(apVal[1]);  /* New rowid */
  1536   1536         if( iOld!=iNew ){
  1537   1537           if( eConflict==SQLITE_REPLACE ){
  1538   1538             rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
  1539   1539             if( rc==SQLITE_OK ){

Changes to ext/fts5/fts5_test_mi.c.

    64     64   
    65     65   
    66     66   /*
    67     67   ** Return a pointer to the fts5_api pointer for database connection db.
    68     68   ** If an error occurs, return NULL and leave an error in the database 
    69     69   ** handle (accessible using sqlite3_errcode()/errmsg()).
    70     70   */
    71         -static fts5_api *fts5_api_from_db(sqlite3 *db){
    72         -  fts5_api *pRet = 0;
           71  +static int fts5_api_from_db(sqlite3 *db, fts5_api **ppApi){
    73     72     sqlite3_stmt *pStmt = 0;
           73  +  int rc;
    74     74   
    75         -  if( SQLITE_OK==sqlite3_prepare(db, "SELECT fts5()", -1, &pStmt, 0)
    76         -   && SQLITE_ROW==sqlite3_step(pStmt) 
    77         -   && sizeof(pRet)==sqlite3_column_bytes(pStmt, 0)
    78         -  ){
    79         -    memcpy(&pRet, sqlite3_column_blob(pStmt, 0), sizeof(pRet));
           75  +  *ppApi = 0;
           76  +  rc = sqlite3_prepare(db, "SELECT fts5()", -1, &pStmt, 0);
           77  +  if( rc==SQLITE_OK ){
           78  +    if( SQLITE_ROW==sqlite3_step(pStmt) 
           79  +        && sizeof(fts5_api*)==sqlite3_column_bytes(pStmt, 0)
           80  +      ){
           81  +      memcpy(ppApi, sqlite3_column_blob(pStmt, 0), sizeof(fts5_api*));
           82  +    }
           83  +    rc = sqlite3_finalize(pStmt);
    80     84     }
    81         -  sqlite3_finalize(pStmt);
    82         -  return pRet;
           85  +
           86  +  return rc;
    83     87   }
    84     88   
    85     89   
    86     90   /*
    87     91   ** Argument f should be a flag accepted by matchinfo() (a valid character
    88     92   ** in the string passed as the second argument). If it is not, -1 is 
    89     93   ** returned. Otherwise, if f is a valid matchinfo flag, the value returned
................................................................................
   395    399   int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){
   396    400     int rc;                         /* Return code */
   397    401     fts5_api *pApi;                 /* FTS5 API functions */
   398    402   
   399    403     /* Extract the FTS5 API pointer from the database handle. The 
   400    404     ** fts5_api_from_db() function above is copied verbatim from the 
   401    405     ** FTS5 documentation. Refer there for details. */
   402         -  pApi = fts5_api_from_db(db);
          406  +  rc = fts5_api_from_db(db, &pApi);
          407  +  if( rc!=SQLITE_OK ) return rc;
   403    408   
   404    409     /* If fts5_api_from_db() returns NULL, then either FTS5 is not registered
   405    410     ** with this database handle, or an error (OOM perhaps?) has occurred.
   406    411     **
   407    412     ** Also check that the fts5_api object is version 2 or newer.  
   408    413     */ 
   409    414     if( pApi==0 || pApi->iVersion<2 ){

Changes to ext/fts5/fts5parse.y.

   100    100   }
   101    101   
   102    102   expr(A) ::= LP expr(X) RP. {A = X;}
   103    103   expr(A) ::= exprlist(X).   {A = X;}
   104    104   
   105    105   exprlist(A) ::= cnearset(X). {A = X;}
   106    106   exprlist(A) ::= exprlist(X) cnearset(Y). {
   107         -  A = sqlite3Fts5ParseNode(pParse, FTS5_AND, X, Y, 0);
          107  +  A = sqlite3Fts5ParseImplicitAnd(pParse, X, Y);
   108    108   }
   109    109   
   110    110   cnearset(A) ::= nearset(X). { 
   111    111     A = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, X); 
   112    112   }
   113    113   cnearset(A) ::= colset(X) COLON nearset(Y). { 
   114    114     sqlite3Fts5ParseSetColset(pParse, Y, X);

Changes to ext/fts5/test/fts5_common.tcl.

   154    154   
   155    155       fts5_test_queryphrase
   156    156       fts5_test_phrasecount
   157    157     } {
   158    158       sqlite3_fts5_create_function $db $f $f
   159    159     }
   160    160   }
          161  +
          162  +proc fts5_segcount {tbl} {
          163  +  set N 0
          164  +  foreach n [fts5_level_segs $tbl] { incr N $n }
          165  +  set N
          166  +}
   161    167   
   162    168   proc fts5_level_segs {tbl} {
   163    169     set sql "SELECT fts5_decode(rowid,block) aS r FROM ${tbl}_data WHERE rowid=10"
   164    170     set ret [list]
   165    171     foreach L [lrange [db one $sql] 1 end] {
   166    172       lappend ret [expr [llength $L] - 3]
   167    173     }

Changes to ext/fts5/test/fts5config.test.

   242    242     set res [list 1 {malformed detail=... directive}]
   243    243     do_catchsql_test 11.$tn "CREATE VIRTUAL TABLE f1 USING fts5(x, $opt)" $res
   244    244   }
   245    245   
   246    246   do_catchsql_test 12.1 {
   247    247     INSERT INTO t1(t1, rank) VALUES('rank', NULL);;
   248    248   } {1 {SQL logic error or missing database}}
          249  +
          250  +#-------------------------------------------------------------------------
          251  +# errors in the 'usermerge' option
          252  +#
          253  +do_execsql_test 13.0 {
          254  +  CREATE VIRTUAL TABLE tt USING fts5(ttt);
          255  +}
          256  +foreach {tn val} {
          257  +  1     -1
          258  +  2     4.2
          259  +  3     17
          260  +  4     1
          261  +} {
          262  +  set sql "INSERT INTO tt(tt, rank) VALUES('usermerge', $val)"
          263  +  do_catchsql_test 13.$tn $sql {1 {SQL logic error or missing database}}
          264  +}
   249    265   
   250    266   finish_test
   251    267   

Changes to ext/fts5/test/fts5eb.test.

    29     29     do_execsql_test $tn {SELECT fts5_expr($se_expr)} [list $res]
    30     30   }
    31     31   
    32     32   foreach {tn expr res} {
    33     33     1  {abc}                            {"abc"}
    34     34     2  {abc ""}                         {"abc"}
    35     35     3  {""}                             {}
    36         -  4  {abc OR ""}                      {"abc"}
    37         -  5  {abc NOT ""}                     {"abc"}
    38         -  6  {abc AND ""}                     {"abc"}
    39         -  7  {"" OR abc}                      {"abc"}
    40         -  8  {"" NOT abc}                     {"abc"}
    41         -  9  {"" AND abc}                     {"abc"}
           36  +  4  {abc OR ""}                      {"abc" OR ""}
           37  +  5  {abc NOT ""}                     {"abc" NOT ""}
           38  +  6  {abc AND ""}                     {"abc" AND ""}
           39  +  7  {"" OR abc}                      {"" OR "abc"}
           40  +  8  {"" NOT abc}                     {"" NOT "abc"}
           41  +  9  {"" AND abc}                     {"" AND "abc"}
    42     42     10 {abc + "" + def}                 {"abc" + "def"}
    43     43     11 {abc "" def}                     {"abc" AND "def"}
    44     44     12 {r+e OR w}                       {"r" + "e" OR "w"}
    45     45   
    46     46     13 {a AND b NOT c}                  {"a" AND ("b" NOT "c")}
    47     47     14 {a OR b NOT c}                   {"a" OR ("b" NOT "c")}
    48     48     15 {a NOT b AND c}                  {("a" NOT "b") AND "c"}

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

    50     50     if {[detail_is_none]==0} {
    51     51       do_faultsim_test 3 -faults oom-* -body {
    52     52         execsql { SELECT rowid FROM t1('b:2') }
    53     53       } -test {
    54     54         faultsim_test_result {0 {1 3}} {1 SQLITE_NOMEM}
    55     55       }
    56     56     }
           57  +
    57     58   } ;# foreach_detail_mode...
           59  +
           60  +
           61  +do_execsql_test 4.0 {
           62  +  CREATE VIRTUAL TABLE x2 USING fts5(a);
           63  +  INSERT INTO x2(x2, rank) VALUES('crisismerge', 2);
           64  +  INSERT INTO x2(x2, rank) VALUES('pgsz', 32);
           65  +  INSERT INTO x2 VALUES('a b c d');
           66  +  INSERT INTO x2 VALUES('e f g h');
           67  +  INSERT INTO x2 VALUES('i j k l');
           68  +  INSERT INTO x2 VALUES('m n o p');
           69  +  INSERT INTO x2 VALUES('q r s t');
           70  +  INSERT INTO x2 VALUES('u v w x');
           71  +  INSERT INTO x2 VALUES('y z a b');
           72  +}
           73  +faultsim_save_and_close
           74  +
           75  +do_faultsim_test 4 -faults oom-* -prep {
           76  +  faultsim_restore_and_reopen
           77  +} -body {
           78  +  execsql { INSERT INTO x2(x2) VALUES('optimize') }
           79  +} -test {
           80  +  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
           81  +}
           82  +
    58     83   
    59     84   finish_test
    60     85   

Added ext/fts5/test/fts5fuzz1.test.

            1  +# 2014 June 17
            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 script is testing the FTS5 module.
           13  +#
           14  +
           15  +source [file join [file dirname [info script]] fts5_common.tcl]
           16  +return_if_no_fts5
           17  +set testprefix fts5fuzz1
           18  +
           19  +
           20  +#-------------------------------------------------------------------------
           21  +reset_db
           22  +do_catchsql_test 1.1 {
           23  +  CREATE VIRTUAL TABLE f1 USING fts5(a b);
           24  +} {/1 {parse error in.*}/}
           25  +
           26  +
           27  +#-------------------------------------------------------------------------
           28  +reset_db
           29  +do_execsql_test 2.1 {
           30  +  CREATE VIRTUAL TABLE f1 USING fts5(a, b);
           31  +  INSERT INTO f1 VALUES('a b', 'c d');
           32  +  INSERT INTO f1 VALUES('e f', 'a b');
           33  +}
           34  +
           35  +do_execsql_test 2.2.1 {
           36  +  SELECT rowid FROM f1('""');
           37  +} {}
           38  +
           39  +do_execsql_test 2.2.2 {
           40  +  SELECT rowid FROM f1('"" AND a');
           41  +} {}
           42  +
           43  +
           44  +do_execsql_test 2.2.3 {
           45  +  SELECT rowid FROM f1('"" a');
           46  +} {1 2}
           47  +
           48  +do_execsql_test 2.2.4 {
           49  +  SELECT rowid FROM f1('"" OR a');
           50  +} {1 2}
           51  +
           52  +do_execsql_test 2.3 {
           53  +  SELECT a, b FROM f1('NEAR("")');
           54  +} {}
           55  +
           56  +do_execsql_test 2.4 {
           57  +  SELECT a, b FROM f1('NEAR("", 5)');
           58  +} {}
           59  +
           60  +do_execsql_test 2.5 {
           61  +  SELECT a, b FROM f1('NEAR("" c, 5)');
           62  +} {{a b} {c d}}
           63  +
           64  +do_execsql_test 2.6 {
           65  +  SELECT a, b FROM f1('NEAR("" c d, 5)');
           66  +} {{a b} {c d}}
           67  +
           68  +do_execsql_test 2.7 {
           69  +  SELECT a, b FROM f1('NEAR(c d, 5)');
           70  +} {{a b} {c d}}
           71  +
           72  +do_execsql_test 2.8 {
           73  +  SELECT rowid FROM f1('NEAR("a" "b", 5)');
           74  +} {1 2}
           75  +
           76  +#-------------------------------------------------------------------------
           77  +reset_db
           78  +do_execsql_test 3.2 {
           79  +  CREATE VIRTUAL TABLE f2 USING fts5(o, t, tokenize="ascii separators abc");
           80  +  SELECT * FROM f2('a+4');
           81  +} {}
           82  +
           83  +
           84  +
           85  +#-------------------------------------------------------------------------
           86  +reset_db
           87  +do_catchsql_test 4.1 {
           88  +  CREATE VIRTUAL TABLE f2 USING fts5(o, t);
           89  +  SELECT * FROM f2('(8 AND 9)`AND 10');
           90  +} {1 {fts5: syntax error near "`"}}
           91  +
           92  +finish_test
           93  +

Changes to ext/fts5/test/fts5merge.test.

    41     41   
    42     42       WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<$::nRowPerSeg)
    43     43         INSERT INTO x8 SELECT repeat('x y ', i % 16) FROM ii;
    44     44   
    45     45       WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<$::nRowPerSeg)
    46     46         INSERT INTO x8 SELECT repeat('x y ', i % 16) FROM ii;
    47     47   
    48         -    INSERT INTO x8(x8, rank) VALUES('automerge', 2);
           48  +    INSERT INTO x8(x8, rank) VALUES('usermerge', 2);
    49     49     }
    50     50   
    51     51     for {set tn 1} {[lindex [fts5_level_segs x8] 0]>0} {incr tn} {
    52     52       do_execsql_test $testname.$tn {
    53     53         INSERT INTO x8(x8, rank) VALUES('merge', 1);
    54     54         INSERT INTO x8(x8) VALUES('integrity-check');
    55     55       }
................................................................................
    80     80   
    81     81     set ::nRow $nRow
    82     82     do_test $testname.1 {
    83     83       for {set i 0} {$i < $::nRow} {incr i} {
    84     84         execsql { INSERT INTO x8 VALUES( rnddoc(($i%16) + 5) ) }
    85     85         while {[not_merged x8]} {
    86     86           execsql {
    87         -          INSERT INTO x8(x8, rank) VALUES('automerge', 2);
           87  +          INSERT INTO x8(x8, rank) VALUES('usermerge', 2);
    88     88             INSERT INTO x8(x8, rank) VALUES('merge', 1);
    89         -          INSERT INTO x8(x8, rank) VALUES('automerge', 16);
           89  +          INSERT INTO x8(x8, rank) VALUES('usermerge', 16);
    90     90             INSERT INTO x8(x8) VALUES('integrity-check');
    91     91           }
    92     92         }
    93     93       }
    94     94     } {}
    95     95   }
    96     96   proc not_merged {tbl} {
................................................................................
   100    100   }
   101    101   
   102    102   do_merge2_test 2.1    5
   103    103   do_merge2_test 2.2   10
   104    104   do_merge2_test 2.3   20
   105    105   
   106    106   #-------------------------------------------------------------------------
   107         -# Test that an auto-merge will complete any merge that has already been
          107  +# Test that a merge will complete any merge that has already been
   108    108   # started, even if the number of input segments is less than the current
   109         -# value of the 'automerge' configuration parameter.
          109  +# value of the 'usermerge' configuration parameter.
   110    110   #
   111    111   db func rnddoc fts5_rnddoc
   112    112   
   113    113   do_execsql_test 3.1 {
   114    114     DROP TABLE IF EXISTS x8;
   115    115     CREATE VIRTUAL TABLE x8 USING fts5(i);
   116    116     INSERT INTO x8(x8, rank) VALUES('pgsz', 32);
   117    117     INSERT INTO x8 VALUES(rnddoc(100));
   118    118     INSERT INTO x8 VALUES(rnddoc(100));
   119    119   }
   120    120   do_test 3.2 {
   121    121     execsql {
   122         -    INSERT INTO x8(x8, rank) VALUES('automerge', 4);
          122  +    INSERT INTO x8(x8, rank) VALUES('usermerge', 4);
   123    123       INSERT INTO x8(x8, rank) VALUES('merge', 1);
   124    124     }
   125    125     fts5_level_segs x8
   126    126   } {2}
   127    127   
   128    128   do_test 3.3 {
   129    129     execsql {
   130         -    INSERT INTO x8(x8, rank) VALUES('automerge', 2);
          130  +    INSERT INTO x8(x8, rank) VALUES('usermerge', 2);
   131    131       INSERT INTO x8(x8, rank) VALUES('merge', 1);
   132    132     }
   133    133     fts5_level_segs x8
   134    134   } {2 1}
   135    135   
   136    136   do_test 3.4 {
   137         -  execsql { INSERT INTO x8(x8, rank) VALUES('automerge', 4) }
          137  +  execsql { INSERT INTO x8(x8, rank) VALUES('usermerge', 4) }
   138    138     while {[not_merged x8]} {
   139    139       execsql { INSERT INTO x8(x8, rank) VALUES('merge', 1) }
   140    140     }
   141    141     fts5_level_segs x8
   142    142   } {0 1}
   143    143   
   144    144   #-------------------------------------------------------------------------
................................................................................
   172    172     }
   173    173   
   174    174     do_execsql_test 4.$tn.3 {
   175    175       WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100)
   176    176         INSERT INTO x8 SELECT mydoc() FROM ii;
   177    177       WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100)
   178    178         INSERT INTO x8 SELECT mydoc() FROM ii;
   179         -    INSERT INTO x8(x8, rank) VALUES('automerge', 2);
          179  +    INSERT INTO x8(x8, rank) VALUES('usermerge', 2);
   180    180     }
   181    181   
   182    182     set expect [mycount]
   183    183       for {set i 0} {$i < 20} {incr i} {
   184    184         do_test 4.$tn.4.$i {
   185    185           execsql { INSERT INTO x8(x8, rank) VALUES('merge', 1); }
   186    186           mycount
   187    187         } $expect
   188    188         break
   189    189       }
   190    190   #  db eval {SELECT fts5_decode(rowid, block) AS r FROM x8_data} { puts $r }
   191    191   }
          192  +
          193  +#-------------------------------------------------------------------------
          194  +# Test that the 'merge' command does not modify the database if there is
          195  +# no work to do. 
          196  +
          197  +do_execsql_test 5.1 {
          198  +  CREATE VIRTUAL TABLE x9 USING fts5(one, two);
          199  +  INSERT INTO x9(x9, rank) VALUES('pgsz', 32);
          200  +  INSERT INTO x9(x9, rank) VALUES('automerge', 2);
          201  +  INSERT INTO x9(x9, rank) VALUES('usermerge', 2);
          202  +  INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
          203  +  INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
          204  +  INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
          205  +  INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
          206  +  INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
          207  +  INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
          208  +  INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
          209  +  INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100));
          210  +}
          211  +
          212  +do_test 5.2 {
          213  +  while 1 {
          214  +    set nChange [db total_changes]
          215  +    execsql { INSERT INTO x9(x9, rank) VALUES('merge', 1); }
          216  +    set nChange [expr [db total_changes] - $nChange]
          217  +    #puts $nChange
          218  +    if {$nChange<2} break
          219  +  }
          220  +} {}
          221  +
          222  +
          223  +#--------------------------------------------------------------------------
          224  +# Test that running 'merge' on an empty database does not cause a 
          225  +# problem.
          226  +#
          227  +reset_db
          228  +do_execsql_test 6.0 {
          229  +  CREATE VIRTUAL TABLE g1 USING fts5(a, b);
          230  +}
          231  +do_execsql_test 6.1 {
          232  +  INSERT INTO g1(g1, rank) VALUES('merge', 10);
          233  +}
          234  +do_execsql_test 6.2 {
          235  +  INSERT INTO g1(g1, rank) VALUES('merge', -10);
          236  +}
          237  +do_execsql_test 6.3 {
          238  +  INSERT INTO g1(g1) VALUES('integrity-check');
          239  +}
          240  +
          241  +
   192    242   
   193    243   finish_test
   194    244   

Changes to ext/fts5/test/fts5optimize.test.

    15     15   set testprefix fts5optimize
    16     16   
    17     17   # If SQLITE_ENABLE_FTS5 is defined, omit this file.
    18     18   ifcapable !fts5 {
    19     19     finish_test
    20     20     return
    21     21   }
           22  +
           23  +#
           24  +# 1.* - Warm body tests for index optimization using ('optimize')
           25  +#
           26  +# 2.* - Warm body tests for index optimization using ('merge', -1)
           27  +#
    22     28   
    23     29   proc rnddoc {nWord} {
    24     30     set vocab {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}
    25     31     set nVocab [llength $vocab]
    26     32     set ret [list]
    27     33     for {set i 0} {$i < $nWord} {incr i} {
    28     34       lappend ret [lindex $vocab [expr {int(rand() * $nVocab)}]]
    29     35     }
    30     36     return $ret
    31     37   }
    32     38   
    33         -
    34     39   foreach {tn nStep} {
    35     40     1 2
    36     41     2 10
    37     42     3 50
    38     43     4 500
    39     44   } {
    40         -if {$tn!=4} continue
    41     45     reset_db
    42     46     db func rnddoc rnddoc
    43     47     do_execsql_test 1.$tn.1 {
    44     48       CREATE VIRTUAL TABLE t1 USING fts5(x, y);
    45     49     }
    46     50     do_test 1.$tn.2 {
    47     51       for {set i 0} {$i < $nStep} {incr i} {
................................................................................
    56     60     do_execsql_test 1.$tn.4 {
    57     61       INSERT INTO t1(t1) VALUES('optimize');
    58     62     }
    59     63   
    60     64     do_execsql_test 1.$tn.5 {
    61     65       INSERT INTO t1(t1) VALUES('integrity-check');
    62     66     }
           67  +
           68  +  do_test 1.$tn.6 { fts5_segcount t1 } 1
    63     69   }
    64     70   
           71  +foreach {tn nStep} {
           72  +  1 2
           73  +  2 10
           74  +  3 50
           75  +  4 500
           76  +} {
           77  +  reset_db
           78  +  db func rnddoc rnddoc
           79  +  do_execsql_test 1.$tn.1 {
           80  +    CREATE VIRTUAL TABLE t1 USING fts5(x, y);
           81  +  }
           82  +  do_test 2.$tn.2 {
           83  +    for {set i 0} {$i < $nStep} {incr i} {
           84  +      execsql { INSERT INTO t1 VALUES( rnddoc(5), rnddoc(5) ) }
           85  +    }
           86  +  } {}
           87  +
           88  +  do_execsql_test 2.$tn.3 {
           89  +    INSERT INTO t1(t1) VALUES('integrity-check');
           90  +  }
           91  +
           92  +  do_test 2.$tn.4 {
           93  +    execsql { INSERT INTO t1(t1, rank) VALUES('merge', -1) }
           94  +    while 1 {
           95  +      set c [db total_changes]
           96  +      execsql { INSERT INTO t1(t1, rank) VALUES('merge', 1) }
           97  +      set c [expr [db total_changes]-$c]
           98  +      if {$c<2} break
           99  +    }
          100  +  } {}
          101  +
          102  +  do_execsql_test 2.$tn.5 {
          103  +    INSERT INTO t1(t1) VALUES('integrity-check');
          104  +  }
          105  +
          106  +  do_test 2.$tn.6 { fts5_segcount t1 } 1
          107  +}
    65    108   finish_test
    66    109   

Changes to ext/misc/spellfix.c.

  1730   1730     sqlite3_value **argv
  1731   1731   ){
  1732   1732     const unsigned char *zIn = sqlite3_value_text(argv[0]);
  1733   1733     int nIn = sqlite3_value_bytes(argv[0]);
  1734   1734     int c, sz;
  1735   1735     int scriptMask = 0;
  1736   1736     int res;
         1737  +  int seenDigit = 0;
  1737   1738   # define SCRIPT_LATIN       0x0001
  1738   1739   # define SCRIPT_CYRILLIC    0x0002
  1739   1740   # define SCRIPT_GREEK       0x0004
  1740   1741   # define SCRIPT_HEBREW      0x0008
  1741   1742   # define SCRIPT_ARABIC      0x0010
  1742   1743   
  1743   1744     while( nIn>0 ){
  1744   1745       c = utf8Read(zIn, nIn, &sz);
  1745   1746       zIn += sz;
  1746   1747       nIn -= sz;
  1747         -    if( c<0x02af && (c>=0x80 || midClass[c&0x7f]<CCLASS_DIGIT) ){
  1748         -      scriptMask |= SCRIPT_LATIN;
         1748  +    if( c<0x02af ){
         1749  +      if( c>=0x80 || midClass[c&0x7f]<CCLASS_DIGIT ){
         1750  +        scriptMask |= SCRIPT_LATIN;
         1751  +      }else if( c>='0' && c<='9' ){
         1752  +        seenDigit = 1;
         1753  +      }
  1749   1754       }else if( c>=0x0400 && c<=0x04ff ){
  1750   1755         scriptMask |= SCRIPT_CYRILLIC;
  1751   1756       }else if( c>=0x0386 && c<=0x03ce ){
  1752   1757         scriptMask |= SCRIPT_GREEK;
  1753   1758       }else if( c>=0x0590 && c<=0x05ff ){
  1754   1759         scriptMask |= SCRIPT_HEBREW;
  1755   1760       }else if( c>=0x0600 && c<=0x06ff ){
  1756   1761         scriptMask |= SCRIPT_ARABIC;
  1757   1762       }
  1758   1763     }
         1764  +  if( scriptMask==0 && seenDigit ) scriptMask = SCRIPT_LATIN;
  1759   1765     switch( scriptMask ){
  1760   1766       case 0:                res = 999; break;
  1761   1767       case SCRIPT_LATIN:     res = 215; break;
  1762   1768       case SCRIPT_CYRILLIC:  res = 220; break;
  1763   1769       case SCRIPT_GREEK:     res = 200; break;
  1764   1770       case SCRIPT_HEBREW:    res = 125; break;
  1765   1771       case SCRIPT_ARABIC:    res = 160; break;

Changes to src/expr.c.

  1564   1564     if( sqlite3StrICmp(z, "_ROWID_")==0 ) return 1;
  1565   1565     if( sqlite3StrICmp(z, "ROWID")==0 ) return 1;
  1566   1566     if( sqlite3StrICmp(z, "OID")==0 ) return 1;
  1567   1567     return 0;
  1568   1568   }
  1569   1569   
  1570   1570   /*
  1571         -** Return true if we are able to the IN operator optimization on a
  1572         -** query of the form
  1573         -**
  1574         -**       x IN (SELECT ...)
  1575         -**
  1576         -** Where the SELECT... clause is as specified by the parameter to this
  1577         -** routine.
  1578         -**
  1579         -** The Select object passed in has already been preprocessed and no
  1580         -** errors have been found.
         1571  +** pX is the RHS of an IN operator.  If pX is a SELECT statement 
         1572  +** that can be simplified to a direct table access, then return
         1573  +** a pointer to the SELECT statement.  If pX is not a SELECT statement,
         1574  +** or if the SELECT statement needs to be manifested into a transient
         1575  +** table, then return NULL.
  1581   1576   */
  1582   1577   #ifndef SQLITE_OMIT_SUBQUERY
  1583         -static int isCandidateForInOpt(Select *p){
         1578  +static Select *isCandidateForInOpt(Expr *pX){
         1579  +  Select *p;
  1584   1580     SrcList *pSrc;
  1585   1581     ExprList *pEList;
         1582  +  Expr *pRes;
  1586   1583     Table *pTab;
  1587         -  if( p==0 ) return 0;                   /* right-hand side of IN is SELECT */
         1584  +  if( !ExprHasProperty(pX, EP_xIsSelect) ) return 0;  /* Not a subquery */
         1585  +  if( ExprHasProperty(pX, EP_VarSelect)  ) return 0;  /* Correlated subq */
         1586  +  p = pX->x.pSelect;
  1588   1587     if( p->pPrior ) return 0;              /* Not a compound SELECT */
  1589   1588     if( p->selFlags & (SF_Distinct|SF_Aggregate) ){
  1590   1589       testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
  1591   1590       testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
  1592   1591       return 0; /* No DISTINCT keyword and no aggregate functions */
  1593   1592     }
  1594   1593     assert( p->pGroupBy==0 );              /* Has no GROUP BY clause */
................................................................................
  1596   1595     assert( p->pOffset==0 );               /* No LIMIT means no OFFSET */
  1597   1596     if( p->pWhere ) return 0;              /* Has no WHERE clause */
  1598   1597     pSrc = p->pSrc;
  1599   1598     assert( pSrc!=0 );
  1600   1599     if( pSrc->nSrc!=1 ) return 0;          /* Single term in FROM clause */
  1601   1600     if( pSrc->a[0].pSelect ) return 0;     /* FROM is not a subquery or view */
  1602   1601     pTab = pSrc->a[0].pTab;
  1603         -  if( NEVER(pTab==0) ) return 0;
         1602  +  assert( pTab!=0 );
  1604   1603     assert( pTab->pSelect==0 );            /* FROM clause is not a view */
  1605   1604     if( IsVirtual(pTab) ) return 0;        /* FROM clause not a virtual table */
  1606   1605     pEList = p->pEList;
  1607   1606     if( pEList->nExpr!=1 ) return 0;       /* One column in the result set */
  1608         -  if( pEList->a[0].pExpr->op!=TK_COLUMN ) return 0; /* Result is a column */
  1609         -  return 1;
         1607  +  pRes = pEList->a[0].pExpr;
         1608  +  if( pRes->op!=TK_COLUMN ) return 0;    /* Result is a column */
         1609  +  assert( pRes->iTable==pSrc->a[0].iCursor );  /* Not a correlated subquery */
         1610  +  return p;
  1610   1611   }
  1611   1612   #endif /* SQLITE_OMIT_SUBQUERY */
  1612   1613   
  1613   1614   /*
  1614   1615   ** Code an OP_Once instruction and allocate space for its flag. Return the 
  1615   1616   ** address of the new instruction.
  1616   1617   */
................................................................................
  1734   1735     assert( pX->op==TK_IN );
  1735   1736     mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0;
  1736   1737   
  1737   1738     /* Check to see if an existing table or index can be used to
  1738   1739     ** satisfy the query.  This is preferable to generating a new 
  1739   1740     ** ephemeral table.
  1740   1741     */
  1741         -  p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0);
  1742         -  if( pParse->nErr==0 && isCandidateForInOpt(p) ){
         1742  +  if( pParse->nErr==0 && (p = isCandidateForInOpt(pX))!=0 ){
  1743   1743       sqlite3 *db = pParse->db;              /* Database connection */
  1744   1744       Table *pTab;                           /* Table <table>. */
  1745   1745       Expr *pExpr;                           /* Expression <column> */
  1746   1746       i16 iCol;                              /* Index of column <column> */
  1747   1747       i16 iDb;                               /* Database idx for pTab */
  1748   1748   
  1749         -    assert( p );                        /* Because of isCandidateForInOpt(p) */
  1750   1749       assert( p->pEList!=0 );             /* Because of isCandidateForInOpt(p) */
  1751   1750       assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */
  1752   1751       assert( p->pSrc!=0 );               /* Because of isCandidateForInOpt(p) */
  1753   1752       pTab = p->pSrc->a[0].pTab;
  1754   1753       pExpr = p->pEList->a[0].pExpr;
  1755   1754       iCol = (i16)pExpr->iColumn;
  1756   1755      

Changes to src/pager.c.

  7163   7163   
  7164   7164   /*
  7165   7165   ** Return true if the underlying VFS for the given pager supports the
  7166   7166   ** primitives necessary for write-ahead logging.
  7167   7167   */
  7168   7168   int sqlite3PagerWalSupported(Pager *pPager){
  7169   7169     const sqlite3_io_methods *pMethods = pPager->fd->pMethods;
         7170  +  if( pPager->noLock ) return 0;
  7170   7171     return pPager->exclusiveMode || (pMethods->iVersion>=2 && pMethods->xShmMap);
  7171   7172   }
  7172   7173   
  7173   7174   /*
  7174   7175   ** Attempt to take an exclusive lock on the database file. If a PENDING lock
  7175   7176   ** is obtained instead, immediately release it.
  7176   7177   */

Changes to src/sqliteInt.h.

   447    447   #if defined(SQLITE_HAVE_OS_TRACE) || defined(SQLITE_TEST) || \
   448    448       (defined(SQLITE_DEBUG) && SQLITE_OS_WIN)
   449    449   # define SQLITE_NEED_ERR_NAME
   450    450   #else
   451    451   # undef  SQLITE_NEED_ERR_NAME
   452    452   #endif
   453    453   
          454  +/*
          455  +** SQLITE_ENABLE_EXPLAIN_COMMENTS is incompatible with SQLITE_OMIT_EXPLAIN
          456  +*/
          457  +#ifdef SQLITE_OMIT_EXPLAIN
          458  +# undef SQLITE_ENABLE_EXPLAIN_COMMENTS
          459  +#endif
          460  +
   454    461   /*
   455    462   ** Return true (non-zero) if the input is an integer that is too large
   456    463   ** to fit in 32-bits.  This macro is used inside of various testcase()
   457    464   ** macros to verify that we have tested SQLite for large-file support.
   458    465   */
   459    466   #define IS_BIG_INT(X)  (((X)&~(i64)0xffffffff)!=0)
   460    467   

Changes to src/util.c.

  1420   1420   u64 sqlite3LogEstToInt(LogEst x){
  1421   1421     u64 n;
  1422   1422     if( x<10 ) return 1;
  1423   1423     n = x%10;
  1424   1424     x /= 10;
  1425   1425     if( n>=5 ) n -= 2;
  1426   1426     else if( n>=1 ) n -= 1;
  1427         -  if( x>=3 ){
  1428         -    return x>60 ? (u64)LARGEST_INT64 : (n+8)<<(x-3);
  1429         -  }
  1430         -  return (n+8)>>(3-x);
         1427  +#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
         1428  +    defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
         1429  +  if( x>60 ) return (u64)LARGEST_INT64;
         1430  +#else
         1431  +  /* If only SQLITE_ENABLE_STAT3_OR_STAT4 is on, then the largest input
         1432  +  ** possible to this routine is 310, resulting in a maximum x of 31 */
         1433  +  assert( x<=60 );
         1434  +#endif
         1435  +  return x>=3 ? (n+8)<<(x-3) : (n+8)>>(3-x);
  1431   1436   }
  1432   1437   #endif /* defined SCANSTAT or STAT4 or ESTIMATED_ROWS */

Changes to src/where.c.

  1975   1975   **    (3)  The template has same or fewer dependencies than the current loop
  1976   1976   **    (4)  The template has the same or lower cost than the current loop
  1977   1977   */
  1978   1978   static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
  1979   1979     WhereLoop **ppPrev, *p;
  1980   1980     WhereInfo *pWInfo = pBuilder->pWInfo;
  1981   1981     sqlite3 *db = pWInfo->pParse->db;
         1982  +  int rc;
  1982   1983   
  1983   1984     /* If pBuilder->pOrSet is defined, then only keep track of the costs
  1984   1985     ** and prereqs.
  1985   1986     */
  1986   1987     if( pBuilder->pOrSet!=0 ){
  1987   1988       if( pTemplate->nLTerm ){
  1988   1989   #if WHERETRACE_ENABLED
................................................................................
  2057   2058           sqlite3DebugPrintf(" delete: ");
  2058   2059           whereLoopPrint(pToDel, pBuilder->pWC);
  2059   2060         }
  2060   2061   #endif
  2061   2062         whereLoopDelete(db, pToDel);
  2062   2063       }
  2063   2064     }
  2064         -  whereLoopXfer(db, p, pTemplate);
         2065  +  rc = whereLoopXfer(db, p, pTemplate);
  2065   2066     if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
  2066   2067       Index *pIndex = p->u.btree.pIndex;
  2067   2068       if( pIndex && pIndex->tnum==0 ){
  2068   2069         p->u.btree.pIndex = 0;
  2069   2070       }
  2070   2071     }
  2071         -  return SQLITE_OK;
         2072  +  return rc;
  2072   2073   }
  2073   2074   
  2074   2075   /*
  2075   2076   ** Adjust the WhereLoop.nOut value downward to account for terms of the
  2076   2077   ** WHERE clause that reference the loop but which are not used by an
  2077   2078   ** index.
  2078   2079   *
................................................................................
  2882   2883     /* Set the WHERE_ONEROW flag if the xBestIndex() method indicated
  2883   2884     ** that the scan will visit at most one row. Clear it otherwise. */
  2884   2885     if( pIdxInfo->idxFlags & SQLITE_INDEX_SCAN_UNIQUE ){
  2885   2886       pNew->wsFlags |= WHERE_ONEROW;
  2886   2887     }else{
  2887   2888       pNew->wsFlags &= ~WHERE_ONEROW;
  2888   2889     }
  2889         -  whereLoopInsert(pBuilder, pNew);
         2890  +  rc = whereLoopInsert(pBuilder, pNew);
  2890   2891     if( pNew->u.vtab.needFree ){
  2891   2892       sqlite3_free(pNew->u.vtab.idxStr);
  2892   2893       pNew->u.vtab.needFree = 0;
  2893   2894     }
  2894   2895     WHERETRACE(0xffff, ("  bIn=%d prereqIn=%04llx prereqOut=%04llx\n",
  2895   2896                         *pbIn, (sqlite3_uint64)mPrereq,
  2896   2897                         (sqlite3_uint64)(pNew->prereq & ~mPrereq)));
  2897   2898   
  2898         -  return SQLITE_OK;
         2899  +  return rc;
  2899   2900   }
  2900   2901   
  2901   2902   
  2902   2903   /*
  2903   2904   ** Add all WhereLoop objects for a table of the join identified by
  2904   2905   ** pBuilder->pNew->iTab.  That table is guaranteed to be a virtual table.
  2905   2906   **

Changes to test/analyzer1.test.

    21     21   
    22     22   if {$tcl_platform(platform)=="windows"} {
    23     23     set PROG "sqlite3_analyzer.exe"
    24     24   } else {
    25     25     set PROG "./sqlite3_analyzer"
    26     26   }
    27     27   if {![file exe $PROG]} {
    28         -  puts "analyzer1 cannot run because $PROG is not available"
    29         -  finish_test
    30         -  return
           28  +  set PROG [file normalize [file join $::cmdlinearg(TESTFIXTURE_HOME) $PROG]]
           29  +  if {![file exe $PROG]} {
           30  +    puts "analyzer1 cannot run because $PROG is not available"
           31  +    finish_test
           32  +    return
           33  +  }
    31     34   }
    32     35   db close
    33     36   forcedelete test.db test.db-journal test.db-wal
    34     37   sqlite3 db test.db
    35     38   
    36     39   do_test analyzer1-1.0 {
    37     40     db eval {

Changes to test/autovacuum.test.

   265    265   do_test autovacuum-2.4.3 {
   266    266     execsql {
   267    267       SELECT rootpage FROM sqlite_master ORDER by rootpage
   268    268     }
   269    269   } {3 4 5 6 7 8 9 10}
   270    270   
   271    271   # Right now there are 5 free pages in the database. Consume and then free
   272         -# a 520 pages. Then create 520 tables. This ensures that at least some of the
          272  +# all 520 pages. Then create 520 tables. This ensures that at least some of the
   273    273   # desired root-pages reside on the second free-list trunk page, and that the
   274    274   # trunk itself is required at some point.
   275    275   do_test autovacuum-2.4.4 {
   276    276     execsql "
   277    277       INSERT INTO av3 VALUES ('[make_str abcde [expr 1020*520 + 500]]');
   278    278       DELETE FROM av3;
   279    279     "
   280    280   } {}
   281    281   set root_page_list [list]
   282    282   set pending_byte_page [expr ($::sqlite_pending_byte / 1024) + 1]
          283  +
          284  +# unusable_pages
          285  +# These are either the pending_byte page or the pointer map pages
          286  +#
          287  +unset -nocomplain unusable_page
          288  +if {[sqlite3 -has-codec]} {
          289  +  array set unusable_page {205 1 408 1}
          290  +} else {
          291  +  array set unusable_page {207 1 412 1}
          292  +}
          293  +set unusable_page($pending_byte_page) 1
          294  +
   283    295   for {set i 3} {$i<=532} {incr i} {
   284         -  # 207 and 412 are pointer-map pages.
   285         -  if { $i!=207 && $i!=412 && $i != $pending_byte_page} {
          296  +  if {![info exists unusable_page($i)]} {
   286    297       lappend root_page_list $i
   287    298     }
   288    299   }
   289    300   if {$i >= $pending_byte_page} {
   290    301     lappend root_page_list $i
   291    302   }
   292    303   do_test autovacuum-2.4.5 {

Changes to test/backcompat.test.

    81     81   array set ::incompatible [list]
    82     82   proc do_allbackcompat_test {script} {
    83     83   
    84     84     foreach bin $::BC(binaries) {
    85     85       set nErr [set_test_counter errors]
    86     86       foreach dir {0 1} {
    87     87   
    88         -      set bintag [string map {testfixture {}} $bin]
           88  +      set bintag $bin
           89  +      regsub {.*testfixture\.} $bintag {} bintag
    89     90         set bintag [string map {\.exe {}} $bintag]
    90     91         if {$bintag == ""} {set bintag self}
    91     92         set ::bcname ".$bintag.$dir."
    92     93   
    93     94         rename do_test _do_test
    94     95         proc do_test {nm sql res} {
    95     96           set nm [regsub {\.} $nm $::bcname]

Changes to test/backup4.test.

    18     18   # schema cookie and change counter. Doing that could cause other clients
    19     19   # to become confused and continue using out-of-date cache data.
    20     20   #
    21     21   
    22     22   set testdir [file dirname $argv0]
    23     23   source $testdir/tester.tcl
    24     24   set testprefix backup4
           25  +
           26  +# The codec logic does not work for zero-length database files.  A database
           27  +# file must contain at least one page in order to be recognized as an
           28  +# encrypted database.
           29  +do_not_use_codec
    25     30   
    26     31   #-------------------------------------------------------------------------
    27     32   # At one point this test was failing because [db] was using an out of
    28     33   # date schema in test case 1.2.
    29     34   #
    30     35   do_execsql_test 1.0 {
    31     36     CREATE TABLE t1(x, y, UNIQUE(x, y));

Changes to test/bc_common.tcl.

     3      3   
     4      4   proc bc_find_binaries {zCaption} {
     5      5     # Search for binaries to test against. Any executable files that match
     6      6     # our naming convention are assumed to be testfixture binaries to test
     7      7     # against.
     8      8     #
     9      9     set binaries [list]
    10         -  set self [file tail [info nameofexec]]
           10  +  set self [info nameofexec]
    11     11     set pattern "$self?*"
    12     12     if {$::tcl_platform(platform)=="windows"} {
    13     13       set pattern [string map {\.exe {}} $pattern]
    14     14     }
    15     15     foreach file [glob -nocomplain $pattern] {
    16     16       if {$file==$self} continue
    17     17       if {[file executable $file] && [file isfile $file]} {lappend binaries $file}
................................................................................
    48     48     proc code2 {tcl} { testfixture $::bc_chan $tcl }
    49     49     proc sql1 sql { code1 [list db eval $sql] }
    50     50     proc sql2 sql { code2 [list db eval $sql] }
    51     51   
    52     52     code1 { sqlite3 db test.db }
    53     53     code2 { sqlite3 db test.db }
    54     54   
    55         -  set bintag [string map {testfixture {}} $bin]
           55  +  set bintag $bin
           56  +  regsub {.*testfixture\.} $bintag {} bintag
    56     57     set bintag [string map {\.exe {}} $bintag]
    57     58     if {$bintag == ""} {set bintag self}
    58     59     set saved_prefix $::testprefix
    59     60     append ::testprefix ".$bintag"
    60     61   
    61     62     uplevel $script
    62     63   

Changes to test/bestindex1.test.

    10     10   #***********************************************************************
    11     11   # 
    12     12   #
    13     13   
    14     14   set testdir [file dirname $argv0]
    15     15   source $testdir/tester.tcl
    16     16   set testprefix bestindex1
           17  +
           18  +ifcapable !vtab {
           19  +  finish_test
           20  +  return
           21  +}
    17     22   
    18     23   register_tcl_module db
    19     24   
    20     25   proc vtab_command {method args} {
    21     26     switch -- $method {
    22     27       xConnect {
    23     28         return "CREATE TABLE t1(a, b, c)"
................................................................................
   157    162   
   158    163     do_eqp_test 2.2.$mode.6 { 
   159    164       SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid
   160    165     } $plan($mode)
   161    166   }
   162    167   
   163    168   finish_test
   164         -
   165         -

Changes to test/bestindex2.test.

     9      9   #
    10     10   #***********************************************************************
    11     11   
    12     12   set testdir [file dirname $argv0]
    13     13   source $testdir/tester.tcl
    14     14   set testprefix bestindex2
    15     15   
           16  +ifcapable !vtab {
           17  +  finish_test
           18  +  return
           19  +}
    16     20   
    17     21   #-------------------------------------------------------------------------
    18     22   # Virtual table callback for table named $tbl, with the columns specified
    19     23   # by list argument $cols. e.g. if the function is invoked as:
    20     24   #
    21     25   #   vtab_cmd t1 {a b c} ...
    22     26   #
................................................................................
   131    135     0 0 0 {SCAN TABLE x1} 
   132    136     0 1 1 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:}
   133    137     0 2 2 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)} 
   134    138     0 3 3 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)}
   135    139   }
   136    140   
   137    141   finish_test
   138         -

Changes to test/close.test.

    12     12   # Test some specific circumstances to do with shared cache mode.
    13     13   #
    14     14   
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   set ::testprefix close
           19  +
           20  +# This module bypasses the "-key" logic in tester.tcl, so it cannot run
           21  +# with the codec enabled.
           22  +do_not_use_codec
    19     23   
    20     24   do_execsql_test 1.0 {
    21     25     CREATE TABLE t1(x);
    22     26     INSERT INTO t1 VALUES('one');
    23     27     INSERT INTO t1 VALUES('two');
    24     28     INSERT INTO t1 VALUES('three');
    25     29   }

Changes to test/corrupt3.test.

    14     14   # segfault if it sees a corrupt database file.
    15     15   #
    16     16   # $Id: corrupt3.test,v 1.2 2007/04/06 21:42:22 drh Exp $
    17     17   
    18     18   set testdir [file dirname $argv0]
    19     19   source $testdir/tester.tcl
    20     20   
    21         -# Do not use a codec for tests in this file, as the database file is
    22         -# manipulated directly using tcl scripts (using the [hexio_write] command).
    23         -#
    24         -do_not_use_codec
           21  +# This module uses hard-coded offsets which do not work if the reserved_bytes
           22  +# value is nonzero.
           23  +if {[nonzero_reserved_bytes]} {finish_test; return;}
    25     24   
    26     25   # These tests deal with corrupt database files
    27     26   #
    28     27   database_may_be_corrupt
    29     28   
    30     29   # We must have the page_size pragma for these tests to work.
    31     30   #

Changes to test/corrupt4.test.

    14     14   # segfault if it sees a corrupt database file.
    15     15   #
    16     16   # $Id: corrupt4.test,v 1.1 2007/09/07 14:32:07 drh Exp $
    17     17   
    18     18   set testdir [file dirname $argv0]
    19     19   source $testdir/tester.tcl
    20     20   
    21         -# Do not use a codec for tests in this file, as the database file is
    22         -# manipulated directly using tcl scripts (using the [hexio_write] command).
    23         -#
    24         -do_not_use_codec
           21  +# This module uses hard-coded offsets which do not work if the reserved_bytes
           22  +# value is nonzero.
           23  +if {[nonzero_reserved_bytes]} {finish_test; return;}
    25     24   
    26     25   # These tests deal with corrupt database files
    27     26   #
    28     27   database_may_be_corrupt
    29     28   
    30     29   # We must have the page_size pragma for these tests to work.
    31     30   #

Changes to test/corrupt6.test.

    15     15   # on corrupt SerialTypeLen values.
    16     16   #
    17     17   # $Id: corrupt6.test,v 1.2 2008/05/19 15:37:10 shane Exp $
    18     18   
    19     19   set testdir [file dirname $argv0]
    20     20   source $testdir/tester.tcl
    21     21   
    22         -# Do not use a codec for tests in this file, as the database file is
    23         -# manipulated directly using tcl scripts (using the [hexio_write] command).
    24         -#
    25         -do_not_use_codec
           22  +# This module uses hard-coded offsets which do not work if the reserved_bytes
           23  +# value is nonzero.
           24  +if {[nonzero_reserved_bytes]} {finish_test; return;}
    26     25   
    27     26   # These tests deal with corrupt database files
    28     27   #
    29     28   database_may_be_corrupt
    30     29   
    31     30   # We must have the page_size pragma for these tests to work.
    32     31   #

Changes to test/corrupt7.test.

    15     15   # on corrupt cell offsets in a btree page.
    16     16   #
    17     17   # $Id: corrupt7.test,v 1.8 2009/08/10 10:18:08 danielk1977 Exp $
    18     18   
    19     19   set testdir [file dirname $argv0]
    20     20   source $testdir/tester.tcl
    21     21   
    22         -# Do not use a codec for tests in this file, as the database file is
    23         -# manipulated directly using tcl scripts (using the [hexio_write] command).
    24         -#
    25         -do_not_use_codec
           22  +# This module uses hard-coded offsets which do not work if the reserved_bytes
           23  +# value is nonzero.
           24  +if {[nonzero_reserved_bytes]} {finish_test; return;}
    26     25   
    27     26   # These tests deal with corrupt database files
    28     27   #
    29     28   database_may_be_corrupt
    30     29   
    31     30   # We must have the page_size pragma for these tests to work.
    32     31   #

Changes to test/corruptE.test.

    14     14   # segfault if it sees a corrupt database file.  It specifcally
    15     15   # focuses on rowid order corruption.
    16     16   #
    17     17   
    18     18   set testdir [file dirname $argv0]
    19     19   source $testdir/tester.tcl
    20     20   
    21         -# Do not use a codec for tests in this file, as the database file is
    22         -# manipulated directly using tcl scripts (using the [hexio_write] command).
    23         -#
    24         -do_not_use_codec
           21  +# This module uses hard-coded offsets which do not work if the reserved_bytes
           22  +# value is nonzero.
           23  +if {[nonzero_reserved_bytes]} {finish_test; return;}
    25     24   
    26     25   # These tests deal with corrupt database files
    27     26   #
    28     27   database_may_be_corrupt
    29     28   
    30     29   # Do not run the tests in this file if ENABLE_OVERSIZE_CELL_CHECK is on.
    31     30   #

Changes to test/corruptG.test.

    10     10   #***********************************************************************
    11     11   #
    12     12   
    13     13   set testdir [file dirname $argv0]
    14     14   source $testdir/tester.tcl
    15     15   set testprefix corruptG
    16     16   
    17         -# Do not use a codec for tests in this file, as the database file is
    18         -# manipulated directly using tcl scripts (using the [hexio_write] command).
    19         -#
    20         -do_not_use_codec
           17  +# This module uses hard-coded offsets which do not work if the reserved_bytes
           18  +# value is nonzero.
           19  +if {[nonzero_reserved_bytes]} {finish_test; return;}
    21     20   
    22     21   # These tests deal with corrupt database files
    23     22   #
    24     23   database_may_be_corrupt
    25     24   
    26     25   # Create a simple database with a single entry.  Then corrupt the
    27     26   # header-size varint on the index payload so that it maps into a

Changes to test/corruptH.test.

    10     10   #***********************************************************************
    11     11   #
    12     12   
    13     13   set testdir [file dirname $argv0]
    14     14   source $testdir/tester.tcl
    15     15   set testprefix corruptH
    16     16   
    17         -# Do not use a codec for tests in this file, as the database file is
    18         -# manipulated directly using tcl scripts (using the [hexio_write] command).
    19         -#
    20         -do_not_use_codec
           17  +# This module uses hard-coded offsets which do not work if the reserved_bytes
           18  +# value is nonzero.
           19  +if {[nonzero_reserved_bytes]} {finish_test; return;}
           20  +
    21     21   database_may_be_corrupt
    22     22   
    23     23   # The corruption migrations tested by the code in this file are not detected
    24     24   # mmap mode.
    25     25   #
    26     26   # The reason is that in mmap mode, the different queries may use different
    27     27   # PgHdr objects for the same page (same data, but different PgHdr container 

Changes to test/corruptI.test.

    15     15   set testprefix corruptI
    16     16   
    17     17   if {[permutation]=="mmap"} {
    18     18     finish_test
    19     19     return
    20     20   }
    21     21   
    22         -# Do not use a codec for tests in this file, as the database file is
    23         -# manipulated directly using tcl scripts (using the [hexio_write] command).
    24         -#
    25         -do_not_use_codec
           22  +# This module uses hard-coded offsets which do not work if the reserved_bytes
           23  +# value is nonzero.
           24  +if {[nonzero_reserved_bytes]} {finish_test; return;}
           25  +
    26     26   database_may_be_corrupt
    27     27   
    28     28   # Initialize the database.
    29     29   #
    30     30   do_execsql_test 1.1 {
    31     31     PRAGMA page_size=1024;
    32     32     PRAGMA auto_vacuum=0;

Changes to test/corruptJ.test.

    18     18   set testprefix corruptJ
    19     19   
    20     20   if {[permutation]=="mmap"} {
    21     21     finish_test
    22     22     return
    23     23   }
    24     24   
    25         -# Do not use a codec for tests in this file, as the database file is
    26         -# manipulated directly using tcl scripts (using the [hexio_write] command).
    27         -#
    28         -do_not_use_codec
           25  +# This module uses hard-coded offsets which do not work if the reserved_bytes
           26  +# value is nonzero.
           27  +if {[nonzero_reserved_bytes]} {finish_test; return;}
           28  +
    29     29   database_may_be_corrupt
    30     30   
    31     31   # Initialize the database.
    32     32   #
    33     33   do_execsql_test 1.1 {
    34     34     PRAGMA page_size=1024;
    35     35     PRAGMA auto_vacuum=0;

Changes to test/crash8.test.

    21     21   set testdir [file dirname $argv0]
    22     22   source $testdir/tester.tcl
    23     23   
    24     24   ifcapable !crashtest {
    25     25     finish_test
    26     26     return
    27     27   }
           28  +do_not_use_codec
    28     29   
    29     30   do_test crash8-1.1 {
    30     31     execsql {
    31     32       PRAGMA auto_vacuum=OFF;
    32     33       CREATE TABLE t1(a, b);
    33     34       CREATE INDEX i1 ON t1(a, b);
    34     35       INSERT INTO t1 VALUES(1, randstr(1000,1000));

Changes to test/e_uri.test.

     9      9   #
    10     10   #***********************************************************************
    11     11   #
    12     12   
    13     13   set testdir [file dirname $argv0]
    14     14   source $testdir/tester.tcl
    15     15   set testprefix e_uri
    16         -
           16  +do_not_use_codec
    17     17   db close
    18     18   
    19     19   proc parse_uri {uri} {
    20     20     testvfs tvfs2
    21     21     testvfs tvfs 
    22     22     tvfs filter xOpen
    23     23     tvfs script parse_uri_open_cb

Changes to test/e_vacuum.test.

   155    155   } {1024 1}
   156    156   do_test e_vacuum-1.3.1.2 {
   157    157     execsql { PRAGMA page_size = 2048 }
   158    158     execsql { PRAGMA auto_vacuum = NONE }
   159    159     execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
   160    160   } {1024 1}
   161    161   
   162         -# EVIDENCE-OF: R-08570-19916 However, when not in write-ahead log mode,
   163         -# the page_size and/or auto_vacuum properties of an existing database
   164         -# may be changed by using the page_size and/or pragma auto_vacuum
   165         -# pragmas and then immediately VACUUMing the database.
   166         -#
   167         -do_test e_vacuum-1.3.2.1 {
   168         -  execsql { PRAGMA journal_mode = delete }
   169         -  execsql { PRAGMA page_size = 2048 }
   170         -  execsql { PRAGMA auto_vacuum = NONE }
   171         -  execsql VACUUM
   172         -  execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
   173         -} {2048 0}
   174         -
   175         -# EVIDENCE-OF: R-48521-51450 When in write-ahead log mode, only the
   176         -# auto_vacuum support property can be changed using VACUUM.
   177         -#
   178         -ifcapable wal {
   179         -do_test e_vacuum-1.3.3.1 {
   180         -  execsql { PRAGMA journal_mode = wal }
   181         -  execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
   182         -} {2048 0}
   183         -do_test e_vacuum-1.3.3.2 {
   184         -  execsql { PRAGMA page_size = 1024 }
   185         -  execsql { PRAGMA auto_vacuum = FULL }
   186         -  execsql VACUUM
   187         -  execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
   188         -} {2048 1}
          162  +if {![nonzero_reserved_bytes]} {
          163  +  # EVIDENCE-OF: R-08570-19916 However, when not in write-ahead log mode,
          164  +  # the page_size and/or auto_vacuum properties of an existing database
          165  +  # may be changed by using the page_size and/or pragma auto_vacuum
          166  +  # pragmas and then immediately VACUUMing the database.
          167  +  #
          168  +  do_test e_vacuum-1.3.2.1 {
          169  +    execsql { PRAGMA journal_mode = delete }
          170  +    execsql { PRAGMA page_size = 2048 }
          171  +    execsql { PRAGMA auto_vacuum = NONE }
          172  +    execsql VACUUM
          173  +    execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
          174  +  } {2048 0}
          175  +  
          176  +  # EVIDENCE-OF: R-48521-51450 When in write-ahead log mode, only the
          177  +  # auto_vacuum support property can be changed using VACUUM.
          178  +  #
          179  +  ifcapable wal {
          180  +    do_test e_vacuum-1.3.3.1 {
          181  +      execsql { PRAGMA journal_mode = wal }
          182  +      execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
          183  +    } {2048 0}
          184  +    do_test e_vacuum-1.3.3.2 {
          185  +      execsql { PRAGMA page_size = 1024 }
          186  +      execsql { PRAGMA auto_vacuum = FULL }
          187  +      execsql VACUUM
          188  +      execsql { PRAGMA page_size ; PRAGMA auto_vacuum }
          189  +    } {2048 1}
          190  +  }
   189    191   }
   190         -
          192  +  
   191    193   # EVIDENCE-OF: R-38001-03952 VACUUM only works on the main database. It
   192    194   # is not possible to VACUUM an attached database file.
   193    195   forcedelete test.db2
   194    196   create_db { PRAGMA auto_vacuum = NONE }
   195    197   do_execsql_test e_vacuum-2.1.1 {
   196    198     ATTACH 'test.db2' AS aux;
   197    199     PRAGMA aux.page_size = 1024;

Changes to test/e_walauto.test.

    19     19   # accessing the same coherent view of the "test.db-shm" file. This doesn't
    20     20   # work on OpenBSD.
    21     21   #
    22     22   if {$tcl_platform(os) == "OpenBSD"} {
    23     23     finish_test
    24     24     return
    25     25   }
           26  +
           27  +# This module uses hard-coded offsets which do not work if the reserved_bytes
           28  +# value is nonzero.
           29  +if {[nonzero_reserved_bytes]} {finish_test; return;}
           30  +
    26     31   
    27     32   proc read_nbackfill {} {
    28     33     seek $::shmfd 96
    29     34     binary scan [read $::shmfd 4] n nBackfill
    30     35     set nBackfill
    31     36   }
    32     37   proc read_mxframe {} {

Changes to test/eqp.test.

   512    512     1 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}
   513    513     2 0 0 {SCAN TABLE t2}
   514    514     2 0 0 {USE TEMP B-TREE FOR ORDER BY}
   515    515     0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)}
   516    516   }
   517    517   
   518    518   
   519         -#-------------------------------------------------------------------------
   520         -# The following tests - eqp-6.* - test that the example C code on 
   521         -# documentation page eqp.html works. The C code is duplicated in test1.c
   522         -# and wrapped in Tcl command [print_explain_query_plan] 
   523         -#
   524         -set boilerplate {
   525         -  proc explain_query_plan {db sql} {
   526         -    set stmt [sqlite3_prepare_v2 db $sql -1 DUMMY]
   527         -    print_explain_query_plan $stmt
   528         -    sqlite3_finalize $stmt
          519  +if {![nonzero_reserved_bytes]} {
          520  +  #-------------------------------------------------------------------------
          521  +  # The following tests - eqp-6.* - test that the example C code on 
          522  +  # documentation page eqp.html works. The C code is duplicated in test1.c
          523  +  # and wrapped in Tcl command [print_explain_query_plan] 
          524  +  #
          525  +  set boilerplate {
          526  +    proc explain_query_plan {db sql} {
          527  +      set stmt [sqlite3_prepare_v2 db $sql -1 DUMMY]
          528  +      print_explain_query_plan $stmt
          529  +      sqlite3_finalize $stmt
          530  +    }
          531  +    sqlite3 db test.db
          532  +    explain_query_plan db {%SQL%}
          533  +    db close
          534  +    exit
   529    535     }
   530         -  sqlite3 db test.db
   531         -  explain_query_plan db {%SQL%}
   532         -  db close
   533         -  exit
   534         -}
   535         -
   536         -# Do a "Print Explain Query Plan" test.
   537         -proc do_peqp_test {tn sql res} {
   538         -  set fd [open script.tcl w]
   539         -  puts $fd [string map [list %SQL% $sql] $::boilerplate]
   540         -  close $fd
   541         -
   542         -  uplevel do_test $tn [list {
   543         -    set fd [open "|[info nameofexec] script.tcl"]
   544         -    set data [read $fd]
          536  +  
          537  +  # Do a "Print Explain Query Plan" test.
          538  +  proc do_peqp_test {tn sql res} {
          539  +    set fd [open script.tcl w]
          540  +    puts $fd [string map [list %SQL% $sql] $::boilerplate]
   545    541       close $fd
   546         -    set data
   547         -  }] [list $res]
   548         -}
   549         -
   550         -do_peqp_test 6.1 {
   551         -  SELECT a, b FROM t1 EXCEPT SELECT d, 99 FROM t2 ORDER BY 1
   552         -} [string trimleft {
          542  +  
          543  +    uplevel do_test $tn [list {
          544  +      set fd [open "|[info nameofexec] script.tcl"]
          545  +      set data [read $fd]
          546  +      close $fd
          547  +      set data
          548  +    }] [list $res]
          549  +  }
          550  +  
          551  +  do_peqp_test 6.1 {
          552  +    SELECT a, b FROM t1 EXCEPT SELECT d, 99 FROM t2 ORDER BY 1
          553  +  } [string trimleft {
   553    554   1 0 0 SCAN TABLE t1 USING COVERING INDEX i2
   554    555   2 0 0 SCAN TABLE t2
   555    556   2 0 0 USE TEMP B-TREE FOR ORDER BY
   556    557   0 0 0 COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)
   557    558   }]
          559  +}
   558    560   
   559    561   #-------------------------------------------------------------------------
   560    562   # The following tests - eqp-7.* - test that queries that use the OP_Count
   561    563   # optimization return something sensible with EQP.
   562    564   #
   563    565   drop_all_tables
   564    566   

Changes to test/fts4opt.test.

   161    161   } {33 1 1057 1 2081 1 3105 1}
   162    162   do_execsql_test 2.7 { INSERT INTO t2(t2) VALUES('integrity-check') }
   163    163   
   164    164   do_execsql_test 2.8 {
   165    165     INSERT INTO t2(words) SELECT words FROM t1;
   166    166     SELECT level, count(*) FROM t2_segdir GROUP BY level;
   167    167   } {0 2 1024 2 2048 2 3072 2}
          168  +
          169  +#-------------------------------------------------------------------------
          170  +# Check that 'optimize' works when there is data in the in-memory hash
          171  +# table, but no segments at all on disk.
          172  +#
          173  +do_execsql_test 3.1 {
          174  +  CREATE VIRTUAL TABLE fts USING fts4 (t);
          175  +  INSERT INTO fts (fts) VALUES ('optimize');
          176  +}
          177  +do_execsql_test 3.2 {
          178  +  INSERT INTO fts(fts) VALUES('integrity-check');
          179  +  SELECT count(*) FROM fts_segdir;
          180  +} {0}
          181  +do_execsql_test 3.3 {
          182  +  BEGIN;
          183  +  INSERT INTO fts (rowid, t) VALUES (2, 'test');
          184  +  INSERT INTO fts (fts) VALUES ('optimize');
          185  +  COMMIT;
          186  +  SELECT level, idx FROM fts_segdir;
          187  +} {0 0}
          188  +do_execsql_test 3.4 {
          189  +  INSERT INTO fts(fts) VALUES('integrity-check');
          190  +  SELECT rowid FROM fts WHERE fts MATCH 'test';
          191  +} {2}
          192  +do_execsql_test 3.5 {
          193  +  INSERT INTO fts (fts) VALUES ('optimize');
          194  +  INSERT INTO fts(fts) VALUES('integrity-check');
          195  +}
          196  +do_test 3.6 {
          197  +  set c1 [db total_changes]
          198  +  execsql { INSERT INTO fts (fts) VALUES ('optimize') }
          199  +  expr {[db total_changes] - $c1}
          200  +} {1}
          201  +do_test 3.7 {
          202  +  execsql { INSERT INTO fts (rowid, t) VALUES (3, 'xyz') }
          203  +  set c1 [db total_changes]
          204  +  execsql { INSERT INTO fts (fts) VALUES ('optimize') }
          205  +  expr {([db total_changes] - $c1) > 1}
          206  +} {1}
          207  +do_test 3.8 {
          208  +  set c1 [db total_changes]
          209  +  execsql { INSERT INTO fts (fts) VALUES ('optimize') }
          210  +  expr {[db total_changes] - $c1}
          211  +} {1}
   168    212   
   169    213   finish_test

Changes to test/in5.test.

   178    178   do_execsql_test 6.3.1 {
   179    179     CREATE TABLE x1(a);
   180    180     CREATE TABLE x2(b);
   181    181     INSERT INTO x1 VALUES(1), (1), (2);
   182    182     INSERT INTO x2 VALUES(1), (2);
   183    183     SELECT count(*) FROM x2 WHERE b IN (SELECT DISTINCT a FROM x1 LIMIT 2);
   184    184   } {2}
          185  +
          186  +#-------------------------------------------------------------------------
          187  +# Test to confirm that bug [5e3c886796e5] is fixed.
          188  +#
          189  +do_execsql_test 7.1 {
          190  +  CREATE TABLE y1(a, b);
          191  +  CREATE TABLE y2(c);
          192  +
          193  +  INSERT INTO y1 VALUES(1,     'one');
          194  +  INSERT INTO y1 VALUES('two', 'two');
          195  +  INSERT INTO y1 VALUES(3,     'three');
          196  +
          197  +  INSERT INTO y2 VALUES('one');
          198  +  INSERT INTO y2 VALUES('two');
          199  +  INSERT INTO y2 VALUES('three');
          200  +} {}
          201  +
          202  +do_execsql_test 7.2.1 {
          203  +  SELECT a FROM y1 WHERE b NOT IN (SELECT a FROM y2);
          204  +} {1 3}
          205  +do_execsql_test 7.2.2 {
          206  +  SELECT a FROM y1 WHERE b IN (SELECT a FROM y2);
          207  +} {two}
          208  +
          209  +do_execsql_test 7.3.1 {
          210  +  CREATE INDEX y2c ON y2(c);
          211  +  SELECT a FROM y1 WHERE b NOT IN (SELECT a FROM y2);
          212  +} {1 3}
          213  +do_execsql_test 7.3.2 {
          214  +  SELECT a FROM y1 WHERE b IN (SELECT a FROM y2);
          215  +} {two}
          216  +
          217  +finish_test
          218  +
          219  +
   185    220   
   186    221   finish_test

Changes to test/incrblob.test.

   122    122     db close
   123    123     forcedelete test.db test.db-journal
   124    124   
   125    125     sqlite3 db test.db
   126    126     execsql "PRAGMA mmap_size = 0"
   127    127     execsql "PRAGMA auto_vacuum = $AutoVacuumMode"
   128    128   
          129  +  # Extra value added to size answers
          130  +  set ib2_extra 0
          131  +  if {$AutoVacuumMode} {incr ib2_extra}
          132  +  if {[nonzero_reserved_bytes]} {incr ib2_extra}
          133  +
   129    134     do_test incrblob-2.$AutoVacuumMode.1 {
   130    135       set ::str [string repeat abcdefghij 2900]
   131    136       execsql {
   132    137         BEGIN;
   133    138         CREATE TABLE blobs(k PRIMARY KEY, v BLOB, i INTEGER);
   134    139         DELETE FROM blobs;
   135    140         INSERT INTO blobs VALUES('one', $::str || randstr(500,500), 45);
   136    141         COMMIT;
   137    142       }
   138    143       expr [file size test.db]/1024
   139         -  } [expr 31 + $AutoVacuumMode]
          144  +  } [expr 31 + $ib2_extra]
   140    145   
   141    146     ifcapable autovacuum {
   142    147       do_test incrblob-2.$AutoVacuumMode.2 {
   143    148         execsql {
   144    149           PRAGMA auto_vacuum;
   145    150         }
   146    151       } $AutoVacuumMode
................................................................................
   159    164       close $::blob
   160    165     
   161    166       # If the database is not in auto-vacuum mode, the whole of
   162    167       # the overflow-chain must be scanned. In auto-vacuum mode,
   163    168       # sqlite uses the ptrmap pages to avoid reading the other pages.
   164    169       #
   165    170       nRead db
   166         -  } [expr $AutoVacuumMode ? 4 : 30]
          171  +  } [expr $AutoVacuumMode ? 4 : 30+$ib2_extra]
   167    172   
   168    173     do_test incrblob-2.$AutoVacuumMode.4 {
   169    174       string range [db one {SELECT v FROM blobs}] end-19 end
   170    175     } $::fragment
   171    176   
   172    177     do_test incrblob-2.$AutoVacuumMode.5 {
   173    178       # Open and close the db to make sure the page cache is empty.
................................................................................
   183    188       flush $::blob
   184    189     
   185    190       # If the database is not in auto-vacuum mode, the whole of
   186    191       # the overflow-chain must be scanned. In auto-vacuum mode,
   187    192       # sqlite uses the ptrmap pages to avoid reading the other pages.
   188    193       #
   189    194       nRead db
   190         -  } [expr $AutoVacuumMode ? 4 : 30]
          195  +  } [expr $AutoVacuumMode ? 4 : 30 + $ib2_extra]
   191    196   
   192    197     # Pages 1 (the write-counter) and 32 (the blob data) were written.
   193    198     do_test incrblob-2.$AutoVacuumMode.6 {
   194    199       close $::blob
   195    200       nWrite db
   196    201     } 2
   197    202   
................................................................................
   206    211       execsql { PRAGMA mmap_size = 0 }
   207    212   
   208    213       execsql { SELECT i FROM blobs } 
   209    214     } {45}
   210    215   
   211    216     do_test incrblob-2.$AutoVacuumMode.9 {
   212    217       nRead db
   213         -  } [expr $AutoVacuumMode ? 4 : 30]
          218  +  } [expr $AutoVacuumMode ? 4 : 30 + $ib2_extra]
   214    219   }
   215    220   sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)
   216    221   
   217    222   #------------------------------------------------------------------------
   218    223   # incrblob-3.*: 
   219    224   #
   220    225   # Test the outcome of trying to write to a read-only blob handle.
................................................................................
   380    385   # incrblob-5.*: 
   381    386   #
   382    387   #     Test that opening a blob in an attached database works.
   383    388   #
   384    389   ifcapable attach {
   385    390     do_test incrblob-5.1 {
   386    391       forcedelete test2.db test2.db-journal
   387         -    set ::size [expr [file size [info script]]]
          392  +    set ::size [expr [file size $::cmdlinearg(INFO_SCRIPT)]]
   388    393       execsql {
   389    394         ATTACH 'test2.db' AS aux;
   390    395         CREATE TABLE aux.files(name, text);
   391    396         INSERT INTO aux.files VALUES('this one', zeroblob($::size));
   392    397       }
   393    398       set fd  [db incrblob aux files text 1]
   394    399       fconfigure $fd -translation binary
   395         -    set fd2 [open [info script]]
          400  +    set fd2 [open $::cmdlinearg(INFO_SCRIPT)]
   396    401       fconfigure $fd2 -translation binary
   397    402       puts -nonewline $fd [read $fd2]
   398    403       close $fd
   399    404       close $fd2
   400    405       set ::text [db one {select text from aux.files}]
   401    406       string length $::text
   402         -  } [file size [info script]]
          407  +  } [file size $::cmdlinearg(INFO_SCRIPT)]
   403    408     do_test incrblob-5.2 {
   404         -    set fd2 [open [info script]]
          409  +    set fd2 [open $::cmdlinearg(INFO_SCRIPT)]
   405    410       fconfigure $fd2 -translation binary
   406    411       set ::data [read $fd2]
   407    412       close $fd2
   408    413       set ::data
   409    414     } $::text
   410    415   }
   411    416   
................................................................................
   572    577       execsql {
   573    578         SELECT d FROM t1;
   574    579       }
   575    580     } {15}
   576    581   
   577    582   }
   578    583   
   579         -set fd [open [info script]]
          584  +set fd [open $::cmdlinearg(INFO_SCRIPT)]
   580    585   fconfigure $fd -translation binary
   581    586   set ::data [read $fd 14000]
   582    587   close $fd
   583    588   
   584    589   db close
   585    590   forcedelete test.db test.db-journal
   586    591   sqlite3 db test.db

Changes to test/incrblob_err.test.

    20     20     finish_test
    21     21     return
    22     22   }
    23     23   
    24     24   source $testdir/malloc_common.tcl
    25     25   
    26     26   unset -nocomplain ::fd ::data
    27         -set ::fd [open [info script]]
           27  +set ::fd [open $::cmdlinearg(INFO_SCRIPT)]
    28     28   set ::data [read $::fd]
    29     29   close $::fd
    30     30   
    31     31   do_malloc_test 1 -tclprep {
    32         -  set bytes [file size [info script]]
           32  +  set bytes [file size $::cmdlinearg(INFO_SCRIPT)]
    33     33     execsql {
    34     34       CREATE TABLE blobs(k, v BLOB);
    35     35       INSERT INTO blobs VALUES(1, zeroblob($::bytes));
    36     36     }
    37     37   } -tclbody {
    38     38     set ::blob [db incrblob blobs v 1]
    39     39     fconfigure $::blob -translation binary

Changes to test/io.test.

   420    420       # that the file is now greater than 20000 bytes in size.
   421    421       list [expr [file size test.db]>20000] [nSync]
   422    422     } {1 0}
   423    423     do_test io-3.3 {
   424    424       # The COMMIT requires a single fsync() - to the database file.
   425    425       execsql { COMMIT }
   426    426       list [file size test.db] [nSync]
   427         -  } {39936 1}
          427  +  } "[expr {[nonzero_reserved_bytes]?40960:39936}] 1"
   428    428   }
   429    429   
   430    430   #----------------------------------------------------------------------
   431    431   # Test cases io-4.* test the IOCAP_SAFE_APPEND optimization.
   432    432   #
   433    433   sqlite3_simulate_device -char safe_append
   434    434   

Changes to test/memsubsys1.test.

   251    251     expr {$pg_used<24}
   252    252   } 1
   253    253   do_test memsubsys1-7.4 {
   254    254     set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2]
   255    255   } 0
   256    256   do_test memsubsys1-7.5 {
   257    257     set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
   258         -  expr {$maxreq<4100}
          258  +  expr {$maxreq<4100 + 4200*[nonzero_reserved_bytes]}
   259    259   } 1
   260    260   do_test memsubsys1-7.6 {
   261    261     set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
   262    262   } 1
   263    263   do_test memsubsys1-7.7 {
   264    264     set s_ovfl [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2]
   265    265   } 0

Changes to test/mmap1.test.

    84     84         sql1 "SELECT count(*) FROM t1; PRAGMA integrity_check ; PRAGMA page_count"
    85     85       } {32 ok 77}
    86     86   
    87     87       # Have connection 2 shrink the file. Check connection 1 can still read it.
    88     88       sql2 { DELETE FROM t1 WHERE rowid%2; }
    89     89       do_test $t.$tn.2 {
    90     90         sql1 "SELECT count(*) FROM t1; PRAGMA integrity_check ; PRAGMA page_count"
    91         -    } {16 ok 42}
           91  +    } "16 ok [expr {42+[nonzero_reserved_bytes]}]"
    92     92   
    93     93       # Have connection 2 grow the file. Check connection 1 can still read it.
    94     94       sql2 { INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1 }
    95     95       do_test $t.$tn.3 {
    96     96         sql1 "SELECT count(*) FROM t1; PRAGMA integrity_check ; PRAGMA page_count"
    97     97       } {32 ok 79}
    98     98   
................................................................................
   100    100       sql2 { INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1 }
   101    101       do_test $t.$tn.4 {
   102    102         sql1 "SELECT count(*) FROM t1; PRAGMA integrity_check ; PRAGMA page_count"
   103    103       } {64 ok 149}
   104    104   
   105    105       # Check that the number of pages read by connection 1 indicates that the
   106    106       # "PRAGMA mmap_size" command worked.
   107         -    do_test $t.$tn.5 { nRead db } $nRead
          107  +    if {[nonzero_reserved_bytes]==0} {
          108  +      do_test $t.$tn.5 { nRead db } $nRead
          109  +    }
   108    110     }
   109    111   }
   110    112   
   111    113   set ::rcnt 0
   112    114   proc rblob {n} {
   113    115     set ::rcnt [expr (($::rcnt << 3) + $::rcnt + 456) & 0xFFFFFFFF]
   114    116     set str [format %.8x [expr $::rcnt ^ 0xbdf20da3]]

Changes to test/mmap3.test.

    15     15   ifcapable !mmap||!vtab {
    16     16     finish_test
    17     17     return
    18     18   }
    19     19   source $testdir/lock_common.tcl
    20     20   set testprefix mmap3
    21     21   
           22  +# A codec shuts down memory-mapped I/O
           23  +if {[nonzero_reserved_bytes]} {finish_test; return;}
           24  +
    22     25   do_test mmap3-1.0 {
    23     26     load_static_extension db wholenumber
    24     27     db eval {
    25     28       PRAGMA mmap_size=100000;
    26     29       CREATE TABLE t1(x, y);
    27     30       CREATE VIRTUAL TABLE nums USING wholenumber;
    28     31       INSERT INTO t1 SELECT value, randomblob(value) FROM nums

Changes to test/nan.test.

   147    147   # SQLite always converts NaN into NULL so it is not possible to write
   148    148   # a NaN value into the database file using SQLite.  The following series
   149    149   # of tests writes a normal floating point value (0.5) into the database,
   150    150   # then writes directly into the database file to change the 0.5 into NaN.
   151    151   # Then it reads the value of the database to verify it is converted into
   152    152   # NULL.
   153    153   #
   154         -do_test nan-3.1 {
   155         -  db eval {
   156         -    DELETE FROM t1;
   157         -    INSERT INTO t1 VALUES(0.5);
   158         -    PRAGMA auto_vacuum=OFF;
   159         -    PRAGMA page_size=1024;
   160         -    VACUUM;
   161         -  }
   162         -  hexio_read test.db 2040 8
   163         -} {3FE0000000000000}
   164         -do_test nan-3.2 {
   165         -  db eval {
   166         -    SELECT x, typeof(x) FROM t1
   167         -  }
   168         -} {0.5 real}
   169         -do_test nan-3.3 {
   170         -  db close
   171         -  hexio_write test.db 2040 FFF8000000000000
   172         -  sqlite3 db test.db
   173         -  db eval {SELECT x, typeof(x) FROM t1}
   174         -} {{} null}
   175         -do_test nan-3.4 {
   176         -  db close
   177         -  hexio_write test.db 2040 7FF8000000000000
   178         -  sqlite3 db test.db
   179         -  db eval {SELECT x, typeof(x) FROM t1}
   180         -} {{} null}
   181         -do_test nan-3.5 {
   182         -  db close
   183         -  hexio_write test.db 2040 FFFFFFFFFFFFFFFF
   184         -  sqlite3 db test.db
   185         -  db eval {SELECT x, typeof(x) FROM t1}
   186         -} {{} null}
   187         -do_test nan-3.6 {
   188         -  db close
   189         -  hexio_write test.db 2040 7FFFFFFFFFFFFFFF
   190         -  sqlite3 db test.db
   191         -  db eval {SELECT x, typeof(x) FROM t1}
   192         -} {{} null}
          154  +if {![nonzero_reserved_bytes]} {
          155  +  do_test nan-3.1 {
          156  +    db eval {
          157  +      DELETE FROM t1;
          158  +      INSERT INTO t1 VALUES(0.5);
          159  +      PRAGMA auto_vacuum=OFF;
          160  +      PRAGMA page_size=1024;
          161  +      VACUUM;
          162  +    }
          163  +    hexio_read test.db 2040 8
          164  +  } {3FE0000000000000}
          165  +  do_test nan-3.2 {
          166  +    db eval {
          167  +      SELECT x, typeof(x) FROM t1
          168  +    }
          169  +  } {0.5 real}
          170  +  do_test nan-3.3 {
          171  +    db close
          172  +    hexio_write test.db 2040 FFF8000000000000
          173  +    sqlite3 db test.db
          174  +    db eval {SELECT x, typeof(x) FROM t1}
          175  +  } {{} null}
          176  +  do_test nan-3.4 {
          177  +    db close
          178  +    hexio_write test.db 2040 7FF8000000000000
          179  +    sqlite3 db test.db
          180  +    db eval {SELECT x, typeof(x) FROM t1}
          181  +  } {{} null}
          182  +  do_test nan-3.5 {
          183  +    db close
          184  +    hexio_write test.db 2040 FFFFFFFFFFFFFFFF
          185  +    sqlite3 db test.db
          186  +    db eval {SELECT x, typeof(x) FROM t1}
          187  +  } {{} null}
          188  +  do_test nan-3.6 {
          189  +    db close
          190  +    hexio_write test.db 2040 7FFFFFFFFFFFFFFF
          191  +    sqlite3 db test.db
          192  +    db eval {SELECT x, typeof(x) FROM t1}
          193  +  } {{} null}
          194  +}
   193    195   
   194    196   # Verify that the sqlite3AtoF routine is able to handle extreme
   195    197   # numbers.
   196    198   #
   197    199   do_test nan-4.1 {
   198    200     db eval {DELETE FROM t1}
   199    201     db eval "INSERT INTO t1 VALUES([string repeat 9 307].0)"

Changes to test/nolock.test.

   178    178          xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
   179    179          xAccess $::tvfs_calls(xAccess)
   180    180   } {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
   181    181   
   182    182   db2 close
   183    183   db close
   184    184   tvfs delete
          185  +
          186  +# 2016-03-11:  Make sure all works when transitioning to WAL mode under nolock.
          187  +#
          188  +do_test nolock-4.1 {
          189  +  forcedelete test.db
          190  +  sqlite3 db file:test.db?nolock=1 -uri 1
          191  +  db eval {
          192  +     PRAGMA journal_mode=WAL;
          193  +     CREATE TABLE t1(x);
          194  +     INSERT INTO t1 VALUES('youngling');
          195  +     SELECT * FROM t1;
          196  +  }
          197  +} {delete youngling}
          198  +db close
          199  +
          200  +do_test nolock-4.2 {
          201  +  forcedelete test.db
          202  +  sqlite3 db test.db
          203  +  db eval {
          204  +    PRAGMA journal_mode=WAL;
          205  +    CREATE TABLE t1(x);
          206  +    INSERT INTO t1 VALUES('catbird');
          207  +    SELECT * FROM t1;
          208  +  }
          209  +} {wal catbird}
          210  +do_test nolock-4.3 {
          211  +  db close
          212  +  sqlite3 db file:test.db?nolock=1 -uri 1
          213  +  set rc [catch {db eval {SELECT * FROM t1}} msg]
          214  +  lappend rc $msg
          215  +} {1 {unable to open database file}}
          216  +
   185    217   finish_test

Changes to test/pager1.test.

  1392   1392     testvfs tv -default 1
  1393   1393     tv sectorsize 4096
  1394   1394     faultsim_delete_and_reopen
  1395   1395   
  1396   1396     execsql { PRAGMA page_size = 1024 }
  1397   1397     for {set ii 0} {$ii < 4} {incr ii} { execsql "CREATE TABLE t${ii}(a, b)" }
  1398   1398   } {}
  1399         -do_test pager1-9.3.2 {
  1400         -  sqlite3 db2 test.db2
  1401         -
  1402         -  execsql {
  1403         -    PRAGMA page_size = 4096;
  1404         -    PRAGMA synchronous = OFF;
  1405         -    CREATE TABLE t1(a, b);
  1406         -    CREATE TABLE t2(a, b);
  1407         -  } db2
  1408         -
  1409         -  sqlite3_backup B db2 main db main
  1410         -  B step 30
  1411         -  list [B step 10000] [B finish]
  1412         -} {SQLITE_DONE SQLITE_OK}
  1413         -do_test pager1-9.3.3 {
  1414         -  db2 close
  1415         -  db close
  1416         -  tv delete
  1417         -  file size test.db2
  1418         -} [file size test.db]
         1399  +if {[nonzero_reserved_bytes]} {
         1400  +  # backup with a page size changes is not possible with the codec
         1401  +  #
         1402  +  do_test pager1-9.3.2codec {
         1403  +    sqlite3 db2 test.db2
         1404  +    execsql {
         1405  +      PRAGMA page_size = 4096;
         1406  +      PRAGMA synchronous = OFF;
         1407  +      CREATE TABLE t1(a, b);
         1408  +      CREATE TABLE t2(a, b);
         1409  +    } db2
         1410  +    sqlite3_backup B db2 main db main
         1411  +    B step 30
         1412  +    list [B step 10000] [B finish]
         1413  +  } {SQLITE_READONLY SQLITE_READONLY}
         1414  +  do_test pager1-9.3.3codec {
         1415  +    db2 close
         1416  +    db close
         1417  +    tv delete
         1418  +    file size test.db2
         1419  +  } [file size test.db2]
         1420  +} else {
         1421  +  do_test pager1-9.3.2 {
         1422  +    sqlite3 db2 test.db2
         1423  +    execsql {
         1424  +      PRAGMA page_size = 4096;
         1425  +      PRAGMA synchronous = OFF;
         1426  +      CREATE TABLE t1(a, b);
         1427  +      CREATE TABLE t2(a, b);
         1428  +    } db2
         1429  +    sqlite3_backup B db2 main db main
         1430  +    B step 30
         1431  +    list [B step 10000] [B finish]
         1432  +  } {SQLITE_DONE SQLITE_OK}
         1433  +  do_test pager1-9.3.3 {
         1434  +    db2 close
         1435  +    db close
         1436  +    tv delete
         1437  +    file size test.db2
         1438  +  } [file size test.db]
         1439  +}
  1419   1440   
  1420   1441   do_test pager1-9.4.1 {
  1421   1442     faultsim_delete_and_reopen
  1422   1443     sqlite3 db2 test.db2
  1423   1444     execsql {
  1424   1445       PRAGMA page_size = 4096;
  1425   1446       CREATE TABLE t1(a, b);
................................................................................
  2443   2464       PRAGMA auto_vacuum = full;
  2444   2465       PRAGMA locking_mode=exclusive;
  2445   2466       CREATE TABLE t1(a, b);
  2446   2467       INSERT INTO t1 VALUES(1, 2);
  2447   2468     }
  2448   2469     file size test.db
  2449   2470   } [expr 1024*3]
  2450         -do_test pager1-29.2 {
  2451         -  execsql {
  2452         -    PRAGMA page_size = 4096;
  2453         -    VACUUM;
  2454         -  }
  2455         -  file size test.db
  2456         -} [expr 4096*3]
         2471  +if {[nonzero_reserved_bytes]} {
         2472  +  # VACUUM with size changes is not possible with the codec.
         2473  +  do_test pager1-29.2 {
         2474  +    catchsql {
         2475  +      PRAGMA page_size = 4096;
         2476  +      VACUUM;
         2477  +    }
         2478  +  } {1 {attempt to write a readonly database}}
         2479  +} else {
         2480  +  do_test pager1-29.2 {
         2481  +    execsql {
         2482  +      PRAGMA page_size = 4096;
         2483  +      VACUUM;
         2484  +    }
         2485  +    file size test.db
         2486  +  } [expr 4096*3]
         2487  +}
  2457   2488   
  2458   2489   #-------------------------------------------------------------------------
  2459   2490   # Test that if an empty database file (size 0 bytes) is opened in 
  2460   2491   # exclusive-locking mode, any journal file is deleted from the file-system
  2461   2492   # without being rolled back. And that the RESERVED lock obtained while
  2462   2493   # doing this is not released.
  2463   2494   #

Changes to test/pageropt.test.

    12     12   # The focus of the tests in this file are to verify that the
    13     13   # pager optimizations implemented in version 3.3.14 work.
    14     14   #
    15     15   # $Id: pageropt.test,v 1.5 2008/08/20 14:49:25 danielk1977 Exp $
    16     16   
    17     17   set testdir [file dirname $argv0]
    18     18   source $testdir/tester.tcl
           19  +do_not_use_codec
    19     20   
    20     21   ifcapable {!pager_pragmas||secure_delete||direct_read} {
    21     22     finish_test
    22     23     return
    23     24   }
    24     25   
    25     26   # Run the SQL statement supplied by the argument and return

Changes to test/permutations.test.

  1064   1064         puts "  $d"
  1065   1065         puts ""
  1066   1066       }
  1067   1067     }
  1068   1068     exit -1
  1069   1069   }
  1070   1070   
  1071         -if {[info script] == $argv0} {
         1071  +if {[file tail $argv0] == "permutations.test"} {
  1072   1072     proc main {argv} {
  1073   1073       if {[llength $argv]==0} {
  1074   1074         help
  1075   1075       } else {
  1076         -      set suite [lindex $argv 0]
         1076  +      set suite [file tail [lindex $argv 0]]
  1077   1077         if {[info exists ::testspec($suite)]==0} help
  1078   1078         set extra ""
  1079   1079         if {[llength $argv]>1} { set extra [list -files [lrange $argv 1 end]] }
  1080   1080         eval run_tests $suite $::testspec($suite) $extra
  1081   1081       }
  1082   1082     }
  1083   1083     main $argv
  1084   1084     finish_test
  1085   1085   }

Changes to test/pragma.test.

  1737   1737     catchsql {PRAGMA data_store_directory}
  1738   1738   } {0 {}}
  1739   1739   
  1740   1740   forcedelete data_dir
  1741   1741   } ;# endif windows
  1742   1742   
  1743   1743   database_may_be_corrupt
         1744  +if {![nonzero_reserved_bytes]} {
  1744   1745   
  1745         -do_test 21.1 {
  1746         -  # Create a corrupt database in testerr.db. And a non-corrupt at test.db.
  1747         -  #
  1748         -  db close
  1749         -  forcedelete test.db
  1750         -  sqlite3 db test.db
  1751         -  execsql { 
  1752         -    PRAGMA page_size = 1024;
  1753         -    PRAGMA auto_vacuum = 0;
  1754         -    CREATE TABLE t1(a PRIMARY KEY, b);
  1755         -    INSERT INTO t1 VALUES(1, 1);
  1756         -  }
  1757         -  for {set i 0} {$i < 10} {incr i} {
  1758         -    execsql { INSERT INTO t1 SELECT a + (1 << $i), b + (1 << $i) FROM t1 }
  1759         -  }
  1760         -  db close
  1761         -  forcecopy test.db testerr.db
  1762         -  hexio_write testerr.db 15000 [string repeat 55 100]
  1763         -} {100}
  1764         -
  1765         -set mainerr {*** in database main ***
         1746  +  do_test 21.1 {
         1747  +    # Create a corrupt database in testerr.db. And a non-corrupt at test.db.
         1748  +    #
         1749  +    db close
         1750  +    forcedelete test.db
         1751  +    sqlite3 db test.db
         1752  +    execsql { 
         1753  +      PRAGMA page_size = 1024;
         1754  +      PRAGMA auto_vacuum = 0;
         1755  +      CREATE TABLE t1(a PRIMARY KEY, b);
         1756  +      INSERT INTO t1 VALUES(1, 1);
         1757  +    }
         1758  +    for {set i 0} {$i < 10} {incr i} {
         1759  +      execsql { INSERT INTO t1 SELECT a + (1 << $i), b + (1 << $i) FROM t1 }
         1760  +    }
         1761  +    db close
         1762  +    forcecopy test.db testerr.db
         1763  +    hexio_write testerr.db 15000 [string repeat 55 100]
         1764  +  } {100}
         1765  +  
         1766  +  set mainerr {*** in database main ***
         1767  +Multiple uses for byte 672 of page 15}
         1768  +  set auxerr {*** in database aux ***
  1766   1769   Multiple uses for byte 672 of page 15}
  1767         -set auxerr {*** in database aux ***
  1768         -Multiple uses for byte 672 of page 15}
  1769         -
  1770         -set mainerr {/{\*\*\* in database main \*\*\*
         1770  +  
         1771  +  set mainerr {/{\*\*\* in database main \*\*\*
  1771   1772   Multiple uses for byte 672 of page 15}.*/}
  1772         -set auxerr {/{\*\*\* in database aux \*\*\*
         1773  +  set auxerr {/{\*\*\* in database aux \*\*\*
  1773   1774   Multiple uses for byte 672 of page 15}.*/}
  1774         -
  1775         -do_test 22.2 {
  1776         -  catch { db close }
  1777         -  sqlite3 db testerr.db
  1778         -  execsql { PRAGMA integrity_check }
  1779         -} $mainerr
  1780         -
  1781         -do_test 22.3.1 {
  1782         -  catch { db close }
  1783         -  sqlite3 db test.db
  1784         -  execsql { 
  1785         -    ATTACH 'testerr.db' AS 'aux';
  1786         -    PRAGMA integrity_check;
  1787         -  }
  1788         -} $auxerr
  1789         -do_test 22.3.2 {
  1790         -  execsql { PRAGMA main.integrity_check; }
  1791         -} {ok}
  1792         -do_test 22.3.3 {
  1793         -  execsql { PRAGMA aux.integrity_check; }
  1794         -} $auxerr
  1795         -
  1796         -do_test 22.4.1 {
  1797         -  catch { db close }
  1798         -  sqlite3 db testerr.db
  1799         -  execsql { 
  1800         -    ATTACH 'test.db' AS 'aux';
  1801         -    PRAGMA integrity_check;
  1802         -  }
  1803         -} $mainerr
  1804         -do_test 22.4.2 {
  1805         -  execsql { PRAGMA main.integrity_check; }
  1806         -} $mainerr
  1807         -do_test 22.4.3 {
  1808         -  execsql { PRAGMA aux.integrity_check; }
  1809         -} {ok}
  1810         -
         1775  +  
         1776  +  do_test 22.2 {
         1777  +    catch { db close }
         1778  +    sqlite3 db testerr.db
         1779  +    execsql { PRAGMA integrity_check }
         1780  +  } $mainerr
         1781  +  
         1782  +  do_test 22.3.1 {
         1783  +    catch { db close }
         1784  +    sqlite3 db test.db
         1785  +    execsql { 
         1786  +      ATTACH 'testerr.db' AS 'aux';
         1787  +      PRAGMA integrity_check;
         1788  +    }
         1789  +  } $auxerr
         1790  +  do_test 22.3.2 {
         1791  +    execsql { PRAGMA main.integrity_check; }
         1792  +  } {ok}
         1793  +  do_test 22.3.3 {
         1794  +    execsql { PRAGMA aux.integrity_check; }
         1795  +  } $auxerr
         1796  +  
         1797  +  do_test 22.4.1 {
         1798  +    catch { db close }
         1799  +    sqlite3 db testerr.db
         1800  +    execsql { 
         1801  +      ATTACH 'test.db' AS 'aux';
         1802  +      PRAGMA integrity_check;
         1803  +    }
         1804  +  } $mainerr
         1805  +  do_test 22.4.2 {
         1806  +    execsql { PRAGMA main.integrity_check; }
         1807  +  } $mainerr
         1808  +  do_test 22.4.3 {
         1809  +    execsql { PRAGMA aux.integrity_check; }
         1810  +  } {ok}
         1811  +}
         1812  +  
  1811   1813   db close
  1812   1814   forcedelete test.db test.db-wal test.db-journal
  1813   1815   sqlite3 db test.db
  1814   1816   sqlite3 db2 test.db
  1815   1817   do_test 23.1 {
  1816   1818     db eval {
  1817   1819       CREATE TABLE t1(a INTEGER PRIMARY KEY,b,c,d);

Changes to test/pragma3.test.

    11     11   # This file implements regression tests for SQLite library.
    12     12   #
    13     13   # This file implements tests for PRAGMA data_version command.
    14     14   #
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
           18  +do_not_use_codec
    18     19   
    19     20   do_execsql_test pragma3-100 {
    20     21     PRAGMA data_version;
    21     22   } {1}
    22     23   do_execsql_test pragma3-101 {
    23     24     PRAGMA temp.data_version;
    24     25   } {1}

Changes to test/spellfix3.test.

    31     31     SELECT spellfix1_scriptcode('וַיֹּ֥אמֶר אֱלֹהִ֖ים יְהִ֣י א֑וֹר וַֽיְהִי־אֽוֹר׃');
    32     32   } {125}
    33     33   do_execsql_test 140 {
    34     34     SELECT spellfix1_scriptcode('فِي ذَلِكَ الوَقتِ، قالَ اللهُ: لِيَكُنْ نُورٌ. فَصَارَ نُورٌ.');
    35     35   } {160}
    36     36   do_execsql_test 200 {
    37     37     SELECT spellfix1_scriptcode('+3.14159');
    38         -} {999}
           38  +} {215}
    39     39   do_execsql_test 210 {
    40     40     SELECT spellfix1_scriptcode('And God said: "Да будет свет"');
    41     41   } {998}
           42  +do_execsql_test 220 {
           43  +  SELECT spellfix1_scriptcode('+3.14159 light');
           44  +} {215}
           45  +do_execsql_test 230 {
           46  +  SELECT spellfix1_scriptcode('+3.14159 свет');
           47  +} {220}
           48  +do_execsql_test 240 {
           49  +  SELECT spellfix1_scriptcode('וַיֹּ֥אמֶר +3.14159');
           50  +} {125}
    42     51   
    43     52   finish_test

Changes to test/stat.test.

    17     17   set testprefix stat
    18     18   
    19     19   ifcapable !vtab||!compound {
    20     20     finish_test
    21     21     return
    22     22   }
    23     23   
           24  +# This module uses hard-coded results that depend on exact measurements of
           25  +# pages sizes at the byte level, and hence will not work if the reserved_bytes
           26  +# value is nonzero.
           27  +if {[nonzero_reserved_bytes]} {finish_test; return;}
    24     28   
    25     29   set ::asc 1
    26     30   proc a_string {n} { string range [string repeat [incr ::asc]. $n] 1 $n }
    27     31   db func a_string a_string
    28     32   
    29     33   register_dbstat_vtab db
    30     34   do_execsql_test stat-0.0 {

Changes to test/superlock.test.

    11     11   #
    12     12   
    13     13   set testdir [file dirname $argv0]
    14     14   source $testdir/tester.tcl
    15     15   source $testdir/lock_common.tcl
    16     16   
    17     17   set testprefix superlock
           18  +do_not_use_codec
    18     19   
    19     20   # Test organization:
    20     21   #
    21     22   #   1.*: Test superlock on a rollback database. Test that once the db is
    22     23   #        superlocked, it is not possible for a second client to read from
    23     24   #        it.
    24     25   #
................................................................................
   234    235   do_catchsql_test 6.7 { SELECT * FROM t1 } {1 {no such table: t1}}
   235    236   do_catchsql_test 6.8 { SELECT * FROM t2 } {0 {a b}}
   236    237   
   237    238   db_swap test.db2 test.db
   238    239   do_catchsql_test 6.9 { SELECT * FROM t1 } {0 {1 2 3 4}}
   239    240   do_catchsql_test 6.10 { SELECT * FROM t2 } {1 {no such table: t2}}
   240    241   
   241         -do_execsql_test  6.11 { 
   242         -  PRAGMA journal_mode = delete;
   243         -  PRAGMA page_size = 512;
   244         -  VACUUM;
   245         -  PRAGMA journal_mode = wal;
   246         -  INSERT INTO t1 VALUES(5, 6);
   247         -} {delete wal}
          242  +if {[nonzero_reserved_bytes]} {
          243  +  # Vacuum with a size change is not allowed with the codec
          244  +  do_execsql_test  6.11codec { 
          245  +    PRAGMA journal_mode = delete;
          246  +    VACUUM;
          247  +    PRAGMA journal_mode = wal;
          248  +    INSERT INTO t1 VALUES(5, 6);
          249  +  } {delete wal}
          250  +} else {
          251  +  do_execsql_test  6.11 { 
          252  +    PRAGMA journal_mode = delete;
          253  +    PRAGMA page_size = 512;
          254  +    VACUUM;
          255  +    PRAGMA journal_mode = wal;
          256  +    INSERT INTO t1 VALUES(5, 6);
          257  +  } {delete wal}
          258  +}
   248    259   
   249    260   db_swap test.db2 test.db
   250    261   do_catchsql_test 6.12 { SELECT * FROM t1 } {1 {no such table: t1}}
   251    262   do_catchsql_test 6.13 { SELECT * FROM t2 } {0 {a b}}
   252    263   
   253    264   db_swap test.db2 test.db
   254    265   do_catchsql_test 6.14 { SELECT * FROM t1 } {0 {1 2 3 4 5 6}}
   255    266   do_catchsql_test 6.15 { SELECT * FROM t2 } {1 {no such table: t2}}
   256    267   
   257    268   finish_test

Changes to test/tclsqlite.test.

    18     18   # $Id: tclsqlite.test,v 1.73 2009/03/16 13:19:36 danielk1977 Exp $
    19     19   
    20     20   set testdir [file dirname $argv0]
    21     21   source $testdir/tester.tcl
    22     22   
    23     23   # Check the error messages generated by tclsqlite
    24     24   #
           25  +set r "sqlite_orig HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
    25     26   if {[sqlite3 -has-codec]} {
    26         -  set r "sqlite_orig HANDLE FILENAME ?-key CODEC-KEY?"
    27         -} else {
    28         -  set r "sqlite_orig HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
           27  +  append r " ?-key CODECKEY?"
    29     28   }
    30     29   do_test tcl-1.1 {
    31     30     set v [catch {sqlite3 bogus} msg]
    32     31     regsub {really_sqlite3} $msg {sqlite3} msg
    33     32     lappend v $msg
    34     33   } [list 1 "wrong # args: should be \"$r\""]
    35     34   do_test tcl-1.2 {

Changes to test/tester.tcl.

   369    369   # This command should be called after loading tester.tcl from within
   370    370   # all test scripts that are incompatible with encryption codecs.
   371    371   #
   372    372   proc do_not_use_codec {} {
   373    373     set ::do_not_use_codec 1
   374    374     reset_db
   375    375   }
          376  +
          377  +# Return true if the "reserved_bytes" integer on database files is non-zero.
          378  +#
          379  +proc nonzero_reserved_bytes {} {
          380  +  return [sqlite3 -has-codec]
          381  +}
   376    382   
   377    383   # Print a HELP message and exit
   378    384   #
   379    385   proc print_help_and_quit {} {
   380    386     puts {Options:
   381    387     --pause                  Wait for user input before continuing
   382    388     --soft-heap-limit=N      Set the soft-heap-limit to N
................................................................................
   407    413     #   --soak=N
   408    414     #   --file-retries=N
   409    415     #   --file-retry-delay=N
   410    416     #   --start=[$permutation:]$testfile
   411    417     #   --match=$pattern
   412    418     #   --verbose=$val
   413    419     #   --output=$filename
          420  +  #   -q                                      Reduce output
          421  +  #   --testdir=$dir                          Run tests in subdirectory $dir
   414    422     #   --help
   415    423     #
   416    424     set cmdlinearg(soft-heap-limit)    0
   417    425     set cmdlinearg(maxerror)        1000
   418    426     set cmdlinearg(malloctrace)        0
   419    427     set cmdlinearg(backtrace)         10
   420    428     set cmdlinearg(binarylog)          0
................................................................................
   421    429     set cmdlinearg(soak)               0
   422    430     set cmdlinearg(file-retries)       0
   423    431     set cmdlinearg(file-retry-delay)   0
   424    432     set cmdlinearg(start)             ""
   425    433     set cmdlinearg(match)             ""
   426    434     set cmdlinearg(verbose)           ""
   427    435     set cmdlinearg(output)            ""
          436  +  set cmdlinearg(testdir)           "testdir"
   428    437   
   429    438     set leftover [list]
   430    439     foreach a $argv {
   431    440       switch -regexp -- $a {
   432    441         {^-+pause$} {
   433    442           # Wait for user input before continuing. This is to give the user an
   434    443           # opportunity to connect profiling tools to the process.
................................................................................
   450    459         }
   451    460         {^-+backtrace=.+$} {
   452    461           foreach {dummy cmdlinearg(backtrace)} [split $a =] break
   453    462           sqlite3_memdebug_backtrace $value
   454    463         }
   455    464         {^-+binarylog=.+$} {
   456    465           foreach {dummy cmdlinearg(binarylog)} [split $a =] break
          466  +        set cmdlinearg(binarylog) [file normalize $cmdlinearg(binarylog)]
   457    467         }
   458    468         {^-+soak=.+$} {
   459    469           foreach {dummy cmdlinearg(soak)} [split $a =] break
   460    470           set ::G(issoak) $cmdlinearg(soak)
   461    471         }
   462    472         {^-+file-retries=.+$} {
   463    473           foreach {dummy cmdlinearg(file-retries)} [split $a =] break
................................................................................
   482    492   
   483    493           set ::G(match) $cmdlinearg(match)
   484    494           if {$::G(match) == ""} {unset ::G(match)}
   485    495         }
   486    496   
   487    497         {^-+output=.+$} {
   488    498           foreach {dummy cmdlinearg(output)} [split $a =] break
          499  +        set cmdlinearg(output) [file normalize $cmdlinearg(output)]
   489    500           if {$cmdlinearg(verbose)==""} {
   490    501             set cmdlinearg(verbose) 2
   491    502           }
   492    503         }
   493    504         {^-+verbose=.+$} {
   494    505           foreach {dummy cmdlinearg(verbose)} [split $a =] break
   495    506           if {$cmdlinearg(verbose)=="file"} {
   496    507             set cmdlinearg(verbose) 2
   497    508           } elseif {[string is boolean -strict $cmdlinearg(verbose)]==0} {
   498    509             error "option --verbose= must be set to a boolean or to \"file\""
   499    510           }
   500    511         }
          512  +      {^-+testdir=.*$} {
          513  +        foreach {dummy cmdlinearg(testdir)} [split $a =] break
          514  +      }
   501    515         {.*help.*} {
   502    516            print_help_and_quit
   503    517         }
   504    518         {^-q$} {
   505    519           set cmdlinearg(output) test-out.txt
   506    520           set cmdlinearg(verbose) 2
   507    521         }
   508    522   
   509    523         default {
   510         -        lappend leftover $a
          524  +        lappend leftover [file normalize $a]
   511    525         }
   512    526       }
          527  +  }
          528  +  set testdir [file normalize $testdir]
          529  +  set cmdlinearg(TESTFIXTURE_HOME) [pwd]
          530  +  set cmdlinearg(INFO_SCRIPT) [file normalize [info script]]
          531  +  set argv0 [file normalize $argv0]
          532  +  if {$cmdlinearg(testdir)!=""} {
          533  +    file mkdir $cmdlinearg(testdir)
          534  +    cd $cmdlinearg(testdir)
   513    535     }
   514    536     set argv $leftover
   515    537   
   516    538     # Install the malloc layer used to inject OOM errors. And the 'automatic'
   517    539     # extensions. This only needs to be done once for the process.
   518    540     #
   519    541     sqlite3_shutdown

Changes to test/tkt4018.test.

    12     12   #
    13     13   # This file implements tests to verify that ticket #4018 has been
    14     14   # fixed.  
    15     15   #
    16     16   
    17     17   set testdir [file dirname $argv0]
    18     18   source $testdir/tester.tcl
           19  +do_not_use_codec
    19     20   
    20     21   proc testsql {sql} {
    21     22     set fd [open tf_main.tcl w]
    22     23     puts $fd [subst -nocommands {
    23     24       sqlite3_test_control_pending_byte 0x0010000
    24     25       sqlite3 db test.db
    25     26       set rc [catch { db eval {$sql} } msg]

Changes to test/wal.test.

  1374   1374   do_test wal-21.3 {
  1375   1375     execsql { PRAGMA integrity_check }
  1376   1376   } {ok}
  1377   1377   
  1378   1378   #-------------------------------------------------------------------------
  1379   1379   # Test reading and writing of databases with different page-sizes.
  1380   1380   #
         1381  +incr ::do_not_use_codec
  1381   1382   foreach pgsz {512 1024 2048 4096 8192 16384 32768 65536} {
  1382   1383     do_multiclient_test tn [string map [list %PGSZ% $pgsz] {
  1383   1384       do_test wal-22.%PGSZ%.$tn.1 {
  1384   1385         sql1 {
  1385   1386           PRAGMA main.page_size = %PGSZ%;
  1386   1387           PRAGMA auto_vacuum = 0;
  1387   1388           PRAGMA journal_mode = WAL;
................................................................................
  1394   1395       do_test wal-22.%PGSZ%.$tn.2 { sql2 { PRAGMA integrity_check } } {ok}
  1395   1396       do_test wal-22.%PGSZ%.$tn.3 {
  1396   1397         sql1 {PRAGMA wal_checkpoint}
  1397   1398         expr {[file size test.db] % %PGSZ%}
  1398   1399       } {0}
  1399   1400     }]
  1400   1401   }
         1402  +incr ::do_not_use_codec -1
  1401   1403   
  1402   1404   #-------------------------------------------------------------------------
  1403   1405   # Test that when 1 or more pages are recovered from a WAL file, 
  1404   1406   # sqlite3_log() is invoked to report this to the user.
  1405   1407   #
  1406   1408   ifcapable curdir {
  1407   1409     set walfile [file nativename [file join [get_pwd] test.db-wal]]

Changes to test/wal5.test.

    14     14   #
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   source $testdir/lock_common.tcl
    19     19   source $testdir/wal_common.tcl
    20     20   ifcapable !wal {finish_test ; return }
           21  +do_not_use_codec
    21     22   
    22     23   set testprefix wal5
    23     24   
    24     25   proc db_page_count  {{file test.db}} { expr [file size $file] / 1024 }
    25     26   proc wal_page_count {{file test.db}} { wal_frame_count ${file}-wal 1024 }
    26     27   
    27     28   

Changes to test/wal8.test.

    23     23   # first read transaction is executed), and the "PRAGMA page_size = XXX"
    24     24   # is a no-op.
    25     25   #
    26     26   set testdir [file dirname $argv0]
    27     27   source $testdir/tester.tcl
    28     28   set ::testprefix wal8
    29     29   ifcapable !wal {finish_test ; return }
           30  +do_not_use_codec
    30     31   
    31     32   db close
    32     33   forcedelete test.db test.db-wal
    33     34   
    34     35   sqlite3 db test.db
    35     36   sqlite3 db2 test.db
    36     37   

Changes to test/walbak.test.

   123    123         INSERT INTO t1 SELECT randomblob(500), randomblob(500) FROM t1; /* 16 */
   124    124         INSERT INTO t1 SELECT randomblob(500), randomblob(500) FROM t1; /* 32 */
   125    125         INSERT INTO t1 SELECT randomblob(500), randomblob(500) FROM t1; /* 64 */
   126    126       COMMIT;
   127    127     }
   128    128   } {}
   129    129   do_test walbak-2.2 {
          130  +  forcedelete abc.db
   130    131     db backup abc.db
   131    132     sqlite3 db2 abc.db
   132    133     string compare [sig db] [sig db2]
   133    134   } {0}
   134    135   
   135    136   do_test walbak-2.3 {
   136    137     sqlite3_backup B db2 main db main
................................................................................
   235    236         PRAGMA page_size = 2048;
   236    237         PRAGMA journal_mode = PERSIST;
   237    238         CREATE TABLE xx(x);
   238    239       }
   239    240     }
   240    241   
   241    242   } {
          243  +  if {$tn==4 && [sqlite3 -has-codec]} continue
   242    244     foreach f [glob -nocomplain test.db*] { forcedelete $f }
   243    245   
   244    246     eval $setup
   245    247   
   246    248     do_test walbak-3.$tn.1 {
   247    249       execsql {
   248    250         CREATE TABLE t1(a, b);

Changes to test/walro.test.

   208    208         INSERT INTO t2 SELECT x||y, y||x FROM t2;
   209    209         INSERT INTO t2 SELECT x||y, y||x FROM t2;
   210    210         INSERT INTO t2 SELECT x||y, y||x FROM t2;
   211    211         INSERT INTO t2 SELECT x||y, y||x FROM t2;
   212    212         INSERT INTO t2 SELECT x||y, y||x FROM t2;
   213    213       }
   214    214       file size test.db-wal
   215         -  } {147800}
          215  +  } [expr {[nonzero_reserved_bytes]?148848:147800}]
   216    216     do_test 1.4.4.2 {
   217    217       csql1 { SELECT * FROM t1 }
   218    218     } {0 {a b c d e f g h i j k l 1 2 3 4 5 6}}
   219    219     do_test 1.4.4.3 {
   220    220       csql2 COMMIT
   221    221       csql1 { SELECT count(*) FROM t2 }
   222    222     } {0 512}

Changes to test/where2.test.

   760    760   #
   761    761   do_execsql_test where2-13.1 {
   762    762     CREATE TABLE t13(a,b);
   763    763     CREATE INDEX t13a ON t13(a);
   764    764     INSERT INTO t13 VALUES(4,5);
   765    765     SELECT * FROM t13 WHERE (1=2 AND a=3) OR a=4;
   766    766   } {4 5}
          767  +
          768  +# https://www.sqlite.org/src/info/5e3c886796e5512e  (2016-03-09)
          769  +# Correlated subquery on the RHS of an IN operator 
          770  +#
          771  +do_execsql_test where2-14.1 {
          772  +  CREATE TABLE t14a(x INTEGER PRIMARY KEY);
          773  +  INSERT INTO t14a(x) VALUES(1),(2),(3),(4);
          774  +  CREATE TABLE t14b(y INTEGER PRIMARY KEY);
          775  +  INSERT INTO t14b(y) VALUES(1);
          776  +  SELECT x FROM t14a WHERE x NOT IN (SELECT x FROM t14b);
          777  +} {}
   767    778   
   768    779   finish_test

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

   661    661   
   662    662           REM
   663    663           REM NOTE: Copy the "sqlite3.pdb" file to the appropriate directory for
   664    664           REM       the build and platform beneath the binary directory unless we
   665    665           REM       are prevented from doing so.
   666    666           REM
   667    667           IF NOT DEFINED NOSYMBOLS (
   668         -          %__ECHO% XCOPY "%DLL_PDB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
          668  +          IF EXIST "%DLL_PDB_FILE_NAME%" (
          669  +            %__ECHO% XCOPY "%DLL_PDB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
   669    670   
   670         -          IF ERRORLEVEL 1 (
   671         -            ECHO Failed to copy "%DLL_PDB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
   672         -            GOTO errors
          671  +            IF ERRORLEVEL 1 (
          672  +              ECHO Failed to copy "%DLL_PDB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
          673  +              GOTO errors
          674  +            )
   673    675             )
   674    676           )
   675    677   
   676    678           REM
   677    679           REM NOTE: If requested, also build the shell executable.
   678    680           REM
   679    681           IF DEFINED BUILD_ALL_SHELL (
................................................................................
   718    720   
   719    721             REM
   720    722             REM NOTE: Copy the "sqlite3sh.pdb" file to the appropriate directory
   721    723             REM       for the build and platform beneath the binary directory
   722    724             REM       unless we are prevented from doing so.
   723    725             REM
   724    726             IF NOT DEFINED NOSYMBOLS (
   725         -            %__ECHO% XCOPY "%EXE_PDB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
          727  +            IF EXIST "%EXE_PDB_FILE_NAME%" (
          728  +              %__ECHO% XCOPY "%EXE_PDB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
   726    729   
   727         -            IF ERRORLEVEL 1 (
   728         -              ECHO Failed to copy "%EXE_PDB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
   729         -              GOTO errors
          730  +              IF ERRORLEVEL 1 (
          731  +                ECHO Failed to copy "%EXE_PDB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
          732  +                GOTO errors
          733  +              )
   730    734               )
   731    735             )
   732    736           )
   733    737         )
   734    738       )
   735    739     )
   736    740