/ Check-in [1c78d892]
Login

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

Overview
Comment:Merge latest trunk changes with this branch.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | fts5
Files: files | file ages | folders
SHA1:1c78d8920fb59da3cb97dd2eb09b3e08dfd14259
User & Date: dan 2015-04-24 20:18:21
Context
2015-04-25
18:56
Add tests for fts5. check-in: e748651c user: dan tags: fts5
2015-04-24
20:18
Merge latest trunk changes with this branch. check-in: 1c78d892 user: dan tags: fts5
19:41
Add the "unindexed" column option to fts5. check-in: 86309961 user: dan tags: fts5
18:31
Fix fuzzershell so that it works with SQLITE_OMIT_TRACE. check-in: dc88fe7e user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Makefile.in.

   947    947   TESTFIXTURE_SRC += $(TESTFIXTURE_SRC$(USE_AMALGAMATION))
   948    948   
   949    949   testfixture$(TEXE):	$(TESTFIXTURE_SRC)
   950    950   	$(LTLINK) -DSQLITE_NO_SYNC=1 $(TEMP_STORE) $(TESTFIXTURE_FLAGS) \
   951    951   		-o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS)
   952    952   
   953    953   # A very detailed test running most or all test cases
   954         -fulltest:	testfixture$(TEXE) sqlite3$(TEXE)
          954  +fulltest:	testfixture$(TEXE) sqlite3$(TEXE) fuzztest
   955    955   	./testfixture$(TEXE) $(TOP)/test/all.test
   956    956   
   957    957   # Really really long testing
   958    958   soaktest:	testfixture$(TEXE) sqlite3$(TEXE)
   959    959   	./testfixture$(TEXE) $(TOP)/test/all.test -soak=1
   960    960   
   961    961   # Do extra testing but not aeverything.
   962    962   fulltestonly:	testfixture$(TEXE) sqlite3$(TEXE)
   963    963   	./testfixture$(TEXE) $(TOP)/test/full.test
   964    964   
          965  +# Fuzz testing
          966  +fuzztest:	fuzzershell$(TEXE)
          967  +	./fuzzershell$(TEXE) -f $(TOP)/test/fuzzdata1.txt
          968  +
   965    969   # This is the common case.  Run many tests but not those that take
   966    970   # a really long time.
   967    971   #
   968         -test:	testfixture$(TEXE) sqlite3$(TEXE)
          972  +test:	testfixture$(TEXE) sqlite3$(TEXE) fuzztest
   969    973   	./testfixture$(TEXE) $(TOP)/test/veryquick.test
   970    974   
   971    975   # Run a test using valgrind.  This can take a really long time
   972    976   # because valgrind is so much slower than a native machine.
   973    977   #
   974         -valgrindtest:	testfixture$(TEXE) sqlite3$(TEXE)
          978  +valgrindtest:	testfixture$(TEXE) sqlite3$(TEXE) fuzzershell$(TEXE)
          979  +	valgrind -v ./fuzzershell$(TEXE) -f $(TOP)/test/fuzzdata1.txt
   975    980   	OMIT_MISUSE=1 valgrind -v ./testfixture$(TEXE) $(TOP)/test/permutations.test valgrind
   976    981   
   977    982   # A very fast test that checks basic sanity.  The name comes from
   978    983   # the 60s-era electronics testing:  "Turn it on and see if smoke
   979    984   # comes out."
   980    985   #
   981         -smoketest:	testfixture$(TEXE)
          986  +smoketest:	testfixture$(TEXE) fuzzershell$(TEXE)
   982    987   	./testfixture$(TEXE) $(TOP)/test/main.test
   983    988   
   984    989   sqlite3_analyzer.c: sqlite3.c $(TOP)/src/test_stat.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
   985    990   	echo "#define TCLSH 2" > $@
   986    991   	cat sqlite3.c $(TOP)/src/test_stat.c $(TOP)/src/tclsqlite.c >> $@
   987    992   	echo "static const char *tclsh_main_loop(void){" >> $@
   988    993   	echo "static const char *zMainloop = " >> $@

Changes to Makefile.msc.

  1620   1620   		-DBUILD_sqlite -I$(TCLINCDIR) \
  1621   1621   		$(TESTFIXTURE_SRC) \
  1622   1622   		/link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
  1623   1623   
  1624   1624   extensiontest: testfixture.exe testloadext.dll
  1625   1625   	.\testfixture.exe $(TOP)\test\loadext.test
  1626   1626   
  1627         -fulltest:	testfixture.exe sqlite3.exe
         1627  +fulltest:	testfixture.exe sqlite3.exe fuzztest
  1628   1628   	.\testfixture.exe $(TOP)\test\all.test
  1629   1629   
  1630   1630   soaktest:	testfixture.exe sqlite3.exe
  1631   1631   	.\testfixture.exe $(TOP)\test\all.test -soak=1
  1632   1632   
  1633         -fulltestonly:	testfixture.exe sqlite3.exe
         1633  +fulltestonly:	testfixture.exe sqlite3.exe fuzztest
  1634   1634   	.\testfixture.exe $(TOP)\test\full.test
  1635   1635   
  1636   1636   queryplantest:	testfixture.exe sqlite3.exe
  1637   1637   	.\testfixture.exe $(TOP)\test\permutations.test queryplanner
  1638   1638   
  1639         -test:	testfixture.exe sqlite3.exe
         1639  +fuzztest:	fuzzershell.exe
         1640  +	.\fuzzershell.exe -f $(TOP)\test\fuzzdata1.txt
         1641  +
         1642  +test:	testfixture.exe sqlite3.exe fuzztest
  1640   1643   	.\testfixture.exe $(TOP)\test\veryquick.test
  1641   1644   
  1642   1645   smoketest:	testfixture.exe
  1643   1646   	.\testfixture.exe $(TOP)\test\main.test
  1644   1647   
  1645   1648   sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\test_stat.c $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl
  1646   1649   	copy $(SQLITE3C) + $(TOP)\src\test_stat.c + $(TOP)\src\tclsqlite.c $@

Changes to ext/fts3/fts3.c.

  2806   2806     ** for the pending-terms. If this is a scan, then this call must be being
  2807   2807     ** made by an fts4aux module, not an FTS table. In this case calling
  2808   2808     ** Fts3SegReaderPending might segfault, as the data structures used by 
  2809   2809     ** fts4aux are not completely populated. So it's easiest to filter these
  2810   2810     ** calls out here.  */
  2811   2811     if( iLevel<0 && p->aIndex ){
  2812   2812       Fts3SegReader *pSeg = 0;
  2813         -    rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix, &pSeg);
         2813  +    rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan, &pSeg);
  2814   2814       if( rc==SQLITE_OK && pSeg ){
  2815   2815         rc = fts3SegReaderCursorAppend(pCsr, pSeg);
  2816   2816       }
  2817   2817     }
  2818   2818   
  2819   2819     if( iLevel!=FTS3_SEGCURSOR_PENDING ){
  2820   2820       if( rc==SQLITE_OK ){

Changes to ext/fts3/fts3_write.c.

   322    322   /* 21 */  "SELECT size FROM %Q.'%q_docsize' WHERE docid=?",
   323    323   /* 22 */  "SELECT value FROM %Q.'%q_stat' WHERE id=?",
   324    324   /* 23 */  "REPLACE INTO %Q.'%q_stat' VALUES(?,?)",
   325    325   /* 24 */  "",
   326    326   /* 25 */  "",
   327    327   
   328    328   /* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?",
   329         -/* 27 */ "SELECT DISTINCT level / (1024 * ?) FROM %Q.'%q_segdir'",
          329  +/* 27 */ "SELECT ? UNION SELECT level / (1024 * ?) FROM %Q.'%q_segdir'",
   330    330   
   331    331   /* This statement is used to determine which level to read the input from
   332    332   ** when performing an incremental merge. It returns the absolute level number
   333    333   ** of the oldest level in the db that contains at least ? segments. Or,
   334    334   ** if no level in the FTS index contains more than ? segments, the statement
   335    335   ** returns zero rows.  */
   336    336   /* 28 */ "SELECT level FROM %Q.'%q_segdir' GROUP BY level HAVING count(*)>=?"
................................................................................
  3440   3440     int bSeenDone = 0;
  3441   3441     int rc;
  3442   3442     sqlite3_stmt *pAllLangid = 0;
  3443   3443   
  3444   3444     rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
  3445   3445     if( rc==SQLITE_OK ){
  3446   3446       int rc2;
  3447         -    sqlite3_bind_int(pAllLangid, 1, p->nIndex);
         3447  +    sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid);
         3448  +    sqlite3_bind_int(pAllLangid, 2, p->nIndex);
  3448   3449       while( sqlite3_step(pAllLangid)==SQLITE_ROW ){
  3449   3450         int i;
  3450   3451         int iLangid = sqlite3_column_int(pAllLangid, 0);
  3451   3452         for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
  3452   3453           rc = fts3SegmentMerge(p, iLangid, i, FTS3_SEGCURSOR_ALL);
  3453   3454           if( rc==SQLITE_DONE ){
  3454   3455             bSeenDone = 1;
................................................................................
  4772   4773     i = pHint->n-2;
  4773   4774     while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
  4774   4775     while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
  4775   4776   
  4776   4777     pHint->n = i;
  4777   4778     i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel);
  4778   4779     i += fts3GetVarint32(&pHint->a[i], pnInput);
  4779         -  if( i!=nHint ) return SQLITE_CORRUPT_VTAB;
         4780  +  if( i!=nHint ) return FTS_CORRUPT_VTAB;
  4780   4781   
  4781   4782     return SQLITE_OK;
  4782   4783   }
  4783   4784   
  4784   4785   
  4785   4786   /*
  4786   4787   ** Attempt an incremental merge that writes nMerge leaf blocks.
................................................................................
  5140   5141     u64 cksum2 = 0;                 /* Checksum based on %_content contents */
  5141   5142     sqlite3_stmt *pAllLangid = 0;   /* Statement to return all language-ids */
  5142   5143   
  5143   5144     /* This block calculates the checksum according to the FTS index. */
  5144   5145     rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
  5145   5146     if( rc==SQLITE_OK ){
  5146   5147       int rc2;
  5147         -    sqlite3_bind_int(pAllLangid, 1, p->nIndex);
         5148  +    sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid);
         5149  +    sqlite3_bind_int(pAllLangid, 2, p->nIndex);
  5148   5150       while( rc==SQLITE_OK && sqlite3_step(pAllLangid)==SQLITE_ROW ){
  5149   5151         int iLangid = sqlite3_column_int(pAllLangid, 0);
  5150   5152         int i;
  5151   5153         for(i=0; i<p->nIndex; i++){
  5152   5154           cksum1 = cksum1 ^ fts3ChecksumIndex(p, iLangid, i, &rc);
  5153   5155         }
  5154   5156       }
  5155   5157       rc2 = sqlite3_reset(pAllLangid);
  5156   5158       if( rc==SQLITE_OK ) rc = rc2;
  5157   5159     }
  5158   5160   
  5159   5161     /* This block calculates the checksum according to the %_content table */
  5160         -  rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
  5161   5162     if( rc==SQLITE_OK ){
  5162   5163       sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule;
  5163   5164       sqlite3_stmt *pStmt = 0;
  5164   5165       char *zSql;
  5165   5166      
  5166   5167       zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist);
  5167   5168       if( !zSql ){
................................................................................
  5250   5251   */
  5251   5252   static int fts3DoIntegrityCheck(
  5252   5253     Fts3Table *p                    /* FTS3 table handle */
  5253   5254   ){
  5254   5255     int rc;
  5255   5256     int bOk = 0;
  5256   5257     rc = fts3IntegrityCheck(p, &bOk);
  5257         -  if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_CORRUPT_VTAB;
         5258  +  if( rc==SQLITE_OK && bOk==0 ) rc = FTS_CORRUPT_VTAB;
  5258   5259     return rc;
  5259   5260   }
  5260   5261   
  5261   5262   /*
  5262   5263   ** Handle a 'special' INSERT of the form:
  5263   5264   **
  5264   5265   **   "INSERT INTO tbl(tbl) VALUES(<expr>)"

Changes to ext/fts5/fts5_config.c.

   403    403   **
   404    404   ** If *pRc is other than SQLITE_OK when this function is called, it is
   405    405   ** a no-op (NULL is returned). Otherwise, if an OOM occurs within this
   406    406   ** function, *pRc is set to SQLITE_NOMEM before returning. *pRc is *not*
   407    407   ** set if a parse error (failed to find close quote) occurs.
   408    408   */
   409    409   static const char *fts5ConfigGobbleWord(
   410         -  int *pRc, 
   411         -  const char *zIn, 
   412         -  char **pzOut, 
   413         -  int *pbQuoted
          410  +  int *pRc,                       /* IN/OUT: Error code */
          411  +  const char *zIn,                /* Buffer to gobble string/bareword from */
          412  +  char **pzOut,                   /* OUT: malloc'd buffer containing str/bw */
          413  +  int *pbQuoted                   /* OUT: Set to true if dequoting required */
   414    414   ){
   415    415     const char *zRet = 0;
   416    416     *pbQuoted = 0;
   417    417     *pzOut = 0;
   418    418   
   419    419     if( *pRc==SQLITE_OK ){
   420    420       int nIn = strlen(zIn);

Changes to main.mk.

   707    707   
   708    708   fts3-testfixture$(EXE): sqlite3.c fts3amal.c $(TESTSRC) $(TOP)/src/tclsqlite.c
   709    709   	$(TCCX) $(TCL_FLAGS) -DTCLSH=1 $(TESTFIXTURE_FLAGS)                  \
   710    710   	-DSQLITE_ENABLE_FTS3=1                                               \
   711    711   		$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c fts3amal.c       \
   712    712   		-o testfixture$(EXE) $(LIBTCL) $(THREADLIB)
   713    713   
   714         -fulltest:	testfixture$(EXE) sqlite3$(EXE)
          714  +fulltest:	testfixture$(EXE) sqlite3$(EXE) fuzztest
   715    715   	./testfixture$(EXE) $(TOP)/test/all.test
   716    716   
   717    717   soaktest:	testfixture$(EXE) sqlite3$(EXE)
   718    718   	./testfixture$(EXE) $(TOP)/test/all.test -soak=1
   719    719   
   720         -fulltestonly:	testfixture$(EXE) sqlite3$(EXE)
          720  +fulltestonly:	testfixture$(EXE) sqlite3$(EXE) fuzztest
   721    721   	./testfixture$(EXE) $(TOP)/test/full.test
   722    722   
   723    723   queryplantest:	testfixture$(EXE) sqlite3$(EXE)
   724    724   	./testfixture$(EXE) $(TOP)/test/permutations.test queryplanner
   725    725   
   726         -test:	testfixture$(EXE) sqlite3$(EXE)
          726  +fuzztest:	fuzzershell$(EXE)
          727  +	./fuzzershell$(EXE) -f $(TOP)/test/fuzzdata1.txt
          728  +
          729  +test:	testfixture$(EXE) sqlite3$(EXE) fuzztest
   727    730   	./testfixture$(EXE) $(TOP)/test/veryquick.test
   728    731   
          732  +# Run a test using valgrind.  This can take a really long time
          733  +# because valgrind is so much slower than a native machine.
          734  +#
          735  +valgrindtest:	testfixture$(EXE) sqlite3$(EXE) fuzzershell$(EXE)
          736  +	valgrind -v ./fuzzershell$(EXE) -f $(TOP)/test/fuzzdata1.txt
          737  +	OMIT_MISUSE=1 valgrind -v ./testfixture$(EXE) $(TOP)/test/permutations.test valgrind
          738  +
   729    739   # The next two rules are used to support the "threadtest" target. Building
   730    740   # threadtest runs a few thread-safety tests that are implemented in C. This
   731    741   # target is invoked by the releasetest.tcl script.
   732    742   # 
   733    743   THREADTEST3_SRC = $(TOP)/test/threadtest3.c    \
   734    744                     $(TOP)/test/tt3_checkpoint.c \
   735    745                     $(TOP)/test/tt3_index.c      \

Changes to src/expr.c.

  3379   3379       }
  3380   3380       case TK_AS: {
  3381   3381         sqlite3TreeViewLine(pView,"AS %Q", pExpr->u.zToken);
  3382   3382         sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
  3383   3383         break;
  3384   3384       }
  3385   3385       case TK_ID: {
  3386         -      sqlite3TreeViewLine(pView,"ID %Q", pExpr->u.zToken);
         3386  +      sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);
  3387   3387         break;
  3388   3388       }
  3389   3389   #ifndef SQLITE_OMIT_CAST
  3390   3390       case TK_CAST: {
  3391   3391         /* Expressions of the form:   CAST(pLeft AS token) */
  3392   3392         sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);
  3393   3393         sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);

Changes to src/resolve.c.

    75     75   **     SELECT a+b, c+d FROM t1 ORDER BY 1 COLLATE nocase;
    76     76   **
    77     77   ** Should be transformed into:
    78     78   **
    79     79   **     SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase;
    80     80   **
    81     81   ** The nSubquery parameter specifies how many levels of subquery the
    82         -** alias is removed from the original expression.  The usually value is
           82  +** alias is removed from the original expression.  The usual value is
    83     83   ** zero but it might be more if the alias is contained within a subquery
    84     84   ** of the original expression.  The Expr.op2 field of TK_AGG_FUNCTION
    85     85   ** structures must be increased by the nSubquery amount.
    86     86   */
    87     87   static void resolveAlias(
    88     88     Parse *pParse,         /* Parsing context */
    89     89     ExprList *pEList,      /* A result set */
................................................................................
    95     95     Expr *pOrig;           /* The iCol-th column of the result set */
    96     96     Expr *pDup;            /* Copy of pOrig */
    97     97     sqlite3 *db;           /* The database connection */
    98     98   
    99     99     assert( iCol>=0 && iCol<pEList->nExpr );
   100    100     pOrig = pEList->a[iCol].pExpr;
   101    101     assert( pOrig!=0 );
   102         -  assert( pOrig->flags & EP_Resolved );
          102  +  assert( (pOrig->flags & EP_Resolved)!=0 || zType[0]==0 );
   103    103     db = pParse->db;
   104    104     pDup = sqlite3ExprDup(db, pOrig, 0);
   105    105     if( pDup==0 ) return;
   106    106     if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){
   107    107       incrAggFunctionDepth(pDup, nSubquery);
   108    108       pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
   109    109       if( pDup==0 ) return;

Changes to test/fts4check.test.

   174    174     db close
   175    175     sqlite3 db test.db
   176    176     catchsql {
   177    177       INSERT INTO t4(t4) VALUES('integrity-check');
   178    178     }
   179    179   } {1 {database disk image is malformed}}
   180    180   reset_db
          181  +
          182  +#--------------------------------------------------------------------------
          183  +# Test case 5.*
          184  +#
          185  +# Test that the integrity-check works if there is uncommitted data.
          186  +#
          187  +do_execsql_test 5.0 {
          188  +  BEGIN;
          189  +  CREATE VIRTUAL TABLE t5 USING fts4(a, prefix="1,2,3");
          190  +  INSERT INTO t5 VALUES('And down by Kosiosko, where the reed-banks sweep');
          191  +  INSERT INTO t5 VALUES('and sway, and the rolling plains are wide, the');
          192  +  INSERT INTO t5 VALUES('man from snowy river is a household name today,');
          193  +  INSERT INTO t5 VALUES('and the stockmen tell the story of his ride');
          194  +}
          195  +
          196  +do_execsql_test 5.1 {
          197  +  INSERT INTO t5(t5) VALUES('integrity-check');
          198  +} {}
          199  +
          200  +do_catchsql_test 5.2 {
          201  +  INSERT INTO t5_content VALUES(5, 'his hardy mountain pony');
          202  +  INSERT INTO t5(t5) VALUES('integrity-check');
          203  +} {1 {database disk image is malformed}}
          204  +
          205  +do_execsql_test 5.3 ROLLBACK
          206  +
          207  +do_execsql_test 5.4 {
          208  +  CREATE VIRTUAL TABLE t5 USING fts4(a, prefix="1,2,3");
          209  +  INSERT INTO t5(t5) VALUES('integrity-check');
          210  +} {}
   181    211   
   182    212   finish_test
   183    213   

Added test/fuzzdata1.txt.

cannot compute difference between binary files

Changes to test/releasetest.tcl.

    14     14       --config   CONFIGNAME              (Run only CONFIGNAME)
    15     15       --quick                            (Run "veryquick.test" only)
    16     16       --veryquick                        (Run "make smoketest" only)
    17     17       --msvc                             (Use MSVC as the compiler)
    18     18       --buildonly                        (Just build testfixture - do not run)
    19     19       --dryrun                           (Print what would have happened)
    20     20       --info                             (Show diagnostic info)
           21  +    --with-tcl=DIR                     (Use TCL build at DIR)
    21     22   
    22     23   The default value for --srcdir is the parent of the directory holding
    23     24   this script.
    24     25   
    25     26   The script determines the default value for --platform using the
    26     27   $tcl_platform(os) and $tcl_platform(machine) variables.  Supported
    27     28   platforms are "Linux-x86", "Linux-x86_64", "Darwin-i386",
................................................................................
   195    196     # different names for them all so that they results appear in separate
   196    197     # subdirectories.
   197    198     #
   198    199     Fail0 {-O0}
   199    200     Fail2 {-O0}
   200    201     Fail3 {-O0}
   201    202     Fail4 {-O0}
          203  +  FuzzFail1 {-O0}
          204  +  FuzzFail2 {-O0}
   202    205   }]
   203    206   
   204    207   array set ::Platforms [strip_comments {
   205    208     Linux-x86_64 {
   206    209       "Check-Symbols"           checksymbols
   207    210       "Debug-One"               "mptest test"
   208    211       "Have-Not"                test
................................................................................
   251    254     #
   252    255     Failure-Detection {
   253    256       Fail0     "TEST_FAILURE=0 test"
   254    257       Sanitize  "TEST_FAILURE=1 test"
   255    258       Fail2     "TEST_FAILURE=2 valgrindtest"
   256    259       Fail3     "TEST_FAILURE=3 valgrindtest"
   257    260       Fail4     "TEST_FAILURE=4 test"
          261  +    FuzzFail1 "TEST_FAILURE=5 test"
          262  +    FuzzFail2 "TEST_FAILURE=5 valgrindtest"
   258    263     }
   259    264   }]
   260    265   
   261    266   
   262    267   # End of configuration section.
   263    268   #########################################################################
   264    269   #########################################################################
................................................................................
   347    352     # OPTS Makefile variable. Variable $cflags holds the value for
   348    353     # CFLAGS. The makefile will pass OPTS to both gcc and lemon, but
   349    354     # CFLAGS is only passed to gcc.
   350    355     #
   351    356     set cflags [expr {$::MSVC ? "-Zi" : "-g"}]
   352    357     set opts ""
   353    358     set title ${name}($testtarget)
   354         -  set configOpts ""
          359  +  set configOpts $::WITHTCL
   355    360   
   356    361     regsub -all {#[^\n]*\n} $config \n config
   357    362     foreach arg $config {
   358    363       if {[regexp {^-[UD]} $arg]} {
   359    364         lappend opts $arg
   360    365       } elseif {[regexp {^[A-Z]+=} $arg]} {
   361    366         lappend testtarget $arg
................................................................................
   478    483     set ::SRCDIR    [file normalize [file dirname [file dirname $::argv0]]]
   479    484     set ::QUICK     0
   480    485     set ::MSVC      0
   481    486     set ::BUILDONLY 0
   482    487     set ::DRYRUN    0
   483    488     set ::EXEC      exec
   484    489     set ::TRACE     0
          490  +  set ::WITHTCL   {}
   485    491     set config {}
   486    492     set platform $::tcl_platform(os)-$::tcl_platform(machine)
   487    493   
   488    494     for {set i 0} {$i < [llength $argv]} {incr i} {
   489    495       set x [lindex $argv $i]
   490    496       if {[regexp {^--[a-z]} $x]} {set x [string range $x 1 end]}
   491    497       switch -glob -- $x {
................................................................................
   551    557         -g {
   552    558           if {$::MSVC} {
   553    559             lappend ::EXTRACONFIG -Zi
   554    560           } else {
   555    561             lappend ::EXTRACONFIG [lindex $argv $i]
   556    562           }
   557    563         }
          564  +
          565  +      -with-tcl=* {
          566  +        set ::WITHTCL -$x
          567  +      }
   558    568   
   559    569         -D* -
   560    570         -O* -
   561    571         -enable-* -
   562    572         -disable-* -
   563    573         *=* {
   564    574           lappend ::EXTRACONFIG [lindex $argv $i]

Changes to test/resolver01.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   #
    12     12   # This file tests features of the name resolver (the component that
    13     13   # figures out what identifiers in the SQL statement refer to) that
    14         -# were fixed by ticket [2500cdb9be]
           14  +# were fixed by ticket [2500cdb9be].
    15     15   #
    16     16   # See also tickets [1c69be2daf] and [f617ea3125] from 2013-08-14.
           17  +#
           18  +# Also a fuzzer-discovered problem on 2015-04-23.
    17     19   #
    18     20   
    19     21   set testdir [file dirname $argv0]
    20     22   source $testdir/tester.tcl
    21     23   
    22     24   # "ORDER BY y" binds to the output result-set column named "y"
    23     25   # if available.  If no output column is named "y", then try to
................................................................................
   197    199     INSERT INTO t63 VALUES ('abc');
   198    200     SELECT count(),
   199    201          NULLIF(name,'abc') AS name
   200    202       FROM t63
   201    203      GROUP BY lower(name);
   202    204   } {1 {} 1 {}}
   203    205   
          206  +do_execsql_test resolver01-7.1 {
          207  +  SELECT 2 AS x WHERE (SELECT x AS y WHERE 3>y);
          208  +} {2}
          209  +do_execsql_test resolver01-7.2 {
          210  +  SELECT 2 AS x WHERE (SELECT x AS y WHERE 1>y);
          211  +} {}
   204    212   
   205    213   
   206    214   
   207    215   
   208    216   finish_test

Changes to test/trace2.test.

   139    139       "-- SELECT level, idx, end_block FROM 'main'.'x1_segdir' WHERE level BETWEEN ? AND ? ORDER BY level DESC, idx ASC"
   140    140     }
   141    141   
   142    142     do_trace_test 2.3 {
   143    143       INSERT INTO x1(x1) VALUES('optimize');
   144    144     } {
   145    145       "INSERT INTO x1(x1) VALUES('optimize');"
   146         -    "-- SELECT DISTINCT level / (1024 * ?) FROM 'main'.'x1_segdir'"
          146  +    "-- SELECT ? UNION SELECT level / (1024 * ?) FROM 'main'.'x1_segdir'"
   147    147       "-- SELECT idx, start_block, leaves_end_block, end_block, root FROM 'main'.'x1_segdir' WHERE level BETWEEN ? AND ?ORDER BY level DESC, idx ASC"
   148    148       "-- SELECT max(level) FROM 'main'.'x1_segdir' WHERE level BETWEEN ? AND ?"
   149    149       "-- SELECT coalesce((SELECT max(blockid) FROM 'main'.'x1_segments') + 1, 1)"
   150    150       "-- DELETE FROM 'main'.'x1_segdir' WHERE level BETWEEN ? AND ?"
   151    151       "-- REPLACE INTO 'main'.'x1_segdir' VALUES(?,?,?,?,?,?)"
   152    152     }
   153    153   }
   154    154   
   155    155   finish_test

Changes to tool/fuzzershell.c.

    35     35   ** 2015-04-20: The input text can be divided into separate SQL chunks using
    36     36   ** lines of the form:
    37     37   **
    38     38   **       |****<...>****|
    39     39   **
    40     40   ** where the "..." is arbitrary text, except the "|" should really be "/".
    41     41   ** ("|" is used here to avoid compiler warnings about nested comments.)
    42         -** Each such SQL comment is printed as it is encountered.  A separate 
    43         -** in-memory SQLite database is created to run each chunk of SQL.  This
    44         -** feature allows the "queue" of AFL to be captured into a single big
           42  +** A separate in-memory SQLite database is created to run each chunk of SQL.
           43  +** This feature allows the "queue" of AFL to be captured into a single big
    45     44   ** file using a command like this:
    46     45   **
    47     46   **    (for i in id:*; do echo '|****<'$i'>****|'; cat $i; done) >~/all-queue.txt
    48     47   **
    49     48   ** (Once again, change the "|" to "/") Then all elements of the AFL queue
    50     49   ** can be run in a single go (for regression testing, for example) by typing:
    51     50   **
    52         -**    fuzzershell -f ~/all-queue.txt >out.txt
           51  +**    fuzzershell -f ~/all-queue.txt
    53     52   **
    54     53   ** After running each chunk of SQL, the database connection is closed.  The
    55     54   ** program aborts if the close fails or if there is any unfreed memory after
    56     55   ** the close.
           56  +**
           57  +** New cases can be appended to all-queue.txt at any time.  If redundant cases
           58  +** are added, that can be eliminated by running:
           59  +**
           60  +**    fuzzershell -f ~/all-queue.txt --unique-cases ~/unique-cases.txt
           61  +**
    57     62   */
    58     63   #include <stdio.h>
    59     64   #include <stdlib.h>
    60     65   #include <string.h>
    61     66   #include <stdarg.h>
    62     67   #include <ctype.h>
    63     68   #include "sqlite3.h"
................................................................................
   134    139         printf("[%s]\n", argv[i]);
   135    140       }else{
   136    141         printf("NULL\n");
   137    142       }
   138    143     }
   139    144     return 0;
   140    145   }
          146  +static int execNoop(void *NotUsed, int argc, char **argv, char **colv){
          147  +  return 0;
          148  +}
   141    149   
          150  +#ifndef SQLITE_OMIT_TRACE
   142    151   /*
   143    152   ** This callback is invoked by sqlite3_trace() as each SQL statement
   144    153   ** starts.
   145    154   */
   146    155   static void traceCallback(void *NotUsed, const char *zMsg){
   147    156     printf("TRACE: %s\n", zMsg);
   148    157   }
          158  +#endif
   149    159   
   150    160   /***************************************************************************
   151    161   ** eval() implementation copied from ../ext/misc/eval.c
   152    162   */
   153    163   /*
   154    164   ** Structure used to accumulate the output
   155    165   */
................................................................................
   239    249   ** Print sketchy documentation for this utility program
   240    250   */
   241    251   static void showHelp(void){
   242    252     printf("Usage: %s [options]\n", g.zArgv0);
   243    253     printf(
   244    254   "Read SQL text from standard input and evaluate it.\n"
   245    255   "Options:\n"
   246         -"  --autovacuum        Enable AUTOVACUUM mode\n"
   247         -"  -f FILE             Read SQL text from FILE instead of standard input\n"
   248         -"  --heap SZ MIN       Memory allocator uses SZ bytes & min allocation MIN\n"
   249         -"  --help              Show this help text\n"    
   250         -"  --initdb DBFILE     Initialize the in-memory database using template DBFILE\n"
   251         -"  --lookaside N SZ    Configure lookaside for N slots of SZ bytes each\n"
   252         -"  --pagesize N        Set the page size to N\n"
   253         -"  --pcache N SZ       Configure N pages of pagecache each of size SZ bytes\n"
   254         -"  --scratch N SZ      Configure scratch memory for N slots of SZ bytes each\n"
   255         -"  --utf16be           Set text encoding to UTF-16BE\n"
   256         -"  --utf16le           Set text encoding to UTF-16LE\n"
          256  +"  --autovacuum          Enable AUTOVACUUM mode\n"
          257  +"  -f FILE               Read SQL text from FILE instead of standard input\n"
          258  +"  --heap SZ MIN         Memory allocator uses SZ bytes & min allocation MIN\n"
          259  +"  --help                Show this help text\n"    
          260  +"  --initdb DBFILE       Initialize the in-memory database using template DBFILE\n"
          261  +"  --lookaside N SZ      Configure lookaside for N slots of SZ bytes each\n"
          262  +"  --pagesize N          Set the page size to N\n"
          263  +"  --pcache N SZ         Configure N pages of pagecache each of size SZ bytes\n"
          264  +"  -q                    Reduced output\n"
          265  +"  --quiet               Reduced output\n"
          266  +"  --scratch N SZ        Configure scratch memory for N slots of SZ bytes each\n"
          267  +"  --unique-cases FILE   Write all unique test cases to FILE\n"
          268  +"  --utf16be             Set text encoding to UTF-16BE\n"
          269  +"  --utf16le             Set text encoding to UTF-16LE\n"
          270  +"  -v                    Increased output\n"
          271  +"  --verbose             Increased output\n"
   257    272     );
   258    273   }
   259    274   
   260    275   /*
   261    276   ** Return the value of a hexadecimal digit.  Return -1 if the input
   262    277   ** is not a hex digit.
   263    278   */
................................................................................
   347    362     void *pLook = 0;              /* Allocated lookaside space */
   348    363     void *pPCache = 0;            /* Allocated storage for pcache */
   349    364     void *pScratch = 0;           /* Allocated storage for scratch */
   350    365     int doAutovac = 0;            /* True for --autovacuum */
   351    366     char *zSql;                   /* SQL to run */
   352    367     char *zToFree = 0;            /* Call sqlite3_free() on this afte running zSql */
   353    368     int iMode = FZMODE_Generic;   /* Operating mode */
          369  +  const char *zCkGlob = 0;      /* Inputs must match this glob */
          370  +  int verboseFlag = 0;          /* --verbose or -v flag */
          371  +  int quietFlag = 0;            /* --quiet or -q flag */
          372  +  int nTest = 0;                /* Number of test cases run */
          373  +  int multiTest = 0;            /* True if there will be multiple test cases */
          374  +  int lastPct = -1;             /* Previous percentage done output */
          375  +  sqlite3 *dataDb = 0;          /* Database holding compacted input data */
          376  +  sqlite3_stmt *pStmt = 0;      /* Statement to insert testcase into dataDb */
          377  +  const char *zDataOut = 0;     /* Write compacted data to this output file */
          378  +  int nHeader = 0;              /* Bytes of header comment text on input file */
   354    379   
   355    380   
   356    381     g.zArgv0 = argv[0];
   357    382     for(i=1; i<argc; i++){
   358    383       const char *z = argv[i];
   359    384       if( z[0]=='-' ){
   360    385         z++;
................................................................................
   388    413           i += 2;
   389    414         }else
   390    415         if( strcmp(z,"mode")==0 ){
   391    416           if( i>=argc-1 ) abendError("missing argument on %s", argv[i]);
   392    417           z = argv[++i];
   393    418           if( strcmp(z,"generic")==0 ){
   394    419             iMode = FZMODE_Printf;
          420  +          zCkGlob = 0;
   395    421           }else if( strcmp(z, "glob")==0 ){
   396    422             iMode = FZMODE_Glob;
          423  +          zCkGlob = "'*','*'";
   397    424           }else if( strcmp(z, "printf")==0 ){
   398    425             iMode = FZMODE_Printf;
          426  +          zCkGlob = "'*',*";
   399    427           }else if( strcmp(z, "strftime")==0 ){
   400    428             iMode = FZMODE_Strftime;
          429  +          zCkGlob = "'*',*";
   401    430           }else{
   402    431             abendError("unknown --mode: %s", z);
   403    432           }
   404    433         }else
   405    434         if( strcmp(z,"pagesize")==0 ){
   406    435           if( i>=argc-1 ) abendError("missing argument on %s", argv[i]);
   407    436           pageSize = integerValue(argv[++i]);
   408    437         }else
   409    438         if( strcmp(z,"pcache")==0 ){
   410    439           if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
   411    440           nPCache = integerValue(argv[i+1]);
   412    441           szPCache = integerValue(argv[i+2]);
   413    442           i += 2;
          443  +      }else
          444  +      if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
          445  +        quietFlag = 1;
          446  +        verboseFlag = 0;
   414    447         }else
   415    448         if( strcmp(z,"scratch")==0 ){
   416    449           if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
   417    450           nScratch = integerValue(argv[i+1]);
   418    451           szScratch = integerValue(argv[i+2]);
   419    452           i += 2;
          453  +      }else
          454  +      if( strcmp(z, "unique-cases")==0 ){
          455  +        if( i>=argc-1 ) abendError("missing arguments on %s", argv[i]);
          456  +        if( zDataOut ) abendError("only one --minimize allowed");
          457  +        zDataOut = argv[++i];
   420    458         }else
   421    459         if( strcmp(z,"utf16le")==0 ){
   422    460           zEncoding = "utf16le";
   423    461         }else
   424    462         if( strcmp(z,"utf16be")==0 ){
   425    463           zEncoding = "utf16be";
          464  +      }else
          465  +      if( strcmp(z,"verbose")==0 || strcmp(z,"v")==0 ){
          466  +        quietFlag = 0;
          467  +        verboseFlag = 1;
   426    468         }else
   427    469         {
   428    470           abendError("unknown option: %s", argv[i]);
   429    471         }
   430    472       }else{
   431    473         abendError("unknown argument: %s", argv[i]);
   432    474       }
   433    475     }
   434         -  sqlite3_config(SQLITE_CONFIG_LOG, shellLog, 0);
          476  +  if( verboseFlag ) sqlite3_config(SQLITE_CONFIG_LOG, shellLog, 0);
   435    477     if( nHeap>0 ){
   436    478       pHeap = malloc( nHeap );
   437    479       if( pHeap==0 ) fatalError("cannot allocate %d-byte heap\n", nHeap);
   438    480       rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, mnHeap);
   439    481       if( rc ) abendError("heap configuration failed: %d\n", rc);
   440    482     }
   441    483     if( nLook>0 ){
................................................................................
   464    506       zIn = realloc(zIn, nAlloc);
   465    507       if( zIn==0 ) fatalError("out of memory");
   466    508       got = fread(zIn+nIn, 1, nAlloc-nIn-1, in); 
   467    509       nIn += (int)got;
   468    510       zIn[nIn] = 0;
   469    511       if( got==0 ) break;
   470    512     }
          513  +  if( in!=stdin ) fclose(in);
          514  +  if( zDataOut ){
          515  +    rc = sqlite3_open(":memory:", &dataDb);
          516  +    if( rc ) abendError("cannot open :memory: database");
          517  +    rc = sqlite3_exec(dataDb,
          518  +          "CREATE TABLE testcase(sql BLOB PRIMARY KEY) WITHOUT ROWID;",0,0,0);
          519  +    if( rc ) abendError("%s", sqlite3_errmsg(dataDb));
          520  +    rc = sqlite3_prepare_v2(dataDb, "INSERT OR IGNORE INTO testcase(sql)VALUES(?1)",
          521  +                            -1, &pStmt, 0);
          522  +    if( rc ) abendError("%s", sqlite3_errmsg(dataDb));
          523  +  }
   471    524     if( zInitDb ){
   472    525       rc = sqlite3_open_v2(zInitDb, &dbInit, SQLITE_OPEN_READONLY, 0);
   473    526       if( rc!=SQLITE_OK ){
   474    527         abendError("unable to open initialization database \"%s\"", zInitDb);
   475    528       }
   476    529     }
   477         -  for(i=0; i<nIn; i=iNext){
          530  +  for(i=0; i<nIn; i=iNext+1){   /* Skip initial lines beginning with '#' */
          531  +    if( zIn[i]!='#' ) break;
          532  +    for(iNext=i+1; iNext<nIn && zIn[iNext]!='\n'; iNext++){}
          533  +  }
          534  +  nHeader = i;
          535  +  for(nTest=0; i<nIn; i=iNext, nTest++){
   478    536       char cSaved;
   479    537       if( strncmp(&zIn[i], "/****<",6)==0 ){
   480    538         char *z = strstr(&zIn[i], ">****/");
   481    539         if( z ){
   482    540           z += 6;
   483         -        printf("%.*s\n", (int)(z-&zIn[i]), &zIn[i]);
          541  +        if( verboseFlag ) printf("%.*s\n", (int)(z-&zIn[i]), &zIn[i]);
   484    542           i += (int)(z-&zIn[i]);
          543  +        multiTest = 1;
   485    544         }
   486    545       }
   487    546       for(iNext=i; iNext<nIn && strncmp(&zIn[iNext],"/****<",6)!=0; iNext++){}
   488         -    
          547  +    if( zDataOut ){
          548  +      sqlite3_bind_blob(pStmt, 1, &zIn[i], iNext-i, SQLITE_STATIC);
          549  +      rc = sqlite3_step(pStmt);
          550  +      if( rc!=SQLITE_DONE ) abendError("%s", sqlite3_errmsg(dataDb));
          551  +      sqlite3_reset(pStmt);
          552  +      continue;
          553  +    }
          554  +    cSaved = zIn[iNext];
          555  +    zIn[iNext] = 0;
          556  +    if( zCkGlob && sqlite3_strglob(zCkGlob,&zIn[i])!=0 ){
          557  +      zIn[iNext] = cSaved;
          558  +      continue;
          559  +    }
   489    560       rc = sqlite3_open_v2(
   490    561         "main.db", &db,
   491    562         SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY,
   492    563         0);
   493    564       if( rc!=SQLITE_OK ){
   494    565         abendError("Unable to open the in-memory database");
   495    566       }
................................................................................
   503    574         rc = sqlite3_backup_step(pBackup, -1);
   504    575         if( rc!=SQLITE_DONE ){
   505    576           abendError("attempt to initialize the in-memory database failed (rc=%d)",
   506    577                      rc);
   507    578         }
   508    579         sqlite3_backup_finish(pBackup);
   509    580       }
   510         -    sqlite3_trace(db, traceCallback, 0);
          581  +#ifndef SQLITE_OMIT_TRACE
          582  +    if( verboseFlag ) sqlite3_trace(db, traceCallback, 0);
          583  +#endif
   511    584       sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
   512    585       sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
   513    586       sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 1000000);
   514    587       if( zEncoding ) sqlexec(db, "PRAGMA encoding=%s", zEncoding);
   515    588       if( pageSize ) sqlexec(db, "PRAGMA pagesize=%d", pageSize);
   516    589       if( doAutovac ) sqlexec(db, "PRAGMA auto_vacuum=FULL");
   517         -    cSaved = zIn[iNext];
   518         -    zIn[iNext] = 0;
   519         -    printf("INPUT (offset: %d, size: %d): [%s]\n",
   520         -            i, (int)strlen(&zIn[i]), &zIn[i]);
   521    590       zSql = &zIn[i];
          591  +    if( verboseFlag ){
          592  +      printf("INPUT (offset: %d, size: %d): [%s]\n",
          593  +              i, (int)strlen(&zIn[i]), &zIn[i]);
          594  +    }else if( multiTest && !quietFlag ){
          595  +      int pct = 10*iNext/nIn;
          596  +      if( pct!=lastPct ){
          597  +        if( lastPct<0 ) printf("fuzz test:");
          598  +        printf(" %d%%", pct*10);
          599  +        fflush(stdout);
          600  +        lastPct = pct;
          601  +      }
          602  +    }
   522    603       switch( iMode ){
   523    604         case FZMODE_Glob:
   524    605           zSql = zToFree = sqlite3_mprintf("SELECT glob(%s);", zSql);
   525    606           break;
   526    607         case FZMODE_Printf:
   527    608           zSql = zToFree = sqlite3_mprintf("SELECT printf(%s);", zSql);
   528    609           break;
   529    610         case FZMODE_Strftime:
   530    611           zSql = zToFree = sqlite3_mprintf("SELECT strftime(%s);", zSql);
   531    612           break;
   532    613       }
   533         -    rc = sqlite3_exec(db, zSql, execCallback, 0, &zErrMsg);
          614  +    zErrMsg = 0;
          615  +    rc = sqlite3_exec(db, zSql, verboseFlag ? execCallback : execNoop, 0, &zErrMsg);
   534    616       if( zToFree ){
   535    617         sqlite3_free(zToFree);
   536    618         zToFree = 0;
   537    619       }
   538    620       zIn[iNext] = cSaved;
   539         -
   540         -    printf("RESULT-CODE: %d\n", rc);
   541         -    if( zErrMsg ){
   542         -      printf("ERROR-MSG: [%s]\n", zErrMsg);
   543         -      sqlite3_free(zErrMsg);
          621  +    if( verboseFlag ){
          622  +      printf("RESULT-CODE: %d\n", rc);
          623  +      if( zErrMsg ){
          624  +        printf("ERROR-MSG: [%s]\n", zErrMsg);
          625  +      }
   544    626       }
          627  +    sqlite3_free(zErrMsg);
   545    628       rc = sqlite3_close(db);
   546    629       if( rc ){
   547    630         abendError("sqlite3_close() failed with rc=%d", rc);
   548    631       }
   549    632       if( sqlite3_memory_used()>0 ){
   550    633         abendError("memory in use after close: %lld bytes", sqlite3_memory_used());
   551    634       }
          635  +    if( nTest==1 ){
          636  +      /* Simulate an error if the TEST_FAILURE environment variable is "5" */
          637  +      char *zFailCode = getenv("TEST_FAILURE");
          638  +      if( zFailCode ){
          639  +        if( zFailCode[0]=='5' && zFailCode[1]==0 ){
          640  +          abendError("simulated failure");
          641  +        }else if( zFailCode[0]!=0 ){
          642  +          /* If TEST_FAILURE is something other than 5, just exit the test
          643  +          ** early */
          644  +          printf("\nExit early due to TEST_FAILURE being set");
          645  +          break;
          646  +        }
          647  +      }
          648  +    }
          649  +  }
          650  +  if( !verboseFlag && multiTest && !quietFlag ) printf("\n");
          651  +  if( nTest>1 && !quietFlag ){
          652  +    printf("%d fuzz tests with no errors\nSQLite %s %s\n",
          653  +           nTest, sqlite3_libversion(), sqlite3_sourceid());
          654  +  }
          655  +  if( zDataOut ){
          656  +    int n = 0;
          657  +    FILE *out = fopen(zDataOut, "wb");
          658  +    if( out==0 ) abendError("cannot open %s for writing", zDataOut);
          659  +    if( nHeader>0 ) fwrite(zIn, nHeader, 1, out);
          660  +    sqlite3_finalize(pStmt);
          661  +    rc = sqlite3_prepare_v2(dataDb, "SELECT sql FROM testcase", -1, &pStmt, 0);
          662  +    if( rc ) abendError("%s", sqlite3_errmsg(dataDb));
          663  +    while( sqlite3_step(pStmt)==SQLITE_ROW ){
          664  +      fprintf(out,"/****<%d>****/", ++n);
          665  +      fwrite(sqlite3_column_blob(pStmt,0),sqlite3_column_bytes(pStmt,0),1,out);
          666  +    }
          667  +    fclose(out);
          668  +    sqlite3_finalize(pStmt);
          669  +    sqlite3_close(dataDb);
   552    670     }
   553    671     free(zIn);
   554    672     free(pHeap);
   555    673     free(pLook);
   556    674     free(pScratch);
   557    675     free(pPCache);
   558    676     return 0;
   559    677   }