/ Check-in [1754faef]
Login

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

Overview
Comment:Merge all changes from trunk prior to the read-only WAL enhancement.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | apple-osx
Files: files | file ages | folders
SHA3-256:1754faefccba39900a89bad3d6ba6670a504a1f229621ce3a16eca03ae062e36
User & Date: drh 2017-11-14 20:00:51
Context
2017-11-14
20:36
Merge the patch that enables reading a read-only WAL-mode database, without any special query parameters, as long as the -shm and -wal files are on disk. check-in: 8c2a769c user: drh tags: apple-osx
20:00
Merge all changes from trunk prior to the read-only WAL enhancement. check-in: 1754faef user: drh tags: apple-osx
17:06
Fix the SQLITE_ENABLE_UPDATE_DELETE_LIMIT functionality so that it works with views and WITHOUT ROWID tables. check-in: dae4a97a user: dan tags: trunk
2017-10-24
19:12
Merge all enhancements and fixes from the 3.21.0 release. check-in: 13be3a44 user: drh tags: apple-osx
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Makefile.in.

   685    685   	$(TCLSH_CMD) $(TOP)/tool/vdbe-compress.tcl $(OPTS) <tsrc/vdbe.c >vdbe.new
   686    686   	mv vdbe.new tsrc/vdbe.c
   687    687   	cp fts5.c fts5.h tsrc
   688    688   	touch .target_source
   689    689   
   690    690   sqlite3.c:	.target_source $(TOP)/tool/mksqlite3c.tcl
   691    691   	$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl
   692         -	cp tsrc/shell.c tsrc/sqlite3ext.h .
          692  +	cp tsrc/sqlite3ext.h .
   693    693   	cp $(TOP)/ext/session/sqlite3session.h .
   694    694   
   695    695   sqlite3ext.h:	.target_source
   696    696   	cp tsrc/sqlite3ext.h .
   697    697   
   698    698   tclsqlite3.c:	sqlite3.c
   699    699   	echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c
................................................................................
  1196   1196   
  1197   1197   sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in
  1198   1198   	$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c
  1199   1199   
  1200   1200   sqlite3_analyzer$(TEXE): sqlite3_analyzer.c
  1201   1201   	$(LTLINK) sqlite3_analyzer.c -o $@ $(LIBTCL) $(TLIBS)
  1202   1202   
         1203  +CHECKER_DEPS =\
         1204  +  $(TOP)/tool/mkccode.tcl \
         1205  +  sqlite3.c \
         1206  +  $(TOP)/src/tclsqlite.c \
         1207  +  $(TOP)/ext/repair/sqlite3_checker.tcl \
         1208  +  $(TOP)/ext/repair/checkindex.c \
         1209  +  $(TOP)/ext/repair/checkfreelist.c \
         1210  +  $(TOP)/ext/misc/btreeinfo.c \
         1211  +  $(TOP)/ext/repair/sqlite3_checker.c.in
         1212  +
         1213  +sqlite3_checker.c:	$(CHECKER_DEPS)
         1214  +	$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/ext/repair/sqlite3_checker.c.in >$@
         1215  +
         1216  +sqlite3_checker$(TEXE):	sqlite3_checker.c
         1217  +	$(LTLINK) sqlite3_checker.c -o $@ $(LIBTCL) $(TLIBS)
         1218  +
  1203   1219   dbdump$(TEXE): $(TOP)/ext/misc/dbdump.c sqlite3.lo
  1204   1220   	$(LTLINK) -DDBDUMP_STANDALONE -o $@ \
  1205   1221              $(TOP)/ext/misc/dbdump.c sqlite3.lo $(TLIBS)
  1206   1222   
  1207   1223   showdb$(TEXE):	$(TOP)/tool/showdb.c sqlite3.lo
  1208   1224   	$(LTLINK) -o $@ $(TOP)/tool/showdb.c sqlite3.lo $(TLIBS)
  1209   1225   
................................................................................
  1212   1228   
  1213   1229   showjournal$(TEXE):	$(TOP)/tool/showjournal.c sqlite3.lo
  1214   1230   	$(LTLINK) -o $@ $(TOP)/tool/showjournal.c sqlite3.lo $(TLIBS)
  1215   1231   
  1216   1232   showwal$(TEXE):	$(TOP)/tool/showwal.c sqlite3.lo
  1217   1233   	$(LTLINK) -o $@ $(TOP)/tool/showwal.c sqlite3.lo $(TLIBS)
  1218   1234   
         1235  +showshm$(TEXE):	$(TOP)/tool/showshm.c
         1236  +	$(LTLINK) -o $@ $(TOP)/tool/showshm.c
         1237  +
  1219   1238   changeset$(TEXE):	$(TOP)/ext/session/changeset.c sqlite3.lo
  1220   1239   	$(LTLINK) -o $@ $(TOP)/ext/session/changeset.c sqlite3.lo $(TLIBS)
  1221   1240   
  1222   1241   rollback-test$(TEXE):	$(TOP)/tool/rollback-test.c sqlite3.lo
  1223   1242   	$(LTLINK) -o $@ $(TOP)/tool/rollback-test.c sqlite3.lo $(TLIBS)
  1224   1243   
  1225   1244   LogEst$(TEXE):	$(TOP)/tool/logest.c sqlite3.h

Changes to Makefile.msc.

  1487   1487   
  1488   1488   # executables needed for testing
  1489   1489   #
  1490   1490   TESTPROGS = \
  1491   1491     testfixture.exe \
  1492   1492     $(SQLITE3EXE) \
  1493   1493     sqlite3_analyzer.exe \
         1494  +  sqlite3_checker.exe \
  1494   1495     sqldiff.exe \
  1495   1496     dbhash.exe
  1496   1497   
  1497   1498   # Databases containing fuzzer test cases
  1498   1499   #
  1499   1500   FUZZDATA = \
  1500   1501     $(TOP)\test\fuzzdata1.db \
................................................................................
  1648   1649   	del /Q tsrc\sqlite.h.in tsrc\parse.y 2>NUL
  1649   1650   	$(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl $(OPTS) < tsrc\vdbe.c > vdbe.new
  1650   1651   	move vdbe.new tsrc\vdbe.c
  1651   1652   	echo > .target_source
  1652   1653   
  1653   1654   sqlite3.c:	.target_source sqlite3ext.h $(MKSQLITE3C_TOOL)
  1654   1655   	$(TCLSH_CMD) $(MKSQLITE3C_TOOL) $(MKSQLITE3C_ARGS)
  1655         -	copy tsrc\shell.c .
  1656   1656   	copy $(TOP)\ext\session\sqlite3session.h .
  1657   1657   
  1658   1658   sqlite3-all.c:	sqlite3.c $(TOP)\tool\split-sqlite3c.tcl
  1659   1659   	$(TCLSH_CMD) $(TOP)\tool\split-sqlite3c.tcl
  1660   1660   # <</mark>>
  1661   1661   
  1662   1662   # Rule to build the amalgamation
................................................................................
  2197   2197   sqlite3_analyzer.c:	$(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in $(SQLITE_TCL_DEP)
  2198   2198   	$(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in > $@
  2199   2199   
  2200   2200   sqlite3_analyzer.exe:	sqlite3_analyzer.c $(LIBRESOBJS)
  2201   2201   	$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_analyzer.c \
  2202   2202   		/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
  2203   2203   
         2204  +CHECKER_DEPS =\
         2205  +  $(TOP)/tool/mkccode.tcl \
         2206  +  sqlite3.c \
         2207  +  $(TOP)/src/tclsqlite.c \
         2208  +  $(TOP)/ext/repair/sqlite3_checker.tcl \
         2209  +  $(TOP)/ext/repair/checkindex.c \
         2210  +  $(TOP)/ext/repair/checkfreelist.c \
         2211  +  $(TOP)/ext/misc/btreeinfo.c \
         2212  +  $(TOP)/ext/repair/sqlite3_checker.c.in
         2213  +
         2214  +sqlite3_checker.c:	$(CHECKER_DEPS)
         2215  +	$(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\ext\repair\sqlite3_checker.c.in > $@
         2216  +
         2217  +sqlite3_checker.exe:	sqlite3_checker.c $(LIBRESOBJS)
         2218  +	$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_checker.c \
         2219  +		/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
         2220  +
  2204   2221   dbdump.exe:	$(TOP)\ext\misc\dbdump.c $(SQLITE3C) $(SQLITE3H)
  2205   2222   	$(LTLINK) $(NO_WARN) -DDBDUMP_STANDALONE $(TOP)\ext\misc\dbdump.c $(SQLITE3C) \
  2206   2223   		/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS)
  2207   2224   
  2208   2225   testloadext.lo:	$(TOP)\src\test_loadext.c
  2209   2226   	$(LTCOMPILE) $(NO_WARN) -c $(TOP)\src\test_loadext.c
  2210   2227   
................................................................................
  2223   2240   	$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
  2224   2241   		$(TOP)\tool\showjournal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
  2225   2242   
  2226   2243   showwal.exe:	$(TOP)\tool\showwal.c $(SQLITE3C) $(SQLITE3H)
  2227   2244   	$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
  2228   2245   		$(TOP)\tool\showwal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
  2229   2246   
         2247  +showshm.exe:	$(TOP)\tool\showshm.c
         2248  +	$(LTLINK) $(NO_WARN)	$(TOP)\tool\showshm.c /link $(LDFLAGS) $(LTLINKOPTS)
         2249  +
  2230   2250   changeset.exe:	$(TOP)\ext\session\changeset.c $(SQLITE3C) $(SQLITE3H)
  2231   2251   	$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
  2232   2252   		-DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 \
  2233   2253   		$(TOP)\ext\session\changeset.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
  2234   2254   
  2235   2255   fts3view.exe:	$(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) $(SQLITE3H)
  2236   2256   	$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \

Changes to VERSION.

     1         -3.21.0
            1  +3.22.0

Changes to autoconf/Makefile.msc.

   970    970   
   971    971   
   972    972   # Rule to build the Win32 resources object file.
   973    973   #
   974    974   !IF $(USE_RC)!=0
   975    975   _HASHCHAR=^#
   976    976   !IF ![echo !IFNDEF VERSION > rcver.vc] && \
   977         -    ![for /F "delims=" %V in ('type "$(SQLITE3H)" ^| find "$(_HASHCHAR)define SQLITE_VERSION "') do (echo VERSION = ^^%V >> rcver.vc)] && \
          977  +    ![for /F "delims=" %V in ('type "$(SQLITE3H)" ^| "%SystemRoot%\System32\find.exe" "$(_HASHCHAR)define SQLITE_VERSION "') do (echo VERSION = ^^%V >> rcver.vc)] && \
   978    978       ![echo !ENDIF >> rcver.vc]
   979    979   !INCLUDE rcver.vc
   980    980   !ENDIF
   981    981   
   982    982   RESOURCE_VERSION = $(VERSION:^#=)
   983    983   RESOURCE_VERSION = $(RESOURCE_VERSION:define=)
   984    984   RESOURCE_VERSION = $(RESOURCE_VERSION:SQLITE_VERSION=)

Changes to autoconf/configure.ac.

     8      8   #   --enable-static-shell
     9      9   #   --enable-dynamic-extensions
    10     10   #
    11     11   
    12     12   AC_PREREQ(2.61)
    13     13   AC_INIT(sqlite, --SQLITE-VERSION--, http://www.sqlite.org)
    14     14   AC_CONFIG_SRCDIR([sqlite3.c])
           15  +AC_CONFIG_AUX_DIR([.])
    15     16   
    16     17   # Use automake.
    17     18   AM_INIT_AUTOMAKE([foreign])
    18     19   
    19     20   AC_SYS_LARGEFILE
    20     21   
    21     22   # Check for required programs.

Changes to configure.

     1      1   #! /bin/sh
     2      2   # Guess values for system-dependent variables and create Makefiles.
     3         -# Generated by GNU Autoconf 2.69 for sqlite 3.21.0.
            3  +# Generated by GNU Autoconf 2.69 for sqlite 3.22.0.
     4      4   #
     5      5   #
     6      6   # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
     7      7   #
     8      8   #
     9      9   # This configure script is free software; the Free Software Foundation
    10     10   # gives unlimited permission to copy, distribute and modify it.
................................................................................
   722    722   subdirs=
   723    723   MFLAGS=
   724    724   MAKEFLAGS=
   725    725   
   726    726   # Identity of this package.
   727    727   PACKAGE_NAME='sqlite'
   728    728   PACKAGE_TARNAME='sqlite'
   729         -PACKAGE_VERSION='3.21.0'
   730         -PACKAGE_STRING='sqlite 3.21.0'
          729  +PACKAGE_VERSION='3.22.0'
          730  +PACKAGE_STRING='sqlite 3.22.0'
   731    731   PACKAGE_BUGREPORT=''
   732    732   PACKAGE_URL=''
   733    733   
   734    734   # Factoring default headers for most tests.
   735    735   ac_includes_default="\
   736    736   #include <stdio.h>
   737    737   #ifdef HAVE_SYS_TYPES_H
................................................................................
  1460   1460   #
  1461   1461   # Report the --help message.
  1462   1462   #
  1463   1463   if test "$ac_init_help" = "long"; then
  1464   1464     # Omit some internal or obsolete options to make the list less imposing.
  1465   1465     # This message is too long to be a string in the A/UX 3.1 sh.
  1466   1466     cat <<_ACEOF
  1467         -\`configure' configures sqlite 3.21.0 to adapt to many kinds of systems.
         1467  +\`configure' configures sqlite 3.22.0 to adapt to many kinds of systems.
  1468   1468   
  1469   1469   Usage: $0 [OPTION]... [VAR=VALUE]...
  1470   1470   
  1471   1471   To assign environment variables (e.g., CC, CFLAGS...), specify them as
  1472   1472   VAR=VALUE.  See below for descriptions of some of the useful variables.
  1473   1473   
  1474   1474   Defaults for the options are specified in brackets.
................................................................................
  1525   1525     --build=BUILD     configure for building on BUILD [guessed]
  1526   1526     --host=HOST       cross-compile to build programs to run on HOST [BUILD]
  1527   1527   _ACEOF
  1528   1528   fi
  1529   1529   
  1530   1530   if test -n "$ac_init_help"; then
  1531   1531     case $ac_init_help in
  1532         -     short | recursive ) echo "Configuration of sqlite 3.21.0:";;
         1532  +     short | recursive ) echo "Configuration of sqlite 3.22.0:";;
  1533   1533      esac
  1534   1534     cat <<\_ACEOF
  1535   1535   
  1536   1536   Optional Features:
  1537   1537     --disable-option-checking  ignore unrecognized --enable/--with options
  1538   1538     --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
  1539   1539     --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
................................................................................
  1650   1650       cd "$ac_pwd" || { ac_status=$?; break; }
  1651   1651     done
  1652   1652   fi
  1653   1653   
  1654   1654   test -n "$ac_init_help" && exit $ac_status
  1655   1655   if $ac_init_version; then
  1656   1656     cat <<\_ACEOF
  1657         -sqlite configure 3.21.0
         1657  +sqlite configure 3.22.0
  1658   1658   generated by GNU Autoconf 2.69
  1659   1659   
  1660   1660   Copyright (C) 2012 Free Software Foundation, Inc.
  1661   1661   This configure script is free software; the Free Software Foundation
  1662   1662   gives unlimited permission to copy, distribute and modify it.
  1663   1663   _ACEOF
  1664   1664     exit
................................................................................
  2069   2069     eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
  2070   2070   
  2071   2071   } # ac_fn_c_check_header_mongrel
  2072   2072   cat >config.log <<_ACEOF
  2073   2073   This file contains any messages produced by compilers while
  2074   2074   running configure, to aid debugging if configure makes a mistake.
  2075   2075   
  2076         -It was created by sqlite $as_me 3.21.0, which was
         2076  +It was created by sqlite $as_me 3.22.0, which was
  2077   2077   generated by GNU Autoconf 2.69.  Invocation command line was
  2078   2078   
  2079   2079     $ $0 $@
  2080   2080   
  2081   2081   _ACEOF
  2082   2082   exec 5>>config.log
  2083   2083   {
................................................................................
 12163  12163   test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
 12164  12164   
 12165  12165   cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 12166  12166   # Save the log message, to keep $0 and so on meaningful, and to
 12167  12167   # report actual input values of CONFIG_FILES etc. instead of their
 12168  12168   # values after options handling.
 12169  12169   ac_log="
 12170         -This file was extended by sqlite $as_me 3.21.0, which was
        12170  +This file was extended by sqlite $as_me 3.22.0, which was
 12171  12171   generated by GNU Autoconf 2.69.  Invocation command line was
 12172  12172   
 12173  12173     CONFIG_FILES    = $CONFIG_FILES
 12174  12174     CONFIG_HEADERS  = $CONFIG_HEADERS
 12175  12175     CONFIG_LINKS    = $CONFIG_LINKS
 12176  12176     CONFIG_COMMANDS = $CONFIG_COMMANDS
 12177  12177     $ $0 $@
................................................................................
 12229  12229   
 12230  12230   Report bugs to the package provider."
 12231  12231   
 12232  12232   _ACEOF
 12233  12233   cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 12234  12234   ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 12235  12235   ac_cs_version="\\
 12236         -sqlite config.status 3.21.0
        12236  +sqlite config.status 3.22.0
 12237  12237   configured by $0, generated by GNU Autoconf 2.69,
 12238  12238     with options \\"\$ac_cs_config\\"
 12239  12239   
 12240  12240   Copyright (C) 2012 Free Software Foundation, Inc.
 12241  12241   This config.status script is free software; the Free Software Foundation
 12242  12242   gives unlimited permission to copy, distribute and modify it."
 12243  12243   

Changes to ext/lsm1/Makefile.

    39     39                $(LSMDIR)/lsm-test/lsmtest_main.c $(LSMDIR)/lsm-test/lsmtest_mem.c \
    40     40                $(LSMDIR)/lsm-test/lsmtest_tdb.c $(LSMDIR)/lsm-test/lsmtest_tdb3.c \
    41     41                $(LSMDIR)/lsm-test/lsmtest_util.c $(LSMDIR)/lsm-test/lsmtest_win32.c
    42     42   
    43     43   
    44     44   # all: lsm.so
    45     45   
    46         -LSMOPTS += -DLSM_MUTEX_PTHREADS=1 -I$(LSMDIR)
           46  +LSMOPTS += -DLSM_MUTEX_PTHREADS=1 -I$(LSMDIR) -DHAVE_ZLIB
    47     47   
    48     48   lsm.so:	$(LSMOBJ)
    49     49   	$(TCCX) -shared -o lsm.so $(LSMOBJ)
    50     50   
    51     51   %.o:	$(LSMDIR)/%.c $(LSMHDR) sqlite3.h
    52     52   	$(TCCX) $(LSMOPTS) -c $<
    53     53   	
    54     54   lsmtest$(EXE): $(LSMOBJ) $(LSMTESTSRC) $(LSMTESTHDR) sqlite3.o
    55     55   	# $(TCPPX) -c $(TOP)/lsm-test/lsmtest_tdb2.cc
    56         -	$(TCCX) $(LSMOPTS) $(LSMTESTSRC) $(LSMOBJ) sqlite3.o -o lsmtest$(EXE) $(THREADLIB)
           56  +	$(TCCX) $(LSMOPTS) $(LSMTESTSRC) $(LSMOBJ) sqlite3.o -o lsmtest$(EXE) $(THREADLIB) -lz

Changes to ext/lsm1/lsm_file.c.

  2799   2799   */
  2800   2800   int lsmFsSortedPadding(
  2801   2801     FileSystem *pFS, 
  2802   2802     Snapshot *pSnapshot,
  2803   2803     Segment *pSeg
  2804   2804   ){
  2805   2805     int rc = LSM_OK;
  2806         -  if( pFS->pCompress ){
         2806  +  if( pFS->pCompress && pSeg->iFirst ){
  2807   2807       Pgno iLast2;
  2808   2808       Pgno iLast = pSeg->iLastPg;     /* Current last page of segment */
  2809   2809       int nPad;                       /* Bytes of padding required */
  2810   2810       u8 aSz[3];
  2811   2811   
  2812   2812       iLast2 = (1 + iLast/pFS->szSector) * pFS->szSector - 1;
  2813   2813       assert( fsPageToBlock(pFS, iLast)==fsPageToBlock(pFS, iLast2) );

Changes to ext/lsm1/lsm_shared.c.

   516    516       rc = lsmFsOpen(pDb, zName, p->bReadonly);
   517    517     }
   518    518   
   519    519     /* If the db handle is read-write, then connect to the system now. Run
   520    520     ** recovery as necessary. Or, if this is a read-only database handle,
   521    521     ** defer attempting to connect to the system until a read-transaction
   522    522     ** is opened.  */
   523         -  if( pDb->bReadonly==0 ){
   524         -    if( rc==LSM_OK ){
   525         -      rc = lsmFsConfigure(pDb);
   526         -    }
   527         -    if( rc==LSM_OK ){
   528         -      rc = doDbConnect(pDb);
   529         -    }
          523  +  if( rc==LSM_OK ){
          524  +    rc = lsmFsConfigure(pDb);
          525  +  }
          526  +  if( rc==LSM_OK && pDb->bReadonly==0 ){
          527  +    rc = doDbConnect(pDb);
   530    528     }
   531    529   
   532    530     return rc;
   533    531   }
   534    532   
   535    533   static void dbDeferClose(lsm_db *pDb){
   536    534     if( pDb->pFS ){

Added ext/misc/btreeinfo.c.

            1  +/*
            2  +** 2017-10-24
            3  +**
            4  +** The author disclaims copyright to this source code.  In place of
            5  +** a legal notice, here is a blessing:
            6  +**
            7  +**    May you do good and not evil.
            8  +**    May you find forgiveness for yourself and forgive others.
            9  +**    May you share freely, never taking more than you give.
           10  +**
           11  +******************************************************************************
           12  +**
           13  +** This file contains an implementation of the "sqlite_btreeinfo" virtual table.
           14  +**
           15  +** The sqlite_btreeinfo virtual table is a read-only eponymous-only virtual
           16  +** table that shows information about all btrees in an SQLite database file.
           17  +** The schema is like this:
           18  +**
           19  +** CREATE TABLE sqlite_btreeinfo(
           20  +**    type TEXT,                   -- "table" or "index"
           21  +**    name TEXT,                   -- Name of table or index for this btree.
           22  +**    tbl_name TEXT,               -- Associated table
           23  +**    rootpage INT,                -- The root page of the btree
           24  +**    sql TEXT,                    -- SQL for this btree - from sqlite_master
           25  +**    hasRowid BOOLEAN,            -- True if the btree has a rowid
           26  +**    nEntry INT,                  -- Estimated number of enteries
           27  +**    nPage INT,                   -- Estimated number of pages
           28  +**    depth INT,                   -- Depth of the btree
           29  +**    szPage INT,                  -- Size of each page in bytes
           30  +**    zSchema TEXT HIDDEN          -- The schema to which this btree belongs
           31  +** );
           32  +**
           33  +** The first 5 fields are taken directly from the sqlite_master table.
           34  +** Considering only the first 5 fields, the only difference between 
           35  +** this virtual table and the sqlite_master table is that this virtual
           36  +** table omits all entries that have a 0 or NULL rowid - in other words
           37  +** it omits triggers and views.
           38  +**
           39  +** The value added by this table comes in the next 5 fields.
           40  +**
           41  +** Note that nEntry and nPage are *estimated*.  They are computed doing
           42  +** a single search from the root to a leaf, counting the number of cells
           43  +** at each level, and assuming that unvisited pages have a similar number
           44  +** of cells.
           45  +**
           46  +** The sqlite_dbpage virtual table must be available for this virtual table
           47  +** to operate.
           48  +**
           49  +** USAGE EXAMPLES:
           50  +**
           51  +** Show the table btrees in a schema order with the tables with the most
           52  +** rows occuring first:
           53  +**
           54  +**      SELECT name, nEntry
           55  +**        FROM sqlite_btreeinfo
           56  +**       WHERE type='table'
           57  +**       ORDER BY nEntry DESC, name;
           58  +**
           59  +** Show the names of all WITHOUT ROWID tables: 
           60  +**
           61  +**      SELECT name FROM sqlite_btreeinfo
           62  +**       WHERE type='table' AND NOT hasRowid;
           63  +*/
           64  +#if !defined(SQLITEINT_H)
           65  +#include "sqlite3ext.h"
           66  +#endif
           67  +SQLITE_EXTENSION_INIT1
           68  +#include <string.h>
           69  +#include <assert.h>
           70  +
           71  +/* Columns available in this virtual table */
           72  +#define BINFO_COLUMN_TYPE         0
           73  +#define BINFO_COLUMN_NAME         1
           74  +#define BINFO_COLUMN_TBL_NAME     2
           75  +#define BINFO_COLUMN_ROOTPAGE     3
           76  +#define BINFO_COLUMN_SQL          4
           77  +#define BINFO_COLUMN_HASROWID     5
           78  +#define BINFO_COLUMN_NENTRY       6
           79  +#define BINFO_COLUMN_NPAGE        7
           80  +#define BINFO_COLUMN_DEPTH        8
           81  +#define BINFO_COLUMN_SZPAGE       9
           82  +#define BINFO_COLUMN_SCHEMA      10
           83  +
           84  +/* Forward declarations */
           85  +typedef struct BinfoTable BinfoTable;
           86  +typedef struct BinfoCursor BinfoCursor;
           87  +
           88  +/* A cursor for the sqlite_btreeinfo table */
           89  +struct BinfoCursor {
           90  +  sqlite3_vtab_cursor base;       /* Base class.  Must be first */
           91  +  sqlite3_stmt *pStmt;            /* Query against sqlite_master */
           92  +  int rc;                         /* Result of previous sqlite_step() call */
           93  +  int hasRowid;                   /* hasRowid value.  Negative if unknown. */
           94  +  sqlite3_int64 nEntry;           /* nEntry value */
           95  +  int nPage;                      /* nPage value */
           96  +  int depth;                      /* depth value */
           97  +  int szPage;                     /* size of a btree page.  0 if unknown */
           98  +  char *zSchema;                  /* Schema being interrogated */
           99  +};
          100  +
          101  +/* The sqlite_btreeinfo table */
          102  +struct BinfoTable {
          103  +  sqlite3_vtab base;              /* Base class.  Must be first */
          104  +  sqlite3 *db;                    /* The databse connection */
          105  +};
          106  +
          107  +/*
          108  +** Connect to the sqlite_btreeinfo virtual table.
          109  +*/
          110  +static int binfoConnect(
          111  +  sqlite3 *db,
          112  +  void *pAux,
          113  +  int argc, const char *const*argv,
          114  +  sqlite3_vtab **ppVtab,
          115  +  char **pzErr
          116  +){
          117  +  BinfoTable *pTab = 0;
          118  +  int rc = SQLITE_OK;
          119  +  rc = sqlite3_declare_vtab(db, 
          120  +      "CREATE TABLE x(\n"
          121  +      " type TEXT,\n"
          122  +      " name TEXT,\n"
          123  +      " tbl_name TEXT,\n"
          124  +      " rootpage INT,\n"
          125  +      " sql TEXT,\n"
          126  +      " hasRowid BOOLEAN,\n"
          127  +      " nEntry INT,\n"
          128  +      " nPage INT,\n"
          129  +      " depth INT,\n"
          130  +      " szPage INT,\n"
          131  +      " zSchema TEXT HIDDEN\n"
          132  +      ")");
          133  +  if( rc==SQLITE_OK ){
          134  +    pTab = (BinfoTable *)sqlite3_malloc64(sizeof(BinfoTable));
          135  +    if( pTab==0 ) rc = SQLITE_NOMEM;
          136  +  }
          137  +  assert( rc==SQLITE_OK || pTab==0 );
          138  +  if( pTab ){
          139  +    pTab->db = db;
          140  +  }
          141  +  *ppVtab = (sqlite3_vtab*)pTab;
          142  +  return rc;
          143  +}
          144  +
          145  +/*
          146  +** Disconnect from or destroy a btreeinfo virtual table.
          147  +*/
          148  +static int binfoDisconnect(sqlite3_vtab *pVtab){
          149  +  sqlite3_free(pVtab);
          150  +  return SQLITE_OK;
          151  +}
          152  +
          153  +/*
          154  +** idxNum:
          155  +**
          156  +**     0     Use "main" for the schema
          157  +**     1     Schema identified by parameter ?1
          158  +*/
          159  +static int binfoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
          160  +  int i;
          161  +  pIdxInfo->estimatedCost = 10000.0;  /* Cost estimate */
          162  +  pIdxInfo->estimatedRows = 100;
          163  +  for(i=0; i<pIdxInfo->nConstraint; i++){
          164  +    struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
          165  +    if( p->usable
          166  +     && p->iColumn==BINFO_COLUMN_SCHEMA
          167  +     && p->op==SQLITE_INDEX_CONSTRAINT_EQ
          168  +    ){
          169  +      pIdxInfo->estimatedCost = 1000.0;
          170  +      pIdxInfo->idxNum = 1;
          171  +      pIdxInfo->aConstraintUsage[i].argvIndex = 1;
          172  +      pIdxInfo->aConstraintUsage[i].omit = 1;
          173  +      break;
          174  +    }
          175  +  }
          176  +  return SQLITE_OK;
          177  +}
          178  +
          179  +/*
          180  +** Open a new btreeinfo cursor.
          181  +*/
          182  +static int binfoOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
          183  +  BinfoCursor *pCsr;
          184  +
          185  +  pCsr = (BinfoCursor *)sqlite3_malloc64(sizeof(BinfoCursor));
          186  +  if( pCsr==0 ){
          187  +    return SQLITE_NOMEM;
          188  +  }else{
          189  +    memset(pCsr, 0, sizeof(BinfoCursor));
          190  +    pCsr->base.pVtab = pVTab;
          191  +  }
          192  +
          193  +  *ppCursor = (sqlite3_vtab_cursor *)pCsr;
          194  +  return SQLITE_OK;
          195  +}
          196  +
          197  +/*
          198  +** Close a btreeinfo cursor.
          199  +*/
          200  +static int binfoClose(sqlite3_vtab_cursor *pCursor){
          201  +  BinfoCursor *pCsr = (BinfoCursor *)pCursor;
          202  +  sqlite3_finalize(pCsr->pStmt);
          203  +  sqlite3_free(pCsr->zSchema);
          204  +  sqlite3_free(pCsr);
          205  +  return SQLITE_OK;
          206  +}
          207  +
          208  +/*
          209  +** Move a btreeinfo cursor to the next entry in the file.
          210  +*/
          211  +static int binfoNext(sqlite3_vtab_cursor *pCursor){
          212  +  BinfoCursor *pCsr = (BinfoCursor *)pCursor;
          213  +  pCsr->rc = sqlite3_step(pCsr->pStmt);
          214  +  pCsr->hasRowid = -1;
          215  +  return pCsr->rc==SQLITE_ERROR ? SQLITE_ERROR : SQLITE_OK;
          216  +}
          217  +
          218  +/* We have reached EOF if previous sqlite3_step() returned
          219  +** anything other than SQLITE_ROW;
          220  +*/
          221  +static int binfoEof(sqlite3_vtab_cursor *pCursor){
          222  +  BinfoCursor *pCsr = (BinfoCursor *)pCursor;
          223  +  return pCsr->rc!=SQLITE_ROW;
          224  +}
          225  +
          226  +/* Position a cursor back to the beginning.
          227  +*/
          228  +static int binfoFilter(
          229  +  sqlite3_vtab_cursor *pCursor, 
          230  +  int idxNum, const char *idxStr,
          231  +  int argc, sqlite3_value **argv
          232  +){
          233  +  BinfoCursor *pCsr = (BinfoCursor *)pCursor;
          234  +  BinfoTable *pTab = (BinfoTable *)pCursor->pVtab;
          235  +  char *zSql;
          236  +  int rc;
          237  +
          238  +  sqlite3_free(pCsr->zSchema);
          239  +  if( idxNum==1 && sqlite3_value_type(argv[0])!=SQLITE_NULL ){
          240  +    pCsr->zSchema = sqlite3_mprintf("%s", sqlite3_value_text(argv[0]));
          241  +  }else{
          242  +    pCsr->zSchema = sqlite3_mprintf("main");
          243  +  }
          244  +  zSql = sqlite3_mprintf(
          245  +      "SELECT 0, 'table','sqlite_master','sqlite_master',1,NULL "
          246  +      "UNION ALL "
          247  +      "SELECT rowid, type, name, tbl_name, rootpage, sql"
          248  +      " FROM \"%w\".sqlite_master WHERE rootpage>=1",
          249  +       pCsr->zSchema);
          250  +  sqlite3_finalize(pCsr->pStmt);
          251  +  pCsr->pStmt = 0;
          252  +  pCsr->hasRowid = -1;
          253  +  rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0);
          254  +  sqlite3_free(zSql);
          255  +  if( rc==SQLITE_OK ){
          256  +    rc = binfoNext(pCursor);
          257  +  }
          258  +  return rc;
          259  +}
          260  +
          261  +/* Decode big-endian integers */
          262  +static unsigned int get_uint16(unsigned char *a){
          263  +  return (a[0]<<8)|a[1];
          264  +}
          265  +static unsigned int get_uint32(unsigned char *a){
          266  +  return (a[0]<<24)|(a[1]<<16)|(a[2]<<8)|a[3];
          267  +}
          268  +
          269  +/* Examine the b-tree rooted at pgno and estimate its size.
          270  +** Return non-zero if anything goes wrong.
          271  +*/
          272  +static int binfoCompute(sqlite3 *db, int pgno, BinfoCursor *pCsr){
          273  +  sqlite3_int64 nEntry = 1;
          274  +  int nPage = 1;
          275  +  unsigned char *aData;
          276  +  sqlite3_stmt *pStmt = 0;
          277  +  int rc = SQLITE_OK;
          278  +  int pgsz = 0;
          279  +  int nCell;
          280  +  int iCell;
          281  +
          282  +  rc = sqlite3_prepare_v2(db, 
          283  +           "SELECT data FROM sqlite_dbpage('main') WHERE pgno=?1", -1,
          284  +           &pStmt, 0);
          285  +  if( rc ) return rc;
          286  +  pCsr->depth = 1;
          287  +  while(1){
          288  +    sqlite3_bind_int(pStmt, 1, pgno);
          289  +    rc = sqlite3_step(pStmt);
          290  +    if( rc!=SQLITE_ROW ){
          291  +      rc = SQLITE_ERROR;
          292  +      break;
          293  +    }
          294  +    pCsr->szPage = pgsz = sqlite3_column_bytes(pStmt, 0);
          295  +    aData = (unsigned char*)sqlite3_column_blob(pStmt, 0);
          296  +    if( aData==0 ){    
          297  +      rc = SQLITE_NOMEM;
          298  +      break;
          299  +    }
          300  +    if( pgno==1 ){
          301  +      aData += 100;
          302  +      pgsz -= 100;
          303  +    }
          304  +    pCsr->hasRowid = aData[0]!=2 && aData[0]!=10;
          305  +    nCell = get_uint16(aData+3);
          306  +    nEntry *= (nCell+1);
          307  +    if( aData[0]==10 || aData[0]==13 ) break;
          308  +    nPage *= (nCell+1);
          309  +    if( nCell<=1 ){
          310  +      pgno = get_uint32(aData+8);
          311  +    }else{
          312  +      iCell = get_uint16(aData+12+2*(nCell/2));
          313  +      if( pgno==1 ) iCell -= 100;
          314  +      if( iCell<=12 || iCell>=pgsz-4 ){
          315  +        rc = SQLITE_CORRUPT;
          316  +        break;
          317  +      }
          318  +      pgno = get_uint32(aData+iCell);
          319  +    }
          320  +    pCsr->depth++;
          321  +    sqlite3_reset(pStmt);
          322  +  }
          323  +  sqlite3_finalize(pStmt);
          324  +  pCsr->nPage = nPage;
          325  +  pCsr->nEntry = nEntry;
          326  +  if( rc==SQLITE_ROW ) rc = SQLITE_OK;
          327  +  return rc;
          328  +}
          329  +
          330  +/* Return a column for the sqlite_btreeinfo table */
          331  +static int binfoColumn(
          332  +  sqlite3_vtab_cursor *pCursor, 
          333  +  sqlite3_context *ctx, 
          334  +  int i
          335  +){
          336  +  BinfoCursor *pCsr = (BinfoCursor *)pCursor;
          337  +  if( i>=BINFO_COLUMN_HASROWID && i<=BINFO_COLUMN_SZPAGE && pCsr->hasRowid<0 ){
          338  +    int pgno = sqlite3_column_int(pCsr->pStmt, BINFO_COLUMN_ROOTPAGE+1);
          339  +    sqlite3 *db = sqlite3_context_db_handle(ctx);
          340  +    int rc = binfoCompute(db, pgno, pCsr);
          341  +    if( rc ){
          342  +      return rc;
          343  +    }
          344  +  }
          345  +  switch( i ){
          346  +    case BINFO_COLUMN_NAME:
          347  +    case BINFO_COLUMN_TYPE:
          348  +    case BINFO_COLUMN_TBL_NAME:
          349  +    case BINFO_COLUMN_ROOTPAGE:
          350  +    case BINFO_COLUMN_SQL: {
          351  +      sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pStmt, i+1));
          352  +      break;
          353  +    }
          354  +    case BINFO_COLUMN_HASROWID: {
          355  +      sqlite3_result_int(ctx, pCsr->hasRowid);
          356  +      break;
          357  +    }
          358  +    case BINFO_COLUMN_NENTRY: {
          359  +      sqlite3_result_int64(ctx, pCsr->nEntry);
          360  +      break;
          361  +    }
          362  +    case BINFO_COLUMN_NPAGE: {
          363  +      sqlite3_result_int(ctx, pCsr->nPage);
          364  +      break;
          365  +    }
          366  +    case BINFO_COLUMN_DEPTH: {
          367  +      sqlite3_result_int(ctx, pCsr->depth);
          368  +      break;
          369  +    }
          370  +    case BINFO_COLUMN_SCHEMA: {
          371  +      sqlite3_result_text(ctx, pCsr->zSchema, -1, SQLITE_STATIC);
          372  +      break;
          373  +    }
          374  +  }
          375  +  return SQLITE_OK;
          376  +}
          377  +
          378  +/* Return the ROWID for the sqlite_btreeinfo table */
          379  +static int binfoRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
          380  +  BinfoCursor *pCsr = (BinfoCursor *)pCursor;
          381  +  *pRowid = sqlite3_column_int64(pCsr->pStmt, 0);
          382  +  return SQLITE_OK;
          383  +}
          384  +
          385  +/*
          386  +** Invoke this routine to register the "sqlite_btreeinfo" virtual table module
          387  +*/
          388  +int sqlite3BinfoRegister(sqlite3 *db){
          389  +  static sqlite3_module binfo_module = {
          390  +    0,                           /* iVersion */
          391  +    0,                           /* xCreate */
          392  +    binfoConnect,                /* xConnect */
          393  +    binfoBestIndex,              /* xBestIndex */
          394  +    binfoDisconnect,             /* xDisconnect */
          395  +    0,                           /* xDestroy */
          396  +    binfoOpen,                   /* xOpen - open a cursor */
          397  +    binfoClose,                  /* xClose - close a cursor */
          398  +    binfoFilter,                 /* xFilter - configure scan constraints */
          399  +    binfoNext,                   /* xNext - advance a cursor */
          400  +    binfoEof,                    /* xEof - check for end of scan */
          401  +    binfoColumn,                 /* xColumn - read data */
          402  +    binfoRowid,                  /* xRowid - read data */
          403  +    0,                           /* xUpdate */
          404  +    0,                           /* xBegin */
          405  +    0,                           /* xSync */
          406  +    0,                           /* xCommit */
          407  +    0,                           /* xRollback */
          408  +    0,                           /* xFindMethod */
          409  +    0,                           /* xRename */
          410  +    0,                           /* xSavepoint */
          411  +    0,                           /* xRelease */
          412  +    0,                           /* xRollbackTo */
          413  +  };
          414  +  return sqlite3_create_module(db, "sqlite_btreeinfo", &binfo_module, 0);
          415  +}
          416  +
          417  +#ifdef _WIN32
          418  +__declspec(dllexport)
          419  +#endif
          420  +int sqlite3_btreeinfo_init(
          421  +  sqlite3 *db, 
          422  +  char **pzErrMsg, 
          423  +  const sqlite3_api_routines *pApi
          424  +){
          425  +  SQLITE_EXTENSION_INIT2(pApi);
          426  +  return sqlite3BinfoRegister(db);
          427  +}

Changes to ext/misc/spellfix.c.

  1118   1118   */
  1119   1119   static int editDist3Install(sqlite3 *db){
  1120   1120     int rc;
  1121   1121     EditDist3Config *pConfig = sqlite3_malloc64( sizeof(*pConfig) );
  1122   1122     if( pConfig==0 ) return SQLITE_NOMEM;
  1123   1123     memset(pConfig, 0, sizeof(*pConfig));
  1124   1124     rc = sqlite3_create_function_v2(db, "editdist3",
  1125         -              2, SQLITE_UTF8, pConfig, editDist3SqlFunc, 0, 0, 0);
         1125  +              2, SQLITE_UTF8|SQLITE_DETERMINISTIC, pConfig,
         1126  +              editDist3SqlFunc, 0, 0, 0);
  1126   1127     if( rc==SQLITE_OK ){
  1127   1128       rc = sqlite3_create_function_v2(db, "editdist3",
  1128         -                3, SQLITE_UTF8, pConfig, editDist3SqlFunc, 0, 0, 0);
         1129  +                3, SQLITE_UTF8|SQLITE_DETERMINISTIC, pConfig,
         1130  +                editDist3SqlFunc, 0, 0, 0);
  1129   1131     }
  1130   1132     if( rc==SQLITE_OK ){
  1131   1133       rc = sqlite3_create_function_v2(db, "editdist3",
  1132         -                1, SQLITE_UTF8, pConfig, editDist3SqlFunc, 0, 0,
  1133         -                editDist3ConfigDelete);
         1134  +                1, SQLITE_UTF8|SQLITE_DETERMINISTIC, pConfig,
         1135  +                editDist3SqlFunc, 0, 0, editDist3ConfigDelete);
  1134   1136     }else{
  1135   1137       sqlite3_free(pConfig);
  1136   1138     }
  1137   1139     return rc;
  1138   1140   }
  1139   1141   /* End configurable cost unicode edit distance routines
  1140   1142   ******************************************************************************
................................................................................
  2891   2893   
  2892   2894   /*
  2893   2895   ** Register the various functions and the virtual table.
  2894   2896   */
  2895   2897   static int spellfix1Register(sqlite3 *db){
  2896   2898     int rc = SQLITE_OK;
  2897   2899     int i;
  2898         -  rc = sqlite3_create_function(db, "spellfix1_translit", 1, SQLITE_UTF8, 0,
  2899         -                                  transliterateSqlFunc, 0, 0);
         2900  +  rc = sqlite3_create_function(db, "spellfix1_translit", 1,
         2901  +                               SQLITE_UTF8|SQLITE_DETERMINISTIC, 0,
         2902  +                                transliterateSqlFunc, 0, 0);
  2900   2903     if( rc==SQLITE_OK ){
  2901         -    rc = sqlite3_create_function(db, "spellfix1_editdist", 2, SQLITE_UTF8, 0,
         2904  +    rc = sqlite3_create_function(db, "spellfix1_editdist", 2,
         2905  +                                 SQLITE_UTF8|SQLITE_DETERMINISTIC, 0,
  2902   2906                                     editdistSqlFunc, 0, 0);
  2903   2907     }
  2904   2908     if( rc==SQLITE_OK ){
  2905         -    rc = sqlite3_create_function(db, "spellfix1_phonehash", 1, SQLITE_UTF8, 0,
         2909  +    rc = sqlite3_create_function(db, "spellfix1_phonehash", 1,
         2910  +                                 SQLITE_UTF8|SQLITE_DETERMINISTIC, 0,
  2906   2911                                     phoneticHashSqlFunc, 0, 0);
  2907   2912     }
  2908   2913     if( rc==SQLITE_OK ){
  2909         -    rc = sqlite3_create_function(db, "spellfix1_scriptcode", 1, SQLITE_UTF8, 0,
         2914  +    rc = sqlite3_create_function(db, "spellfix1_scriptcode", 1,
         2915  +                                  SQLITE_UTF8|SQLITE_DETERMINISTIC, 0,
  2910   2916                                     scriptCodeSqlFunc, 0, 0);
  2911   2917     }
  2912   2918     if( rc==SQLITE_OK ){
  2913   2919       rc = sqlite3_create_module(db, "spellfix1", &spellfix1Module, 0);
  2914   2920     }
  2915   2921     if( rc==SQLITE_OK ){
  2916   2922       rc = editDist3Install(db);

Changes to ext/repair/checkfreelist.c.

   162    162     rc = sqlite3_prepare_v2(db, zTrunk, -1, &pTrunk, 0);
   163    163     if( rc!=SQLITE_OK ) return rc;
   164    164     sqlite3_bind_text(pTrunk, 1, zDb, -1, SQLITE_STATIC);
   165    165     while( rc==SQLITE_OK && sqlite3_step(pTrunk)==SQLITE_ROW ){
   166    166       u32 i;
   167    167       u32 iTrunk = (u32)sqlite3_column_int(pTrunk, 0);
   168    168       const u8 *aData = (const u8*)sqlite3_column_blob(pTrunk, 1);
   169         -    int nData = sqlite3_column_bytes(pTrunk, 1);
          169  +    u32 nData = (u32)sqlite3_column_bytes(pTrunk, 1);
   170    170       u32 iNext = get4byte(&aData[0]);
   171    171       u32 nLeaf = get4byte(&aData[4]);
   172    172   
   173    173       if( nLeaf>((nData/4)-2-6) ){
   174    174         rc = checkFreelistError(pzOut, 
   175    175             "leaf count out of range (%d) on trunk page %d", 
   176    176             (int)nLeaf, (int)iTrunk

Added ext/repair/checkindex.c.

            1  +/*
            2  +** 2017 October 27
            3  +**
            4  +** The author disclaims copyright to this source code.  In place of
            5  +** a legal notice, here is a blessing:
            6  +**
            7  +**    May you do good and not evil.
            8  +**    May you find forgiveness for yourself and forgive others.
            9  +**    May you share freely, never taking more than you give.
           10  +**
           11  +*************************************************************************
           12  +*/
           13  +
           14  +#include "sqlite3ext.h"
           15  +SQLITE_EXTENSION_INIT1
           16  +
           17  +/*
           18  +** Stuff that is available inside the amalgamation, but which we need to
           19  +** declare ourselves if this module is compiled separately.
           20  +*/
           21  +#ifndef SQLITE_AMALGAMATION
           22  +# include <string.h>
           23  +# include <stdio.h>
           24  +# include <stdlib.h>
           25  +# include <assert.h>
           26  +typedef unsigned char u8;
           27  +typedef unsigned short u16;
           28  +typedef unsigned int u32;
           29  +#define get4byte(x) (        \
           30  +    ((u32)((x)[0])<<24) +    \
           31  +    ((u32)((x)[1])<<16) +    \
           32  +    ((u32)((x)[2])<<8) +     \
           33  +    ((u32)((x)[3]))          \
           34  +)
           35  +#endif
           36  +
           37  +typedef struct CidxTable CidxTable;
           38  +typedef struct CidxCursor CidxCursor;
           39  +
           40  +struct CidxTable {
           41  +  sqlite3_vtab base;              /* Base class.  Must be first */
           42  +  sqlite3 *db;
           43  +};
           44  +
           45  +struct CidxCursor {
           46  +  sqlite3_vtab_cursor base;       /* Base class.  Must be first */
           47  +  sqlite3_int64 iRowid;           /* Row number of the output */
           48  +  char *zIdxName;                 /* Copy of the index_name parameter */
           49  +  char *zAfterKey;                /* Copy of the after_key parameter */
           50  +  sqlite3_stmt *pStmt;            /* SQL statement that generates the output */
           51  +};
           52  +
           53  +typedef struct CidxColumn CidxColumn;
           54  +struct CidxColumn {
           55  +  char *zExpr;                    /* Text for indexed expression */
           56  +  int bDesc;                      /* True for DESC columns, otherwise false */
           57  +  int bKey;                       /* Part of index, not PK */
           58  +};
           59  +
           60  +typedef struct CidxIndex CidxIndex;
           61  +struct CidxIndex {
           62  +  char *zWhere;                   /* WHERE clause, if any */
           63  +  int nCol;                       /* Elements in aCol[] array */
           64  +  CidxColumn aCol[1];             /* Array of indexed columns */
           65  +};
           66  +
           67  +static void *cidxMalloc(int *pRc, int n){
           68  +  void *pRet = 0;
           69  +  assert( n!=0 );
           70  +  if( *pRc==SQLITE_OK ){
           71  +    pRet = sqlite3_malloc(n);
           72  +    if( pRet ){
           73  +      memset(pRet, 0, n);
           74  +    }else{
           75  +      *pRc = SQLITE_NOMEM;
           76  +    }
           77  +  }
           78  +  return pRet;
           79  +}
           80  +
           81  +static void cidxCursorError(CidxCursor *pCsr, const char *zFmt, ...){
           82  +  va_list ap;
           83  +  va_start(ap, zFmt);
           84  +  assert( pCsr->base.pVtab->zErrMsg==0 );
           85  +  pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
           86  +  va_end(ap);
           87  +}
           88  +
           89  +/*
           90  +** Connect to the incremental_index_check virtual table.
           91  +*/
           92  +static int cidxConnect(
           93  +  sqlite3 *db,
           94  +  void *pAux,
           95  +  int argc, const char *const*argv,
           96  +  sqlite3_vtab **ppVtab,
           97  +  char **pzErr
           98  +){
           99  +  int rc = SQLITE_OK;
          100  +  CidxTable *pRet;
          101  +
          102  +#define IIC_ERRMSG        0
          103  +#define IIC_CURRENT_KEY   1
          104  +#define IIC_INDEX_NAME    2
          105  +#define IIC_AFTER_KEY     3
          106  +#define IIC_SCANNER_SQL   4
          107  +  rc = sqlite3_declare_vtab(db,
          108  +      "CREATE TABLE xyz("
          109  +      " errmsg TEXT,"            /* Error message or NULL if everything is ok */
          110  +      " current_key TEXT,"       /* SQLite quote() text of key values */
          111  +      " index_name HIDDEN,"      /* IN: name of the index being scanned */
          112  +      " after_key HIDDEN,"       /* IN: Start scanning after this key */
          113  +      " scanner_sql HIDDEN"      /* debuggingn info: SQL used for scanner */
          114  +      ")"
          115  +  );
          116  +  pRet = cidxMalloc(&rc, sizeof(CidxTable));
          117  +  if( pRet ){
          118  +    pRet->db = db;
          119  +  }
          120  +
          121  +  *ppVtab = (sqlite3_vtab*)pRet;
          122  +  return rc;
          123  +}
          124  +
          125  +/*
          126  +** Disconnect from or destroy an incremental_index_check virtual table.
          127  +*/
          128  +static int cidxDisconnect(sqlite3_vtab *pVtab){
          129  +  CidxTable *pTab = (CidxTable*)pVtab;
          130  +  sqlite3_free(pTab);
          131  +  return SQLITE_OK;
          132  +}
          133  +
          134  +/*
          135  +** idxNum and idxStr are not used.  There are only three possible plans,
          136  +** which are all distinguished by the number of parameters.
          137  +**
          138  +**   No parameters:         A degenerate plan.  The result is zero rows.
          139  +**   1 Parameter:           Scan all of the index starting with first entry
          140  +**   2 parameters:          Scan the index starting after the "after_key".    
          141  +**
          142  +** Provide successively smaller costs for each of these plans to encourage
          143  +** the query planner to select the one with the most parameters.
          144  +*/
          145  +static int cidxBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pInfo){
          146  +  int iIdxName = -1;
          147  +  int iAfterKey = -1;
          148  +  int i;
          149  +
          150  +  for(i=0; i<pInfo->nConstraint; i++){
          151  +    struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
          152  +    if( p->usable==0 ) continue;
          153  +    if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
          154  +
          155  +    if( p->iColumn==IIC_INDEX_NAME ){
          156  +      iIdxName = i;
          157  +    }
          158  +    if( p->iColumn==IIC_AFTER_KEY ){
          159  +      iAfterKey = i;
          160  +    }
          161  +  }
          162  +
          163  +  if( iIdxName<0 ){
          164  +    pInfo->estimatedCost = 1000000000.0;
          165  +  }else{
          166  +    pInfo->aConstraintUsage[iIdxName].argvIndex = 1;
          167  +    pInfo->aConstraintUsage[iIdxName].omit = 1;
          168  +    if( iAfterKey<0 ){
          169  +      pInfo->estimatedCost = 1000000.0;
          170  +    }else{
          171  +      pInfo->aConstraintUsage[iAfterKey].argvIndex = 2;
          172  +      pInfo->aConstraintUsage[iAfterKey].omit = 1;
          173  +      pInfo->estimatedCost = 1000.0;
          174  +    }
          175  +  }
          176  +
          177  +  return SQLITE_OK;
          178  +}
          179  +
          180  +/*
          181  +** Open a new btreeinfo cursor.
          182  +*/
          183  +static int cidxOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
          184  +  CidxCursor *pRet;
          185  +  int rc = SQLITE_OK;
          186  +
          187  +  pRet = cidxMalloc(&rc, sizeof(CidxCursor));
          188  +
          189  +  *ppCursor = (sqlite3_vtab_cursor*)pRet;
          190  +  return rc;
          191  +}
          192  +
          193  +/*
          194  +** Close a btreeinfo cursor.
          195  +*/
          196  +static int cidxClose(sqlite3_vtab_cursor *pCursor){
          197  +  CidxCursor *pCsr = (CidxCursor*)pCursor;
          198  +  sqlite3_finalize(pCsr->pStmt);
          199  +  sqlite3_free(pCsr->zIdxName);
          200  +  sqlite3_free(pCsr->zAfterKey);
          201  +  sqlite3_free(pCsr);
          202  +  return SQLITE_OK;
          203  +}
          204  +
          205  +/*
          206  +** Move a btreeinfo cursor to the next entry in the file.
          207  +*/
          208  +static int cidxNext(sqlite3_vtab_cursor *pCursor){
          209  +  CidxCursor *pCsr = (CidxCursor*)pCursor;
          210  +  int rc = sqlite3_step(pCsr->pStmt);
          211  +  if( rc!=SQLITE_ROW ){
          212  +    rc = sqlite3_finalize(pCsr->pStmt);
          213  +    pCsr->pStmt = 0;
          214  +    if( rc!=SQLITE_OK ){
          215  +      sqlite3 *db = ((CidxTable*)pCsr->base.pVtab)->db;
          216  +      cidxCursorError(pCsr, "Cursor error: %s", sqlite3_errmsg(db));
          217  +    }
          218  +  }else{
          219  +    pCsr->iRowid++;
          220  +    rc = SQLITE_OK;
          221  +  }
          222  +  return rc;
          223  +}
          224  +
          225  +/* We have reached EOF if previous sqlite3_step() returned
          226  +** anything other than SQLITE_ROW;
          227  +*/
          228  +static int cidxEof(sqlite3_vtab_cursor *pCursor){
          229  +  CidxCursor *pCsr = (CidxCursor*)pCursor;
          230  +  return pCsr->pStmt==0;
          231  +}
          232  +
          233  +static char *cidxMprintf(int *pRc, const char *zFmt, ...){
          234  +  char *zRet = 0;
          235  +  va_list ap;
          236  +  va_start(ap, zFmt);
          237  +  zRet = sqlite3_vmprintf(zFmt, ap);
          238  +  if( *pRc==SQLITE_OK ){
          239  +    if( zRet==0 ){
          240  +      *pRc = SQLITE_NOMEM;
          241  +    }
          242  +  }else{
          243  +    sqlite3_free(zRet);
          244  +    zRet = 0;
          245  +  }
          246  +  va_end(ap);
          247  +  return zRet;
          248  +}
          249  +
          250  +static sqlite3_stmt *cidxPrepare(
          251  +  int *pRc, CidxCursor *pCsr, const char *zFmt, ...
          252  +){
          253  +  sqlite3_stmt *pRet = 0;
          254  +  char *zSql;
          255  +  va_list ap;                     /* ... printf arguments */
          256  +  va_start(ap, zFmt);
          257  +
          258  +  zSql = sqlite3_vmprintf(zFmt, ap);
          259  +  if( *pRc==SQLITE_OK ){
          260  +    if( zSql==0 ){
          261  +      *pRc = SQLITE_NOMEM;
          262  +    }else{
          263  +      sqlite3 *db = ((CidxTable*)pCsr->base.pVtab)->db;
          264  +      *pRc = sqlite3_prepare_v2(db, zSql, -1, &pRet, 0);
          265  +      if( *pRc!=SQLITE_OK ){
          266  +        cidxCursorError(pCsr, "SQL error: %s", sqlite3_errmsg(db));
          267  +      }
          268  +    }
          269  +  }
          270  +  sqlite3_free(zSql);
          271  +  va_end(ap);
          272  +
          273  +  return pRet;
          274  +}
          275  +
          276  +static void cidxFinalize(int *pRc, sqlite3_stmt *pStmt){
          277  +  int rc = sqlite3_finalize(pStmt);
          278  +  if( *pRc==SQLITE_OK ) *pRc = rc;
          279  +}
          280  +
          281  +char *cidxStrdup(int *pRc, const char *zStr){
          282  +  char *zRet = 0;
          283  +  if( *pRc==SQLITE_OK ){
          284  +    int n = (int)strlen(zStr);
          285  +    zRet = cidxMalloc(pRc, n+1);
          286  +    if( zRet ) memcpy(zRet, zStr, n+1);
          287  +  }
          288  +  return zRet;
          289  +}
          290  +
          291  +static void cidxFreeIndex(CidxIndex *pIdx){
          292  +  if( pIdx ){
          293  +    int i;
          294  +    for(i=0; i<pIdx->nCol; i++){
          295  +      sqlite3_free(pIdx->aCol[i].zExpr);
          296  +    }
          297  +    sqlite3_free(pIdx->zWhere);
          298  +    sqlite3_free(pIdx);
          299  +  }
          300  +}
          301  +
          302  +static int cidx_isspace(char c){
          303  +  return c==' ' || c=='\t' || c=='\r' || c=='\n';
          304  +}
          305  +
          306  +static int cidx_isident(char c){
          307  +  return c<0 
          308  +    || (c>='0' && c<='9') || (c>='a' && c<='z') 
          309  +    || (c>='A' && c<='Z') || c=='_';
          310  +}
          311  +
          312  +#define CIDX_PARSE_EOF   0
          313  +#define CIDX_PARSE_COMMA 1      /*  "," */
          314  +#define CIDX_PARSE_OPEN  2      /*  "(" */
          315  +#define CIDX_PARSE_CLOSE 3      /*  ")" */
          316  +
          317  +/*
          318  +** Argument zIn points into the start, middle or end of a CREATE INDEX
          319  +** statement. If argument pbDoNotTrim is non-NULL, then this function
          320  +** scans the input until it finds EOF, a comma (",") or an open or
          321  +** close parenthesis character. It then sets (*pzOut) to point to said
          322  +** character and returns a CIDX_PARSE_XXX constant as appropriate. The
          323  +** parser is smart enough that special characters inside SQL strings
          324  +** or comments are not returned for.
          325  +**
          326  +** Or, if argument pbDoNotTrim is NULL, then this function sets *pzOut
          327  +** to point to the first character of the string that is not whitespace
          328  +** or part of an SQL comment and returns CIDX_PARSE_EOF.
          329  +**
          330  +** Additionally, if pbDoNotTrim is not NULL and the element immediately
          331  +** before (*pzOut) is an SQL comment of the form "-- comment", then
          332  +** (*pbDoNotTrim) is set before returning. In all other cases it is
          333  +** cleared.
          334  +*/
          335  +static int cidxFindNext(
          336  +  const char *zIn, 
          337  +  const char **pzOut,
          338  +  int *pbDoNotTrim                /* OUT: True if prev is -- comment */
          339  +){
          340  +  const char *z = zIn;
          341  +
          342  +  while( 1 ){
          343  +    while( cidx_isspace(*z) ) z++;
          344  +    if( z[0]=='-' && z[1]=='-' ){
          345  +      z += 2;
          346  +      while( z[0]!='\n' ){
          347  +        if( z[0]=='\0' ) return CIDX_PARSE_EOF;
          348  +        z++;
          349  +      }
          350  +      while( cidx_isspace(*z) ) z++;
          351  +      if( pbDoNotTrim ) *pbDoNotTrim = 1;
          352  +    }else
          353  +    if( z[0]=='/' && z[1]=='*' ){
          354  +      z += 2;
          355  +      while( z[0]!='*' || z[1]!='/' ){
          356  +        if( z[1]=='\0' ) return CIDX_PARSE_EOF;
          357  +        z++;
          358  +      }
          359  +      z += 2;
          360  +    }else{
          361  +      *pzOut = z;
          362  +      if( pbDoNotTrim==0 ) return CIDX_PARSE_EOF;
          363  +      switch( *z ){
          364  +        case '\0':
          365  +          return CIDX_PARSE_EOF;
          366  +        case '(':
          367  +          return CIDX_PARSE_OPEN;
          368  +        case ')':
          369  +          return CIDX_PARSE_CLOSE;
          370  +        case ',':
          371  +          return CIDX_PARSE_COMMA;
          372  +  
          373  +        case '"': 
          374  +        case '\'': 
          375  +        case '`': {
          376  +          char q = *z;
          377  +          z++;
          378  +          while( *z ){
          379  +            if( *z==q ){
          380  +              z++;
          381  +              if( *z!=q ) break;
          382  +            }
          383  +            z++;
          384  +          }
          385  +          break;
          386  +        }
          387  +  
          388  +        case '[':
          389  +          while( *z++!=']' );
          390  +          break;
          391  +  
          392  +        default:
          393  +          z++;
          394  +          break;
          395  +      }
          396  +      *pbDoNotTrim = 0;
          397  +    }
          398  +  }
          399  +
          400  +  assert( 0 );
          401  +  return -1;
          402  +}
          403  +
          404  +static int cidxParseSQL(CidxCursor *pCsr, CidxIndex *pIdx, const char *zSql){
          405  +  const char *z = zSql;
          406  +  const char *z1;
          407  +  int e;
          408  +  int rc = SQLITE_OK;
          409  +  int nParen = 1;
          410  +  int bDoNotTrim = 0;
          411  +  CidxColumn *pCol = pIdx->aCol;
          412  +
          413  +  e = cidxFindNext(z, &z, &bDoNotTrim);
          414  +  if( e!=CIDX_PARSE_OPEN ) goto parse_error;
          415  +  z1 = z+1;
          416  +  z++;
          417  +  while( nParen>0 ){
          418  +    e = cidxFindNext(z, &z, &bDoNotTrim);
          419  +    if( e==CIDX_PARSE_EOF ) goto parse_error;
          420  +    if( (e==CIDX_PARSE_COMMA || e==CIDX_PARSE_CLOSE) && nParen==1 ){
          421  +      const char *z2 = z;
          422  +      if( pCol->zExpr ) goto parse_error;
          423  +
          424  +      if( bDoNotTrim==0 ){
          425  +        while( cidx_isspace(z[-1]) ) z--;
          426  +        if( !sqlite3_strnicmp(&z[-3], "asc", 3) && 0==cidx_isident(z[-4]) ){
          427  +          z -= 3;
          428  +          while( cidx_isspace(z[-1]) ) z--;
          429  +        }else
          430  +          if( !sqlite3_strnicmp(&z[-4], "desc", 4) && 0==cidx_isident(z[-5]) ){
          431  +            z -= 4;
          432  +            while( cidx_isspace(z[-1]) ) z--;
          433  +          }
          434  +        while( cidx_isspace(z1[0]) ) z1++;
          435  +      }
          436  +
          437  +      pCol->zExpr = cidxMprintf(&rc, "%.*s", z-z1, z1);
          438  +      pCol++;
          439  +      z = z1 = z2+1;
          440  +    }
          441  +    if( e==CIDX_PARSE_OPEN ) nParen++;
          442  +    if( e==CIDX_PARSE_CLOSE ) nParen--;
          443  +    z++;
          444  +  }
          445  +
          446  +  /* Search for a WHERE clause */
          447  +  cidxFindNext(z, &z, 0);
          448  +  if( 0==sqlite3_strnicmp(z, "where", 5) ){
          449  +    pIdx->zWhere = cidxMprintf(&rc, "%s\n", &z[5]);
          450  +  }else if( z[0]!='\0' ){
          451  +    goto parse_error;
          452  +  }
          453  +
          454  +  return rc;
          455  +
          456  + parse_error:
          457  +  cidxCursorError(pCsr, "Parse error in: %s", zSql);
          458  +  return SQLITE_ERROR;
          459  +}
          460  +
          461  +static int cidxLookupIndex(
          462  +  CidxCursor *pCsr,               /* Cursor object */
          463  +  const char *zIdx,               /* Name of index to look up */
          464  +  CidxIndex **ppIdx,              /* OUT: Description of columns */
          465  +  char **pzTab                    /* OUT: Table name */
          466  +){
          467  +  int rc = SQLITE_OK;
          468  +  char *zTab = 0;
          469  +  CidxIndex *pIdx = 0;
          470  +
          471  +  sqlite3_stmt *pFindTab = 0;
          472  +  sqlite3_stmt *pInfo = 0;
          473  +    
          474  +  /* Find the table for this index. */
          475  +  pFindTab = cidxPrepare(&rc, pCsr, 
          476  +      "SELECT tbl_name, sql FROM sqlite_master WHERE name=%Q AND type='index'",
          477  +      zIdx
          478  +  );
          479  +  if( rc==SQLITE_OK && sqlite3_step(pFindTab)==SQLITE_ROW ){
          480  +    const char *zSql = (const char*)sqlite3_column_text(pFindTab, 1);
          481  +    zTab = cidxStrdup(&rc, (const char*)sqlite3_column_text(pFindTab, 0));
          482  +
          483  +    pInfo = cidxPrepare(&rc, pCsr, "PRAGMA index_xinfo(%Q)", zIdx);
          484  +    if( rc==SQLITE_OK ){
          485  +      int nAlloc = 0;
          486  +      int iCol = 0;
          487  +
          488  +      while( sqlite3_step(pInfo)==SQLITE_ROW ){
          489  +        const char *zName = (const char*)sqlite3_column_text(pInfo, 2);
          490  +        const char *zColl = (const char*)sqlite3_column_text(pInfo, 4);
          491  +        CidxColumn *p;
          492  +        if( zName==0 ) zName = "rowid";
          493  +        if( iCol==nAlloc ){
          494  +          int nByte = sizeof(CidxIndex) + sizeof(CidxColumn)*(nAlloc+8);
          495  +          pIdx = (CidxIndex*)sqlite3_realloc(pIdx, nByte);
          496  +          nAlloc += 8;
          497  +        }
          498  +        p = &pIdx->aCol[iCol++];
          499  +        p->bDesc = sqlite3_column_int(pInfo, 3);
          500  +        p->bKey = sqlite3_column_int(pInfo, 5);
          501  +        if( zSql==0 || p->bKey==0 ){
          502  +          p->zExpr = cidxMprintf(&rc, "\"%w\" COLLATE %s",zName,zColl);
          503  +        }else{
          504  +          p->zExpr = 0;
          505  +        }
          506  +        pIdx->nCol = iCol;
          507  +        pIdx->zWhere = 0;
          508  +      }
          509  +      cidxFinalize(&rc, pInfo);
          510  +    }
          511  +
          512  +    if( rc==SQLITE_OK && zSql ){
          513  +      rc = cidxParseSQL(pCsr, pIdx, zSql);
          514  +    }
          515  +  }
          516  +
          517  +  cidxFinalize(&rc, pFindTab);
          518  +  if( rc==SQLITE_OK && zTab==0 ){
          519  +    rc = SQLITE_ERROR;
          520  +  }
          521  +  
          522  +  if( rc!=SQLITE_OK ){
          523  +    sqlite3_free(zTab);
          524  +    cidxFreeIndex(pIdx);
          525  +  }else{
          526  +    *pzTab = zTab;
          527  +    *ppIdx = pIdx;
          528  +  }
          529  +
          530  +  return rc;
          531  +}
          532  +
          533  +static int cidxDecodeAfter(
          534  +  CidxCursor *pCsr, 
          535  +  int nCol, 
          536  +  const char *zAfterKey, 
          537  +  char ***pazAfter
          538  +){
          539  +  char **azAfter;
          540  +  int rc = SQLITE_OK;
          541  +  int nAfterKey = (int)strlen(zAfterKey);
          542  +
          543  +  azAfter = cidxMalloc(&rc, sizeof(char*)*nCol + nAfterKey+1);
          544  +  if( rc==SQLITE_OK ){
          545  +    int i;
          546  +    char *zCopy = (char*)&azAfter[nCol];
          547  +    char *p = zCopy;
          548  +    memcpy(zCopy, zAfterKey, nAfterKey+1);
          549  +    for(i=0; i<nCol; i++){
          550  +      while( *p==' ' ) p++;
          551  +
          552  +      /* Check NULL values */
          553  +      if( *p=='N' ){
          554  +        if( memcmp(p, "NULL", 4) ) goto parse_error;
          555  +        p += 4;
          556  +      }
          557  +
          558  +      /* Check strings and blob literals */
          559  +      else if( *p=='X' || *p=='\'' ){
          560  +        azAfter[i] = p;
          561  +        if( *p=='X' ) p++;
          562  +        if( *p!='\'' ) goto parse_error;
          563  +        p++;
          564  +        while( 1 ){
          565  +          if( *p=='\0' ) goto parse_error;
          566  +          if( *p=='\'' ){
          567  +            p++;
          568  +            if( *p!='\'' ) break;
          569  +          }
          570  +          p++;
          571  +        }
          572  +      }
          573  +
          574  +      /* Check numbers */
          575  +      else{
          576  +        azAfter[i] = p;
          577  +        while( (*p>='0' && *p<='9') 
          578  +            || *p=='.' || *p=='+' || *p=='-' || *p=='e' || *p=='E'
          579  +        ){
          580  +          p++;
          581  +        }
          582  +      }
          583  +
          584  +      while( *p==' ' ) p++;
          585  +      if( *p!=(i==(nCol-1) ? '\0' : ',') ){
          586  +        goto parse_error;
          587  +      }
          588  +      *p++ = '\0';
          589  +    }
          590  +  }
          591  +
          592  +  *pazAfter = azAfter;
          593  +  return rc;
          594  +
          595  + parse_error:
          596  +  sqlite3_free(azAfter);
          597  +  *pazAfter = 0;
          598  +  cidxCursorError(pCsr, "%s", "error parsing after value");
          599  +  return SQLITE_ERROR;
          600  +}
          601  +
          602  +static char *cidxWhere(
          603  +  int *pRc, CidxColumn *aCol, char **azAfter, int iGt, int bLastIsNull
          604  +){
          605  +  char *zRet = 0;
          606  +  const char *zSep = "";
          607  +  int i;
          608  +
          609  +  for(i=0; i<iGt; i++){
          610  +    zRet = cidxMprintf(pRc, "%z%s(%s) IS %s", zRet, 
          611  +        zSep, aCol[i].zExpr, (azAfter[i] ? azAfter[i] : "NULL")
          612  +    );
          613  +    zSep = " AND ";
          614  +  }
          615  +
          616  +  if( bLastIsNull ){
          617  +    zRet = cidxMprintf(pRc, "%z%s(%s) IS NULL", zRet, zSep, aCol[iGt].zExpr);
          618  +  }
          619  +  else if( azAfter[iGt] ){
          620  +    zRet = cidxMprintf(pRc, "%z%s(%s) %s %s", zRet, 
          621  +        zSep, aCol[iGt].zExpr, (aCol[iGt].bDesc ? "<" : ">"), 
          622  +        azAfter[iGt]
          623  +    );
          624  +  }else{
          625  +    zRet = cidxMprintf(pRc, "%z%s(%s) IS NOT NULL", zRet, zSep,aCol[iGt].zExpr);
          626  +  }
          627  +
          628  +  return zRet;
          629  +}
          630  +
          631  +#define CIDX_CLIST_ALL         0
          632  +#define CIDX_CLIST_ORDERBY     1
          633  +#define CIDX_CLIST_CURRENT_KEY 2
          634  +#define CIDX_CLIST_SUBWHERE    3
          635  +#define CIDX_CLIST_SUBEXPR     4
          636  +
          637  +/*
          638  +** This function returns various strings based on the contents of the
          639  +** CidxIndex structure and the eType parameter.
          640  +*/
          641  +static char *cidxColumnList(
          642  +  int *pRc,                       /* IN/OUT: Error code */
          643  +  const char *zIdx,
          644  +  CidxIndex *pIdx,                /* Indexed columns */
          645  +  int eType                       /* True to include ASC/DESC */
          646  +){
          647  +  char *zRet = 0;
          648  +  if( *pRc==SQLITE_OK ){
          649  +    const char *aDir[2] = {"", " DESC"};
          650  +    int i;
          651  +    const char *zSep = "";
          652  +
          653  +    for(i=0; i<pIdx->nCol; i++){
          654  +      CidxColumn *p = &pIdx->aCol[i];
          655  +      assert( pIdx->aCol[i].bDesc==0 || pIdx->aCol[i].bDesc==1 );
          656  +      switch( eType ){
          657  +
          658  +        case CIDX_CLIST_ORDERBY:
          659  +          zRet = cidxMprintf(pRc, "%z%s%d%s", zRet, zSep, i+1, aDir[p->bDesc]);
          660  +          zSep = ",";
          661  +          break;
          662  +
          663  +        case CIDX_CLIST_CURRENT_KEY:
          664  +          zRet = cidxMprintf(pRc, "%z%squote(i%d)", zRet, zSep, i);
          665  +          zSep = "||','||";
          666  +          break;
          667  +
          668  +        case CIDX_CLIST_SUBWHERE:
          669  +          if( p->bKey==0 ){
          670  +            zRet = cidxMprintf(pRc, "%z%s%s IS i.i%d", zRet, 
          671  +                zSep, p->zExpr, i
          672  +            );
          673  +            zSep = " AND ";
          674  +          }
          675  +          break;
          676  +
          677  +        case CIDX_CLIST_SUBEXPR:
          678  +          if( p->bKey==1 ){
          679  +            zRet = cidxMprintf(pRc, "%z%s%s IS i.i%d", zRet, 
          680  +                zSep, p->zExpr, i
          681  +            );
          682  +            zSep = " AND ";
          683  +          }
          684  +          break;
          685  +
          686  +        default:
          687  +          assert( eType==CIDX_CLIST_ALL );
          688  +          zRet = cidxMprintf(pRc, "%z%s(%s) AS i%d", zRet, zSep, p->zExpr, i);
          689  +          zSep = ", ";
          690  +          break;
          691  +      }
          692  +    }
          693  +  }
          694  +
          695  +  return zRet;
          696  +}
          697  +
          698  +/*
          699  +** Generate SQL (in memory obtained from sqlite3_malloc()) that will
          700  +** continue the index scan for zIdxName starting after zAfterKey.
          701  +*/
          702  +int cidxGenerateScanSql(
          703  +  CidxCursor *pCsr,           /* The cursor which needs the new statement */
          704  +  const char *zIdxName,       /* index to be scanned */
          705  +  const char *zAfterKey,      /* start after this key, if not NULL */
          706  +  char **pzSqlOut             /* OUT: Write the generated SQL here */
          707  +){
          708  +  int rc;
          709  +  char *zTab = 0;
          710  +  char *zCurrentKey = 0;
          711  +  char *zOrderBy = 0;
          712  +  char *zSubWhere = 0;
          713  +  char *zSubExpr = 0;
          714  +  char *zSrcList = 0;
          715  +  char **azAfter = 0;
          716  +  CidxIndex *pIdx = 0;
          717  +
          718  +  *pzSqlOut = 0;
          719  +  rc = cidxLookupIndex(pCsr, zIdxName, &pIdx, &zTab);
          720  +
          721  +  zOrderBy = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_ORDERBY);
          722  +  zCurrentKey = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_CURRENT_KEY);
          723  +  zSubWhere = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_SUBWHERE);
          724  +  zSubExpr = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_SUBEXPR);
          725  +  zSrcList = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_ALL);
          726  +
          727  +  if( rc==SQLITE_OK && zAfterKey ){
          728  +    rc = cidxDecodeAfter(pCsr, pIdx->nCol, zAfterKey, &azAfter);
          729  +  }
          730  +
          731  +  if( rc==SQLITE_OK ){
          732  +    if( zAfterKey==0 ){
          733  +      *pzSqlOut = cidxMprintf(&rc,
          734  +          "SELECT (SELECT %s FROM %Q AS t WHERE %s), %s "
          735  +          "FROM (SELECT %s FROM %Q INDEXED BY %Q %s%sORDER BY %s) AS i",
          736  +          zSubExpr, zTab, zSubWhere, zCurrentKey, 
          737  +          zSrcList, zTab, zIdxName, 
          738  +          (pIdx->zWhere ? "WHERE " : ""), (pIdx->zWhere ? pIdx->zWhere : ""),
          739  +          zOrderBy
          740  +      );
          741  +    }else{
          742  +      const char *zSep = "";
          743  +      char *zSql;
          744  +      int i;
          745  +  
          746  +      zSql = cidxMprintf(&rc, 
          747  +          "SELECT (SELECT %s FROM %Q WHERE %s), %s FROM (",
          748  +          zSubExpr, zTab, zSubWhere, zCurrentKey
          749  +      );
          750  +      for(i=pIdx->nCol-1; i>=0; i--){
          751  +        int j;
          752  +        if( pIdx->aCol[i].bDesc && azAfter[i]==0 ) continue;
          753  +        for(j=0; j<2; j++){
          754  +          char *zWhere = cidxWhere(&rc, pIdx->aCol, azAfter, i, j);
          755  +          zSql = cidxMprintf(&rc, "%z"
          756  +              "%sSELECT * FROM ("
          757  +                "SELECT %s FROM %Q INDEXED BY %Q WHERE %s%s%z ORDER BY %s"
          758  +              ")",
          759  +              zSql, zSep, zSrcList, zTab, zIdxName, 
          760  +              pIdx->zWhere ? pIdx->zWhere : "",
          761  +              pIdx->zWhere ? " AND " : "",
          762  +              zWhere, zOrderBy
          763  +          );
          764  +          zSep = " UNION ALL ";
          765  +          if( pIdx->aCol[i].bDesc==0 ) break;
          766  +        }
          767  +      }
          768  +      *pzSqlOut = cidxMprintf(&rc, "%z) AS i", zSql);
          769  +    }
          770  +  }
          771  +
          772  +  sqlite3_free(zTab);
          773  +  sqlite3_free(zCurrentKey);
          774  +  sqlite3_free(zOrderBy);
          775  +  sqlite3_free(zSubWhere);
          776  +  sqlite3_free(zSubExpr);
          777  +  sqlite3_free(zSrcList);
          778  +  cidxFreeIndex(pIdx);
          779  +  sqlite3_free(azAfter);
          780  +  return rc;
          781  +}
          782  +
          783  +
          784  +/* 
          785  +** Position a cursor back to the beginning.
          786  +*/
          787  +static int cidxFilter(
          788  +  sqlite3_vtab_cursor *pCursor, 
          789  +  int idxNum, const char *idxStr,
          790  +  int argc, sqlite3_value **argv
          791  +){
          792  +  int rc = SQLITE_OK;
          793  +  CidxCursor *pCsr = (CidxCursor*)pCursor;
          794  +  const char *zIdxName = 0;
          795  +  const char *zAfterKey = 0;
          796  +
          797  +  sqlite3_free(pCsr->zIdxName);
          798  +  pCsr->zIdxName = 0;
          799  +  sqlite3_free(pCsr->zAfterKey);
          800  +  pCsr->zAfterKey = 0;
          801  +  sqlite3_finalize(pCsr->pStmt);
          802  +  pCsr->pStmt = 0;
          803  +
          804  +  if( argc>0 ){
          805  +    zIdxName = (const char*)sqlite3_value_text(argv[0]);
          806  +    if( argc>1 ){
          807  +      zAfterKey = (const char*)sqlite3_value_text(argv[1]);
          808  +    }
          809  +  }
          810  +
          811  +  if( zIdxName ){
          812  +    char *zSql = 0;
          813  +    pCsr->zIdxName = sqlite3_mprintf("%s", zIdxName);
          814  +    pCsr->zAfterKey = zAfterKey ? sqlite3_mprintf("%s", zAfterKey) : 0;
          815  +    rc = cidxGenerateScanSql(pCsr, zIdxName, zAfterKey, &zSql);
          816  +    if( zSql ){
          817  +      pCsr->pStmt = cidxPrepare(&rc, pCsr, "%z", zSql);
          818  +    }
          819  +  }
          820  +
          821  +  if( pCsr->pStmt ){
          822  +    assert( rc==SQLITE_OK );
          823  +    rc = cidxNext(pCursor);
          824  +  }
          825  +  pCsr->iRowid = 1;
          826  +  return rc;
          827  +}
          828  +
          829  +/* 
          830  +** Return a column value.
          831  +*/
          832  +static int cidxColumn(
          833  +  sqlite3_vtab_cursor *pCursor, 
          834  +  sqlite3_context *ctx, 
          835  +  int iCol
          836  +){
          837  +  CidxCursor *pCsr = (CidxCursor*)pCursor;
          838  +  assert( iCol>=IIC_ERRMSG && iCol<=IIC_SCANNER_SQL );
          839  +  switch( iCol ){
          840  +    case IIC_ERRMSG: {
          841  +      const char *zVal = 0;
          842  +      if( sqlite3_column_type(pCsr->pStmt, 0)==SQLITE_INTEGER ){
          843  +        if( sqlite3_column_int(pCsr->pStmt, 0)==0 ){
          844  +          zVal = "row data mismatch";
          845  +        }
          846  +      }else{
          847  +        zVal = "row missing";
          848  +      }
          849  +      sqlite3_result_text(ctx, zVal, -1, SQLITE_STATIC);
          850  +      break;
          851  +    }
          852  +    case IIC_CURRENT_KEY: {
          853  +      sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pStmt, 1));
          854  +      break;
          855  +    }
          856  +    case IIC_INDEX_NAME: {
          857  +      sqlite3_result_text(ctx, pCsr->zIdxName, -1, SQLITE_TRANSIENT);
          858  +      break;
          859  +    }
          860  +    case IIC_AFTER_KEY: {
          861  +      sqlite3_result_text(ctx, pCsr->zAfterKey, -1, SQLITE_TRANSIENT);
          862  +      break;
          863  +    }
          864  +    case IIC_SCANNER_SQL: {
          865  +      char *zSql = 0;
          866  +      cidxGenerateScanSql(pCsr, pCsr->zIdxName, pCsr->zAfterKey, &zSql);
          867  +      sqlite3_result_text(ctx, zSql, -1, sqlite3_free);
          868  +      break;
          869  +    }
          870  +  }
          871  +  return SQLITE_OK;
          872  +}
          873  +
          874  +/* Return the ROWID for the sqlite_btreeinfo table */
          875  +static int cidxRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
          876  +  CidxCursor *pCsr = (CidxCursor*)pCursor;
          877  +  *pRowid = pCsr->iRowid;
          878  +  return SQLITE_OK;
          879  +}
          880  +
          881  +/*
          882  +** Register the virtual table modules with the database handle passed
          883  +** as the only argument.
          884  +*/
          885  +static int ciInit(sqlite3 *db){
          886  +  static sqlite3_module cidx_module = {
          887  +    0,                            /* iVersion */
          888  +    0,                            /* xCreate */
          889  +    cidxConnect,                  /* xConnect */
          890  +    cidxBestIndex,                /* xBestIndex */
          891  +    cidxDisconnect,               /* xDisconnect */
          892  +    0,                            /* xDestroy */
          893  +    cidxOpen,                     /* xOpen - open a cursor */
          894  +    cidxClose,                    /* xClose - close a cursor */
          895  +    cidxFilter,                   /* xFilter - configure scan constraints */
          896  +    cidxNext,                     /* xNext - advance a cursor */
          897  +    cidxEof,                      /* xEof - check for end of scan */
          898  +    cidxColumn,                   /* xColumn - read data */
          899  +    cidxRowid,                    /* xRowid - read data */
          900  +    0,                            /* xUpdate */
          901  +    0,                            /* xBegin */
          902  +    0,                            /* xSync */
          903  +    0,                            /* xCommit */
          904  +    0,                            /* xRollback */
          905  +    0,                            /* xFindMethod */
          906  +    0,                            /* xRename */
          907  +    0,                            /* xSavepoint */
          908  +    0,                            /* xRelease */
          909  +    0,                            /* xRollbackTo */
          910  +  };
          911  +  return sqlite3_create_module(db, "incremental_index_check", &cidx_module, 0);
          912  +}
          913  +
          914  +/*
          915  +** Extension load function.
          916  +*/
          917  +#ifdef _WIN32
          918  +__declspec(dllexport)
          919  +#endif
          920  +int sqlite3_checkindex_init(
          921  +  sqlite3 *db, 
          922  +  char **pzErrMsg, 
          923  +  const sqlite3_api_routines *pApi
          924  +){
          925  +  SQLITE_EXTENSION_INIT2(pApi);
          926  +  return ciInit(db);
          927  +}

Added ext/repair/sqlite3_checker.c.in.

            1  +/*
            2  +** Read an SQLite database file and analyze its space utilization.  Generate
            3  +** text on standard output.
            4  +*/
            5  +#define TCLSH_INIT_PROC sqlite3_checker_init_proc
            6  +#define SQLITE_ENABLE_DBPAGE_VTAB 1
            7  +#define SQLITE_ENABLE_JSON1 1
            8  +#undef SQLITE_THREADSAFE
            9  +#define SQLITE_THREADSAFE 0
           10  +#undef SQLITE_ENABLE_COLUMN_METADATA
           11  +#define SQLITE_OMIT_DECLTYPE 1
           12  +#define SQLITE_OMIT_DEPRECATED 1
           13  +#define SQLITE_OMIT_PROGRESS_CALLBACK 1
           14  +#define SQLITE_OMIT_SHARED_CACHE 1
           15  +#define SQLITE_DEFAULT_MEMSTATUS 0
           16  +#define SQLITE_MAX_EXPR_DEPTH 0
           17  +INCLUDE sqlite3.c
           18  +INCLUDE $ROOT/src/tclsqlite.c
           19  +INCLUDE $ROOT/ext/misc/btreeinfo.c
           20  +INCLUDE $ROOT/ext/repair/checkindex.c
           21  +INCLUDE $ROOT/ext/repair/checkfreelist.c
           22  +
           23  +/*
           24  +** Decode a pointer to an sqlite3 object.
           25  +*/
           26  +int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
           27  +  struct SqliteDb *p;
           28  +  Tcl_CmdInfo cmdInfo;
           29  +  if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){
           30  +    p = (struct SqliteDb*)cmdInfo.objClientData;
           31  +    *ppDb = p->db;
           32  +    return TCL_OK;
           33  +  }else{
           34  +    *ppDb = 0;
           35  +    return TCL_ERROR;
           36  +  }
           37  +  return TCL_OK;
           38  +}
           39  +
           40  +/*
           41  +**   sqlite3_imposter db main rootpage {CREATE TABLE...}  ;# setup an imposter
           42  +**   sqlite3_imposter db main                             ;# rm all imposters
           43  +*/
           44  +static int sqlite3_imposter(
           45  +  void *clientData,
           46  +  Tcl_Interp *interp,
           47  +  int objc,
           48  +  Tcl_Obj *CONST objv[]
           49  +){
           50  +  sqlite3 *db;
           51  +  const char *zSchema;
           52  +  int iRoot;
           53  +  const char *zSql;
           54  +
           55  +  if( objc!=3 && objc!=5 ){
           56  +    Tcl_WrongNumArgs(interp, 1, objv, "DB SCHEMA [ROOTPAGE SQL]");
           57  +    return TCL_ERROR;
           58  +  }
           59  +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
           60  +  zSchema = Tcl_GetString(objv[2]);
           61  +  if( objc==3 ){
           62  +    sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 0, 1);
           63  +  }else{
           64  +    if( Tcl_GetIntFromObj(interp, objv[3], &iRoot) ) return TCL_ERROR;
           65  +    zSql = Tcl_GetString(objv[4]);
           66  +    sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 1, iRoot);
           67  +    sqlite3_exec(db, zSql, 0, 0, 0);
           68  +    sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 0, 0);
           69  +  }
           70  +  return TCL_OK;
           71  +}
           72  +
           73  +#include <stdio.h>
           74  +
           75  +const char *sqlite3_checker_init_proc(Tcl_Interp *interp){
           76  +  Tcl_CreateObjCommand(interp, "sqlite3_imposter", 
           77  +                       (Tcl_ObjCmdProc*)sqlite3_imposter, 0, 0);
           78  +  sqlite3_auto_extension((void(*)(void))sqlite3_btreeinfo_init);
           79  +  sqlite3_auto_extension((void(*)(void))sqlite3_checkindex_init);
           80  +  sqlite3_auto_extension((void(*)(void))sqlite3_checkfreelist_init);
           81  +  return
           82  +BEGIN_STRING
           83  +INCLUDE $ROOT/ext/repair/sqlite3_checker.tcl
           84  +END_STRING
           85  +;
           86  +}

Added ext/repair/sqlite3_checker.tcl.

            1  +# This TCL script is the main driver script for the sqlite3_checker utility
            2  +# program.
            3  +#
            4  +
            5  +# Special case:
            6  +#
            7  +#      sqlite3_checker --test FILENAME ARGS
            8  +#
            9  +# uses FILENAME in place of this script.
           10  +#
           11  +if {[lindex $argv 0]=="--test" && [llength $argv]>1} {
           12  +  set ::argv0 [lindex $argv 1]
           13  +  set argv [lrange $argv 2 end]
           14  +  source $argv0
           15  +  exit 0
           16  +}
           17  +
           18  +# Emulate a TCL shell
           19  +#
           20  +proc tclsh {} {
           21  +  set line {}
           22  +  while {![eof stdin]} {
           23  +    if {$line!=""} {
           24  +      puts -nonewline "> "
           25  +    } else {
           26  +      puts -nonewline "% "
           27  +    }
           28  +    flush stdout
           29  +    append line [gets stdin]
           30  +    if {[info complete $line]} {
           31  +      if {[catch {uplevel #0 $line} result]} {
           32  +        puts stderr "Error: $result"
           33  +      } elseif {$result!=""} {
           34  +        puts $result
           35  +      }
           36  +      set line {}
           37  +    } else {
           38  +      append line \n
           39  +    }
           40  +  }
           41  +}
           42  +
           43  +# Do an incremental integrity check of a single index
           44  +#
           45  +proc check_index {idxname batchsize bTrace} {
           46  +  set i 0
           47  +  set more 1
           48  +  set nerr 0
           49  +  set pct 00.0
           50  +  set max [db one {SELECT nEntry FROM sqlite_btreeinfo('main')
           51  +                    WHERE name=$idxname}]
           52  +  puts -nonewline "$idxname: $i of $max rows ($pct%)\r"
           53  +  flush stdout
           54  +  if {$bTrace} {
           55  +    set sql {SELECT errmsg, current_key AS key,
           56  +                    CASE WHEN rowid=1 THEN scanner_sql END AS traceOut
           57  +               FROM incremental_index_check($idxname)
           58  +              WHERE after_key=$key
           59  +              LIMIT $batchsize}
           60  +  } else {
           61  +    set sql {SELECT errmsg, current_key AS key, NULL AS traceOut
           62  +               FROM incremental_index_check($idxname)
           63  +              WHERE after_key=$key
           64  +              LIMIT $batchsize}
           65  +  }
           66  +  while {$more} {
           67  +    set more 0
           68  +    db eval $sql {
           69  +      set more 1
           70  +      if {$errmsg!=""} {
           71  +        incr nerr
           72  +        puts "$idxname: key($key): $errmsg"
           73  +      } elseif {$traceOut!=""} {
           74  +        puts "$idxname: $traceOut"
           75  +      }
           76  +      incr i
           77  +      
           78  +    }
           79  +    set x [format {%.1f} [expr {($i*100.0)/$max}]]
           80  +    if {$x!=$pct} {
           81  +      puts -nonewline "$idxname: $i of $max rows ($pct%)\r"
           82  +      flush stdout
           83  +      set pct $x
           84  +    }
           85  +  }
           86  +  puts "$idxname: $nerr errors out of $i entries"
           87  +}
           88  +
           89  +# Print a usage message on standard error, then quit.
           90  +#
           91  +proc usage {} {
           92  +  set argv0 [file rootname [file tail [info nameofexecutable]]]
           93  +  puts stderr "Usage: $argv0 OPTIONS database-filename"
           94  +  puts stderr {
           95  +Do sanity checking on a live SQLite3 database file specified by the
           96  +"database-filename" argument.
           97  +
           98  +Options:
           99  +
          100  +   --batchsize N     Number of rows to check per transaction
          101  +
          102  +   --freelist        Perform a freelist check
          103  +
          104  +   --index NAME      Run a check of the index NAME
          105  +
          106  +   --summary         Print summary information about the database
          107  +
          108  +   --table NAME      Run a check of all indexes for table NAME
          109  +
          110  +   --tclsh           Run the built-in TCL interpreter (for debugging)
          111  +
          112  +   --trace           (Debugging only:) Output trace information on the scan
          113  +
          114  +   --version         Show the version number of SQLite
          115  +}
          116  +  exit 1
          117  +}
          118  +
          119  +set file_to_analyze {}
          120  +append argv {}
          121  +set bFreelistCheck 0
          122  +set bSummary 0
          123  +set zIndex {}
          124  +set zTable {}
          125  +set batchsize 1000
          126  +set bAll 1
          127  +set bTrace 0
          128  +set argc [llength $argv]
          129  +for {set i 0} {$i<$argc} {incr i} {
          130  +  set arg [lindex $argv $i]
          131  +  if {[regexp {^-+tclsh$} $arg]} {
          132  +    tclsh
          133  +    exit 0
          134  +  }
          135  +  if {[regexp {^-+version$} $arg]} {
          136  +    sqlite3 mem :memory:
          137  +    puts [mem one {SELECT sqlite_version()||' '||sqlite_source_id()}]
          138  +    mem close
          139  +    exit 0
          140  +  }
          141  +  if {[regexp {^-+freelist$} $arg]} {
          142  +    set bFreelistCheck 1
          143  +    set bAll 0
          144  +    continue
          145  +  }
          146  +  if {[regexp {^-+summary$} $arg]} {
          147  +    set bSummary 1
          148  +    set bAll 0
          149  +    continue
          150  +  }
          151  +  if {[regexp {^-+trace$} $arg]} {
          152  +    set bTrace 1
          153  +    continue
          154  +  }
          155  +  if {[regexp {^-+batchsize$} $arg]} {
          156  +    incr i
          157  +    if {$i>=$argc} {
          158  +      puts stderr "missing argument on $arg"
          159  +      exit 1
          160  +    }
          161  +    set batchsize [lindex $argv $i]
          162  +    continue
          163  +  }
          164  +  if {[regexp {^-+index$} $arg]} {
          165  +    incr i
          166  +    if {$i>=$argc} {
          167  +      puts stderr "missing argument on $arg"
          168  +      exit 1
          169  +    }
          170  +    set zIndex [lindex $argv $i]
          171  +    set bAll 0
          172  +    continue
          173  +  }
          174  +  if {[regexp {^-+table$} $arg]} {
          175  +    incr i
          176  +    if {$i>=$argc} {
          177  +      puts stderr "missing argument on $arg"
          178  +      exit 1
          179  +    }
          180  +    set zTable [lindex $argv $i]
          181  +    set bAll 0
          182  +    continue
          183  +  }
          184  +  if {[regexp {^-} $arg]} {
          185  +    puts stderr "Unknown option: $arg"
          186  +    usage
          187  +  }
          188  +  if {$file_to_analyze!=""} {
          189  +    usage
          190  +  } else {
          191  +    set file_to_analyze $arg
          192  +  }
          193  +}
          194  +if {$file_to_analyze==""} usage
          195  +
          196  +# If a TCL script is specified on the command-line, then run that
          197  +# script.
          198  +#
          199  +if {[file extension $file_to_analyze]==".tcl"} {
          200  +  source $file_to_analyze
          201  +  exit 0
          202  +}
          203  +
          204  +set root_filename $file_to_analyze
          205  +regexp {^file:(//)?([^?]*)} $file_to_analyze all x1 root_filename
          206  +if {![file exists $root_filename]} {
          207  +  puts stderr "No such file: $root_filename"
          208  +  exit 1
          209  +}
          210  +if {![file readable $root_filename]} {
          211  +  puts stderr "File is not readable: $root_filename"
          212  +  exit 1
          213  +}
          214  +
          215  +if {[catch {sqlite3 db $file_to_analyze} res]} {
          216  +  puts stderr "Cannot open datababase $root_filename: $res"
          217  +  exit 1
          218  +}
          219  +
          220  +if {$bFreelistCheck || $bAll} {
          221  +  puts -nonewline "freelist-check: "
          222  +  flush stdout
          223  +  puts [db one {SELECT checkfreelist('main')}]
          224  +}
          225  +if {$bSummary} {
          226  +  set scale 0
          227  +  set pgsz [db one {PRAGMA page_size}]
          228  +  db eval {SELECT nPage*$pgsz AS sz, name, tbl_name
          229  +             FROM sqlite_btreeinfo
          230  +            WHERE type='index'
          231  +            ORDER BY 1 DESC, name} {
          232  +    if {$scale==0} {
          233  +      if {$sz>10000000} {
          234  +        set scale 1000000.0
          235  +        set unit MB
          236  +      } else {
          237  +        set scale 1000.0
          238  +        set unit KB
          239  +      }
          240  +    }
          241  +    puts [format {%7.1f %s index %s of table %s} \
          242  +            [expr {$sz/$scale}] $unit $name $tbl_name]
          243  +  }
          244  +}
          245  +if {$zIndex!=""} {
          246  +  check_index $zIndex $batchsize $bTrace
          247  +}
          248  +if {$zTable!=""} {
          249  +  foreach idx [db eval {SELECT name FROM sqlite_master
          250  +                         WHERE type='index' AND rootpage>0
          251  +                           AND tbl_name=$zTable}] {
          252  +    check_index $idx $batchsize $bTrace
          253  +  }
          254  +}
          255  +if {$bAll} {
          256  +  set allidx [db eval {SELECT name FROM sqlite_btreeinfo('main')
          257  +                        WHERE type='index' AND rootpage>0
          258  +                        ORDER BY nEntry}]
          259  +  foreach idx $allidx {
          260  +    check_index $idx $batchsize $bTrace
          261  +  }
          262  +}

Added ext/repair/test/README.md.

            1  +To run these tests, first build sqlite3_checker:
            2  +
            3  +
            4  +>     make sqlite3_checker
            5  +
            6  +
            7  +Then run the "test.tcl" script using:
            8  +
            9  +
           10  +>     ./sqlite3_checker --test $path/test.tcl
           11  +
           12  +
           13  +Optionally add the full pathnames of individual *.test modules

Added ext/repair/test/checkfreelist01.test.

            1  +# 2017-10-11
            2  +
            3  +set testprefix checkfreelist
            4  +
            5  +do_execsql_test 1.0 {
            6  +  PRAGMA page_size=1024;
            7  +  CREATE TABLE t1(a, b);
            8  +}
            9  +
           10  +do_execsql_test 1.2 { SELECT checkfreelist('main') } {ok}
           11  +do_execsql_test 1.3 {
           12  +  WITH s(i) AS (
           13  +    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10000
           14  +  )
           15  +  INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM s;
           16  +  DELETE FROM t1 WHERE rowid%3;
           17  +  PRAGMA freelist_count;
           18  +} {6726}
           19  +
           20  +do_execsql_test 1.4 { SELECT checkfreelist('main') } {ok}
           21  +do_execsql_test 1.5 {
           22  +  WITH freelist_trunk(i, d, n) AS (
           23  +    SELECT 1, NULL, sqlite_readint32(data, 32) FROM sqlite_dbpage WHERE pgno=1
           24  +      UNION ALL
           25  +    SELECT n, data, sqlite_readint32(data) 
           26  +    FROM freelist_trunk, sqlite_dbpage WHERE pgno=n
           27  +  )
           28  +  SELECT i FROM freelist_trunk WHERE i!=1;
           29  +} {
           30  +  10009 9715 9343 8969 8595 8222 7847 7474 7102 6727 6354 5982 5608 5234
           31  +  4860 4487 4112 3740 3367 2992 2619 2247 1872 1499 1125 752 377 5
           32  +}
           33  +
           34  +do_execsql_test 1.6 { SELECT checkfreelist('main') } {ok}
           35  +
           36  +proc set_int {blob idx newval} {
           37  +  binary scan $blob I* ints
           38  +  lset ints $idx $newval
           39  +  binary format I* $ints
           40  +}
           41  +db func set_int set_int
           42  +
           43  +proc get_int {blob idx} {
           44  +  binary scan $blob I* ints
           45  +  lindex $ints $idx
           46  +}
           47  +db func get_int get_int
           48  +
           49  +do_execsql_test 1.7 {
           50  +  BEGIN;
           51  +    UPDATE sqlite_dbpage 
           52  +      SET data = set_int(data, 1, get_int(data, 1)-1) 
           53  +      WHERE pgno=4860;
           54  +    SELECT checkfreelist('main');
           55  +  ROLLBACK;
           56  +} {{free-list count mismatch: actual=6725 header=6726}}
           57  +
           58  +do_execsql_test 1.8 {
           59  +  BEGIN;
           60  +    UPDATE sqlite_dbpage 
           61  +      SET data = set_int(data, 5, (SELECT * FROM pragma_page_count)+1)
           62  +      WHERE pgno=4860;
           63  +    SELECT checkfreelist('main');
           64  +  ROLLBACK;
           65  +} {{leaf page 10092 is out of range (child 3 of trunk page 4860)}}
           66  +
           67  +do_execsql_test 1.9 {
           68  +  BEGIN;
           69  +    UPDATE sqlite_dbpage 
           70  +      SET data = set_int(data, 5, 0)
           71  +      WHERE pgno=4860;
           72  +    SELECT checkfreelist('main');
           73  +  ROLLBACK;
           74  +} {{leaf page 0 is out of range (child 3 of trunk page 4860)}}
           75  +
           76  +do_execsql_test 1.10 {
           77  +  BEGIN;
           78  +    UPDATE sqlite_dbpage 
           79  +      SET data = set_int(data, get_int(data, 1)+1, 0)
           80  +      WHERE pgno=5;
           81  +    SELECT checkfreelist('main');
           82  +  ROLLBACK;
           83  +} {{leaf page 0 is out of range (child 247 of trunk page 5)}}
           84  +
           85  +do_execsql_test 1.11 {
           86  +  BEGIN;
           87  +    UPDATE sqlite_dbpage 
           88  +      SET data = set_int(data, 1, 249)
           89  +      WHERE pgno=5;
           90  +    SELECT checkfreelist('main');
           91  +  ROLLBACK;
           92  +} {{leaf count out of range (249) on trunk page 5}}

Added ext/repair/test/checkindex01.test.

            1  +# 2017-10-11
            2  +#
            3  +set testprefix checkindex
            4  +
            5  +do_execsql_test 1.0 {
            6  +  CREATE TABLE t1(a, b);
            7  +  CREATE INDEX i1 ON t1(a);
            8  +  INSERT INTO t1 VALUES('one', 2);
            9  +  INSERT INTO t1 VALUES('two', 4);
           10  +  INSERT INTO t1 VALUES('three', 6);
           11  +  INSERT INTO t1 VALUES('four', 8);
           12  +  INSERT INTO t1 VALUES('five', 10);
           13  +
           14  +  CREATE INDEX i2 ON t1(a DESC);
           15  +} {}
           16  +
           17  +proc incr_index_check {idx nStep} {
           18  +  set Q {
           19  +    SELECT errmsg, current_key FROM incremental_index_check($idx, $after)
           20  +    LIMIT $nStep
           21  +  }
           22  +
           23  +  set res [list]
           24  +  while {1} {
           25  +    unset -nocomplain current_key
           26  +    set res1 [db eval $Q]
           27  +    if {[llength $res1]==0} break
           28  +    set res [concat $res $res1]
           29  +    set after [lindex $res end]
           30  +  }
           31  +
           32  +  return $res
           33  +}
           34  +
           35  +proc do_index_check_test {tn idx res} {
           36  +  uplevel [list do_execsql_test $tn.1 "
           37  +    SELECT errmsg, current_key FROM incremental_index_check('$idx');
           38  +  " $res]
           39  +
           40  +  uplevel [list do_test $tn.2 "incr_index_check $idx 1" [list {*}$res]]
           41  +  uplevel [list do_test $tn.3 "incr_index_check $idx 2" [list {*}$res]]
           42  +  uplevel [list do_test $tn.4 "incr_index_check $idx 5" [list {*}$res]]
           43  +}
           44  +
           45  +
           46  +do_execsql_test 1.2.1 {
           47  +  SELECT rowid, errmsg IS NULL, current_key FROM incremental_index_check('i1');
           48  +} {
           49  +  1 1 'five',5
           50  +  2 1 'four',4
           51  +  3 1 'one',1
           52  +  4 1 'three',3
           53  +  5 1 'two',2
           54  +}
           55  +do_execsql_test 1.2.2 {
           56  +  SELECT errmsg IS NULL, current_key, index_name, after_key, scanner_sql
           57  +    FROM incremental_index_check('i1') LIMIT 1;
           58  +} {
           59  +  1
           60  +  'five',5
           61  +  i1
           62  +  {}
           63  +  {SELECT (SELECT a IS i.i0 FROM 't1' AS t WHERE "rowid" COLLATE BINARY IS i.i1), quote(i0)||','||quote(i1) FROM (SELECT (a) AS i0, ("rowid" COLLATE BINARY) AS i1 FROM 't1' INDEXED BY 'i1' ORDER BY 1,2) AS i}
           64  +}
           65  +
           66  +do_index_check_test 1.3 i1 {
           67  +  {} 'five',5
           68  +  {} 'four',4
           69  +  {} 'one',1
           70  +  {} 'three',3
           71  +  {} 'two',2
           72  +}
           73  +
           74  +do_index_check_test 1.4 i2 {
           75  +  {} 'two',2
           76  +  {} 'three',3
           77  +  {} 'one',1
           78  +  {} 'four',4
           79  +  {} 'five',5
           80  +}
           81  +
           82  +do_test 1.5 {
           83  +  set tblroot [db one { SELECT rootpage FROM sqlite_master WHERE name='t1' }]
           84  +  sqlite3_imposter db main $tblroot {CREATE TABLE xt1(a,b)}
           85  +  db eval {
           86  +    UPDATE xt1 SET a='six' WHERE rowid=3;
           87  +    DELETE FROM xt1 WHERE rowid = 5;
           88  +  }
           89  +  sqlite3_imposter db main
           90  +} {}
           91  +
           92  +do_index_check_test 1.6 i1 {
           93  +  {row missing} 'five',5
           94  +  {} 'four',4
           95  +  {} 'one',1
           96  +  {row data mismatch} 'three',3
           97  +  {} 'two',2
           98  +}
           99  +
          100  +do_index_check_test 1.7 i2 {
          101  +  {} 'two',2
          102  +  {row data mismatch} 'three',3
          103  +  {} 'one',1
          104  +  {} 'four',4
          105  +  {row missing} 'five',5
          106  +}
          107  +
          108  +#--------------------------------------------------------------------------
          109  +do_execsql_test 2.0 {
          110  +
          111  +  CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c, d);
          112  +
          113  +  INSERT INTO t2 VALUES(1, NULL, 1, 1);
          114  +  INSERT INTO t2 VALUES(2, 1, NULL, 1);
          115  +  INSERT INTO t2 VALUES(3, 1, 1, NULL);
          116  +
          117  +  INSERT INTO t2 VALUES(4, 2, 2, 1);
          118  +  INSERT INTO t2 VALUES(5, 2, 2, 2);
          119  +  INSERT INTO t2 VALUES(6, 2, 2, 3);
          120  +
          121  +  INSERT INTO t2 VALUES(7, 2, 2, 1);
          122  +  INSERT INTO t2 VALUES(8, 2, 2, 2);
          123  +  INSERT INTO t2 VALUES(9, 2, 2, 3);
          124  +
          125  +  CREATE INDEX i3 ON t2(b, c, d);
          126  +  CREATE INDEX i4 ON t2(b DESC, c DESC, d DESC);
          127  +  CREATE INDEX i5 ON t2(d, c DESC, b);
          128  +} {}
          129  +
          130  +do_index_check_test 2.1 i3 {
          131  +  {} NULL,1,1,1 
          132  +  {} 1,NULL,1,2 
          133  +  {} 1,1,NULL,3 
          134  +  {} 2,2,1,4 
          135  +  {} 2,2,1,7 
          136  +  {} 2,2,2,5
          137  +  {} 2,2,2,8 
          138  +  {} 2,2,3,6 
          139  +  {} 2,2,3,9
          140  +}
          141  +
          142  +do_index_check_test 2.2 i4 {
          143  +  {} 2,2,3,6 
          144  +  {} 2,2,3,9
          145  +  {} 2,2,2,5
          146  +  {} 2,2,2,8 
          147  +  {} 2,2,1,4 
          148  +  {} 2,2,1,7 
          149  +  {} 1,1,NULL,3 
          150  +  {} 1,NULL,1,2 
          151  +  {} NULL,1,1,1 
          152  +}
          153  +
          154  +do_index_check_test 2.3 i5 {
          155  +  {} NULL,1,1,3 
          156  +  {} 1,2,2,4 
          157  +  {} 1,2,2,7 
          158  +  {} 1,1,NULL,1 
          159  +  {} 1,NULL,1,2 
          160  +  {} 2,2,2,5 
          161  +  {} 2,2,2,8 
          162  +  {} 3,2,2,6 
          163  +  {} 3,2,2,9
          164  +}
          165  +
          166  +#--------------------------------------------------------------------------
          167  +do_execsql_test 3.0 {
          168  +
          169  +  CREATE TABLE t3(w, x, y, z PRIMARY KEY) WITHOUT ROWID;
          170  +  CREATE INDEX t3wxy ON t3(w, x, y);
          171  +  CREATE INDEX t3wxy2 ON t3(w DESC, x DESC, y DESC);
          172  +
          173  +  INSERT INTO t3 VALUES(NULL, NULL, NULL, 1);
          174  +  INSERT INTO t3 VALUES(NULL, NULL, NULL, 2);
          175  +  INSERT INTO t3 VALUES(NULL, NULL, NULL, 3);
          176  +
          177  +  INSERT INTO t3 VALUES('a', NULL, NULL, 4);
          178  +  INSERT INTO t3 VALUES('a', NULL, NULL, 5);
          179  +  INSERT INTO t3 VALUES('a', NULL, NULL, 6);
          180  +
          181  +  INSERT INTO t3 VALUES('a', 'b', NULL, 7);
          182  +  INSERT INTO t3 VALUES('a', 'b', NULL, 8);
          183  +  INSERT INTO t3 VALUES('a', 'b', NULL, 9);
          184  +
          185  +} {}
          186  +
          187  +do_index_check_test 3.1 t3wxy {
          188  +  {} NULL,NULL,NULL,1 {} NULL,NULL,NULL,2 {} NULL,NULL,NULL,3 
          189  +  {} 'a',NULL,NULL,4  {} 'a',NULL,NULL,5  {} 'a',NULL,NULL,6 
          190  +  {} 'a','b',NULL,7   {} 'a','b',NULL,8   {} 'a','b',NULL,9 
          191  +}
          192  +do_index_check_test 3.2 t3wxy2 {
          193  +  {} 'a','b',NULL,7   {} 'a','b',NULL,8   {} 'a','b',NULL,9 
          194  +  {} 'a',NULL,NULL,4  {} 'a',NULL,NULL,5  {} 'a',NULL,NULL,6 
          195  +  {} NULL,NULL,NULL,1 {} NULL,NULL,NULL,2 {} NULL,NULL,NULL,3 
          196  +}
          197  +
          198  +#--------------------------------------------------------------------------
          199  +# Test with an index that uses non-default collation sequences.
          200  +#
          201  +do_execsql_test 4.0 {
          202  +  CREATE TABLE t4(a INTEGER PRIMARY KEY, c1 TEXT, c2 TEXT);
          203  +  INSERT INTO t4 VALUES(1, 'aaa', 'bbb');
          204  +  INSERT INTO t4 VALUES(2, 'AAA', 'CCC');
          205  +  INSERT INTO t4 VALUES(3, 'aab', 'ddd');
          206  +  INSERT INTO t4 VALUES(4, 'AAB', 'EEE');
          207  +
          208  +  CREATE INDEX t4cc ON t4(c1 COLLATE nocase, c2 COLLATE nocase);
          209  +}
          210  +
          211  +do_index_check_test 4.1 t4cc {
          212  +  {} 'aaa','bbb',1 
          213  +  {} 'AAA','CCC',2 
          214  +  {} 'aab','ddd',3 
          215  +  {} 'AAB','EEE',4
          216  +}
          217  +
          218  +do_test 4.2 {
          219  +  set tblroot [db one { SELECT rootpage FROM sqlite_master WHERE name='t4' }]
          220  +  sqlite3_imposter db main $tblroot \
          221  +     {CREATE TABLE xt4(a INTEGER PRIMARY KEY, c1 TEXT, c2 TEXT)}
          222  +
          223  +  db eval {
          224  +    UPDATE xt4 SET c1='hello' WHERE rowid=2;
          225  +    DELETE FROM xt4 WHERE rowid = 3;
          226  +  }
          227  +  sqlite3_imposter db main
          228  +} {}
          229  +
          230  +do_index_check_test 4.3 t4cc {
          231  +  {} 'aaa','bbb',1 
          232  +  {row data mismatch} 'AAA','CCC',2 
          233  +  {row missing} 'aab','ddd',3 
          234  +  {} 'AAB','EEE',4
          235  +}
          236  +
          237  +#--------------------------------------------------------------------------
          238  +# Test an index on an expression.
          239  +#
          240  +do_execsql_test 5.0 {
          241  +  CREATE TABLE t5(x INTEGER PRIMARY KEY, y TEXT, UNIQUE(y));
          242  +  INSERT INTO t5 VALUES(1, '{"x":1, "y":1}');
          243  +  INSERT INTO t5 VALUES(2, '{"x":2, "y":2}');
          244  +  INSERT INTO t5 VALUES(3, '{"x":3, "y":3}');
          245  +  INSERT INTO t5 VALUES(4, '{"w":4, "z":4}');
          246  +  INSERT INTO t5 VALUES(5, '{"x":5, "y":5}');
          247  +
          248  +  CREATE INDEX t5x ON t5( json_extract(y, '$.x') );
          249  +  CREATE INDEX t5y ON t5( json_extract(y, '$.y') DESC );
          250  +}
          251  +
          252  +do_index_check_test 5.1.1 t5x {
          253  +  {} NULL,4 {} 1,1 {} 2,2 {} 3,3 {} 5,5
          254  +}
          255  +
          256  +do_index_check_test 5.1.2 t5y {
          257  +  {} 5,5 {} 3,3 {} 2,2 {} 1,1 {} NULL,4
          258  +}
          259  +
          260  +do_index_check_test 5.1.3 sqlite_autoindex_t5_1 {
          261  +  {} {'{"w":4, "z":4}',4} 
          262  +  {} {'{"x":1, "y":1}',1} 
          263  +  {} {'{"x":2, "y":2}',2} 
          264  +  {} {'{"x":3, "y":3}',3} 
          265  +  {} {'{"x":5, "y":5}',5}
          266  +}
          267  +
          268  +do_test 5.2 {
          269  +  set tblroot [db one { SELECT rootpage FROM sqlite_master WHERE name='t5' }]
          270  +  sqlite3_imposter db main $tblroot \
          271  +      {CREATE TABLE xt5(a INTEGER PRIMARY KEY, c1 TEXT);}
          272  +  db eval {
          273  +    UPDATE xt5 SET c1='{"x":22, "y":11}' WHERE rowid=1;
          274  +    DELETE FROM xt5 WHERE rowid = 4;
          275  +  }
          276  +  sqlite3_imposter db main
          277  +} {}
          278  +
          279  +do_index_check_test 5.3.1 t5x {
          280  +  {row missing} NULL,4 
          281  +  {row data mismatch} 1,1 
          282  +  {} 2,2 
          283  +  {} 3,3 
          284  +  {} 5,5
          285  +}
          286  +
          287  +do_index_check_test 5.3.2 sqlite_autoindex_t5_1 {
          288  +  {row missing} {'{"w":4, "z":4}',4} 
          289  +  {row data mismatch} {'{"x":1, "y":1}',1} 
          290  +  {} {'{"x":2, "y":2}',2} 
          291  +  {} {'{"x":3, "y":3}',3} 
          292  +  {} {'{"x":5, "y":5}',5}
          293  +}
          294  +
          295  +#-------------------------------------------------------------------------
          296  +#
          297  +do_execsql_test 6.0 {
          298  +  CREATE TABLE t6(x INTEGER PRIMARY KEY, y, z);
          299  +  CREATE INDEX t6x1 ON t6(y, /* one,two,three */ z);
          300  +  CREATE INDEX t6x2 ON t6(z, -- hello,world,
          301  +  y);
          302  +
          303  +  CREATE INDEX t6x3 ON t6(z -- hello,world
          304  +  , y);
          305  +
          306  +  INSERT INTO t6 VALUES(1, 2, 3);
          307  +  INSERT INTO t6 VALUES(4, 5, 6);
          308  +}
          309  +
          310  +do_index_check_test 6.1 t6x1 {
          311  +  {} 2,3,1 
          312  +  {} 5,6,4
          313  +}
          314  +do_index_check_test 6.2 t6x2 {
          315  +  {} 3,2,1 
          316  +  {} 6,5,4
          317  +}
          318  +do_index_check_test 6.2 t6x3 {
          319  +  {} 3,2,1 
          320  +  {} 6,5,4
          321  +}
          322  +
          323  +#-------------------------------------------------------------------------
          324  +#
          325  +do_execsql_test 7.0 {
          326  +  CREATE TABLE t7(x INTEGER PRIMARY KEY, y, z);
          327  +  INSERT INTO t7 VALUES(1, 1, 1);
          328  +  INSERT INTO t7 VALUES(2, 2, 0);
          329  +  INSERT INTO t7 VALUES(3, 3, 1);
          330  +  INSERT INTO t7 VALUES(4, 4, 0);
          331  +
          332  +  CREATE INDEX t7i1 ON t7(y) WHERE z=1;
          333  +  CREATE INDEX t7i2 ON t7(y) /* hello,world */ WHERE z=1;
          334  +  CREATE INDEX t7i3 ON t7(y) WHERE -- yep 
          335  +  z=1;
          336  +  CREATE INDEX t7i4 ON t7(y) WHERE z=1 -- yep;
          337  +}
          338  +do_index_check_test 7.1 t7i1 {
          339  +  {} 1,1 {} 3,3
          340  +}
          341  +do_index_check_test 7.2 t7i2 {
          342  +  {} 1,1 {} 3,3
          343  +}
          344  +do_index_check_test 7.3 t7i3 {
          345  +  {} 1,1 {} 3,3
          346  +}
          347  +do_index_check_test 7.4 t7i4 {
          348  +  {} 1,1 {} 3,3
          349  +}
          350  +
          351  +

Added ext/repair/test/test.tcl.

            1  +# Run this script using
            2  +#
            3  +#       sqlite3_checker --test $thisscript $testscripts
            4  +#
            5  +# The $testscripts argument is optional.  If omitted, all *.test files
            6  +# in the same directory as $thisscript are run.
            7  +#
            8  +set NTEST 0
            9  +set NERR  0
           10  +
           11  +
           12  +# Invoke the do_test procedure to run a single test
           13  +#
           14  +# The $expected parameter is the expected result.  The result is the return
           15  +# value from the last TCL command in $cmd.
           16  +#
           17  +# Normally, $expected must match exactly.  But if $expected is of the form
           18  +# "/regexp/" then regular expression matching is used.  If $expected is
           19  +# "~/regexp/" then the regular expression must NOT match.  If $expected is
           20  +# of the form "#/value-list/" then each term in value-list must be numeric
           21  +# and must approximately match the corresponding numeric term in $result.
           22  +# Values must match within 10%.  Or if the $expected term is A..B then the
           23  +# $result term must be in between A and B.
           24  +#
           25  +proc do_test {name cmd expected} {
           26  +  if {[info exists ::testprefix]} {
           27  +    set name "$::testprefix$name"
           28  +  }
           29  +
           30  +  incr ::NTEST
           31  +  puts -nonewline $name...
           32  +  flush stdout
           33  +
           34  +  if {[catch {uplevel #0 "$cmd;\n"} result]} {
           35  +    puts -nonewline $name...
           36  +    puts "\nError: $result"
           37  +    incr ::NERR
           38  +  } else {
           39  +    set ok [expr {[string compare $result $expected]==0}]
           40  +    if {!$ok} {
           41  +      puts "\n!  $name expected: \[$expected\]\n! $name got:      \[$result\]"
           42  +      incr ::NERR
           43  +    } else {
           44  +      puts " Ok"
           45  +    }
           46  +  }
           47  +  flush stdout
           48  +}
           49  +
           50  +#
           51  +#   do_execsql_test TESTNAME SQL RES
           52  +#
           53  +proc do_execsql_test {testname sql {result {}}} {
           54  +  uplevel [list do_test $testname [list db eval $sql] [list {*}$result]]
           55  +}
           56  +
           57  +if {[llength $argv]==0} {
           58  +  set dir [file dirname $argv0]
           59  +  set argv [glob -nocomplain $dir/*.test]
           60  +}
           61  +foreach testfile $argv {
           62  +  file delete -force test.db
           63  +  sqlite3 db test.db
           64  +  source $testfile
           65  +  catch {db close}
           66  +}
           67  +puts "$NERR errors out of $NTEST tests"

Changes to ext/rtree/rtree.c.

   206    206   #define RTREE_REINSERT(p) RTREE_MINCELLS(p)
   207    207   #define RTREE_MAXCELLS 51
   208    208   
   209    209   /*
   210    210   ** The smallest possible node-size is (512-64)==448 bytes. And the largest
   211    211   ** supported cell size is 48 bytes (8 byte rowid + ten 4 byte coordinates).
   212    212   ** Therefore all non-root nodes must contain at least 3 entries. Since 
   213         -** 2^40 is greater than 2^64, an r-tree structure always has a depth of
          213  +** 3^40 is greater than 2^64, an r-tree structure always has a depth of
   214    214   ** 40 or less.
   215    215   */
   216    216   #define RTREE_MAX_DEPTH 40
   217    217   
   218    218   
   219    219   /*
   220    220   ** Number of entries in the cursor RtreeNode cache.  The first entry is
................................................................................
  3604   3604     ){
  3605   3605       sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1); 
  3606   3606     }else{
  3607   3607       u8 *zBlob = (u8 *)sqlite3_value_blob(apArg[0]);
  3608   3608       sqlite3_result_int(ctx, readInt16(zBlob));
  3609   3609     }
  3610   3610   }
         3611  +
         3612  +/*
         3613  +** Context object passed between the various routines that make up the
         3614  +** implementation of integrity-check function rtreecheck().
         3615  +*/
         3616  +typedef struct RtreeCheck RtreeCheck;
         3617  +struct RtreeCheck {
         3618  +  sqlite3 *db;                    /* Database handle */
         3619  +  const char *zDb;                /* Database containing rtree table */
         3620  +  const char *zTab;               /* Name of rtree table */
         3621  +  int bInt;                       /* True for rtree_i32 table */
         3622  +  int nDim;                       /* Number of dimensions for this rtree tbl */
         3623  +  sqlite3_stmt *pGetNode;         /* Statement used to retrieve nodes */
         3624  +  sqlite3_stmt *aCheckMapping[2]; /* Statements to query %_parent/%_rowid */
         3625  +  int nLeaf;                      /* Number of leaf cells in table */
         3626  +  int nNonLeaf;                   /* Number of non-leaf cells in table */
         3627  +  int rc;                         /* Return code */
         3628  +  char *zReport;                  /* Message to report */
         3629  +  int nErr;                       /* Number of lines in zReport */
         3630  +};
         3631  +
         3632  +#define RTREE_CHECK_MAX_ERROR 100
         3633  +
         3634  +/*
         3635  +** Reset SQL statement pStmt. If the sqlite3_reset() call returns an error,
         3636  +** and RtreeCheck.rc==SQLITE_OK, set RtreeCheck.rc to the error code.
         3637  +*/
         3638  +static void rtreeCheckReset(RtreeCheck *pCheck, sqlite3_stmt *pStmt){
         3639  +  int rc = sqlite3_reset(pStmt);
         3640  +  if( pCheck->rc==SQLITE_OK ) pCheck->rc = rc;
         3641  +}
         3642  +
         3643  +/*
         3644  +** The second and subsequent arguments to this function are a format string
         3645  +** and printf style arguments. This function formats the string and attempts
         3646  +** to compile it as an SQL statement.
         3647  +**
         3648  +** If successful, a pointer to the new SQL statement is returned. Otherwise,
         3649  +** NULL is returned and an error code left in RtreeCheck.rc.
         3650  +*/
         3651  +static sqlite3_stmt *rtreeCheckPrepare(
         3652  +  RtreeCheck *pCheck,             /* RtreeCheck object */
         3653  +  const char *zFmt, ...           /* Format string and trailing args */
         3654  +){
         3655  +  va_list ap;
         3656  +  char *z;
         3657  +  sqlite3_stmt *pRet = 0;
         3658  +
         3659  +  va_start(ap, zFmt);
         3660  +  z = sqlite3_vmprintf(zFmt, ap);
         3661  +
         3662  +  if( pCheck->rc==SQLITE_OK ){
         3663  +    if( z==0 ){
         3664  +      pCheck->rc = SQLITE_NOMEM;
         3665  +    }else{
         3666  +      pCheck->rc = sqlite3_prepare_v2(pCheck->db, z, -1, &pRet, 0);
         3667  +    }
         3668  +  }
         3669  +
         3670  +  sqlite3_free(z);
         3671  +  va_end(ap);
         3672  +  return pRet;
         3673  +}
         3674  +
         3675  +/*
         3676  +** The second and subsequent arguments to this function are a printf()
         3677  +** style format string and arguments. This function formats the string and
         3678  +** appends it to the report being accumuated in pCheck.
         3679  +*/
         3680  +static void rtreeCheckAppendMsg(RtreeCheck *pCheck, const char *zFmt, ...){
         3681  +  va_list ap;
         3682  +  va_start(ap, zFmt);
         3683  +  if( pCheck->rc==SQLITE_OK && pCheck->nErr<RTREE_CHECK_MAX_ERROR ){
         3684  +    char *z = sqlite3_vmprintf(zFmt, ap);
         3685  +    if( z==0 ){
         3686  +      pCheck->rc = SQLITE_NOMEM;
         3687  +    }else{
         3688  +      pCheck->zReport = sqlite3_mprintf("%z%s%z", 
         3689  +          pCheck->zReport, (pCheck->zReport ? "\n" : ""), z
         3690  +      );
         3691  +      if( pCheck->zReport==0 ){
         3692  +        pCheck->rc = SQLITE_NOMEM;
         3693  +      }
         3694  +    }
         3695  +    pCheck->nErr++;
         3696  +  }
         3697  +  va_end(ap);
         3698  +}
         3699  +
         3700  +/*
         3701  +** This function is a no-op if there is already an error code stored
         3702  +** in the RtreeCheck object indicated by the first argument. NULL is
         3703  +** returned in this case.
         3704  +**
         3705  +** Otherwise, the contents of rtree table node iNode are loaded from
         3706  +** the database and copied into a buffer obtained from sqlite3_malloc().
         3707  +** If no error occurs, a pointer to the buffer is returned and (*pnNode)
         3708  +** is set to the size of the buffer in bytes.
         3709  +**
         3710  +** Or, if an error does occur, NULL is returned and an error code left
         3711  +** in the RtreeCheck object. The final value of *pnNode is undefined in
         3712  +** this case.
         3713  +*/
         3714  +static u8 *rtreeCheckGetNode(RtreeCheck *pCheck, i64 iNode, int *pnNode){
         3715  +  u8 *pRet = 0;                   /* Return value */
         3716  +
         3717  +  assert( pCheck->rc==SQLITE_OK );
         3718  +  if( pCheck->pGetNode==0 ){
         3719  +    pCheck->pGetNode = rtreeCheckPrepare(pCheck,
         3720  +        "SELECT data FROM %Q.'%q_node' WHERE nodeno=?", 
         3721  +        pCheck->zDb, pCheck->zTab
         3722  +    );
         3723  +  }
         3724  +
         3725  +  if( pCheck->rc==SQLITE_OK ){
         3726  +    sqlite3_bind_int64(pCheck->pGetNode, 1, iNode);
         3727  +    if( sqlite3_step(pCheck->pGetNode)==SQLITE_ROW ){
         3728  +      int nNode = sqlite3_column_bytes(pCheck->pGetNode, 0);
         3729  +      const u8 *pNode = (const u8*)sqlite3_column_blob(pCheck->pGetNode, 0);
         3730  +      pRet = sqlite3_malloc(nNode);
         3731  +      if( pRet==0 ){
         3732  +        pCheck->rc = SQLITE_NOMEM;
         3733  +      }else{
         3734  +        memcpy(pRet, pNode, nNode);
         3735  +        *pnNode = nNode;
         3736  +      }
         3737  +    }
         3738  +    rtreeCheckReset(pCheck, pCheck->pGetNode);
         3739  +    if( pCheck->rc==SQLITE_OK && pRet==0 ){
         3740  +      rtreeCheckAppendMsg(pCheck, "Node %lld missing from database", iNode);
         3741  +    }
         3742  +  }
         3743  +
         3744  +  return pRet;
         3745  +}
         3746  +
         3747  +/*
         3748  +** This function is used to check that the %_parent (if bLeaf==0) or %_rowid
         3749  +** (if bLeaf==1) table contains a specified entry. The schemas of the
         3750  +** two tables are:
         3751  +**
         3752  +**   CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER)
         3753  +**   CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER)
         3754  +**
         3755  +** In both cases, this function checks that there exists an entry with
         3756  +** IPK value iKey and the second column set to iVal.
         3757  +**
         3758  +*/
         3759  +static void rtreeCheckMapping(
         3760  +  RtreeCheck *pCheck,             /* RtreeCheck object */
         3761  +  int bLeaf,                      /* True for a leaf cell, false for interior */
         3762  +  i64 iKey,                       /* Key for mapping */
         3763  +  i64 iVal                        /* Expected value for mapping */
         3764  +){
         3765  +  int rc;
         3766  +  sqlite3_stmt *pStmt;
         3767  +  const char *azSql[2] = {
         3768  +    "SELECT parentnode FROM %Q.'%q_parent' WHERE nodeno=?",
         3769  +    "SELECT nodeno FROM %Q.'%q_rowid' WHERE rowid=?"
         3770  +  };
         3771  +
         3772  +  assert( bLeaf==0 || bLeaf==1 );
         3773  +  if( pCheck->aCheckMapping[bLeaf]==0 ){
         3774  +    pCheck->aCheckMapping[bLeaf] = rtreeCheckPrepare(pCheck,
         3775  +        azSql[bLeaf], pCheck->zDb, pCheck->zTab
         3776  +    );
         3777  +  }
         3778  +  if( pCheck->rc!=SQLITE_OK ) return;
         3779  +
         3780  +  pStmt = pCheck->aCheckMapping[bLeaf];
         3781  +  sqlite3_bind_int64(pStmt, 1, iKey);
         3782  +  rc = sqlite3_step(pStmt);
         3783  +  if( rc==SQLITE_DONE ){
         3784  +    rtreeCheckAppendMsg(pCheck, "Mapping (%lld -> %lld) missing from %s table",
         3785  +        iKey, iVal, (bLeaf ? "%_rowid" : "%_parent")
         3786  +    );
         3787  +  }else if( rc==SQLITE_ROW ){
         3788  +    i64 ii = sqlite3_column_int64(pStmt, 0);
         3789  +    if( ii!=iVal ){
         3790  +      rtreeCheckAppendMsg(pCheck, 
         3791  +          "Found (%lld -> %lld) in %s table, expected (%lld -> %lld)",
         3792  +          iKey, ii, (bLeaf ? "%_rowid" : "%_parent"), iKey, iVal
         3793  +      );
         3794  +    }
         3795  +  }
         3796  +  rtreeCheckReset(pCheck, pStmt);
         3797  +}
         3798  +
         3799  +/*
         3800  +** Argument pCell points to an array of coordinates stored on an rtree page.
         3801  +** This function checks that the coordinates are internally consistent (no
         3802  +** x1>x2 conditions) and adds an error message to the RtreeCheck object
         3803  +** if they are not.
         3804  +**
         3805  +** Additionally, if pParent is not NULL, then it is assumed to point to
         3806  +** the array of coordinates on the parent page that bound the page 
         3807  +** containing pCell. In this case it is also verified that the two
         3808  +** sets of coordinates are mutually consistent and an error message added
         3809  +** to the RtreeCheck object if they are not.
         3810  +*/
         3811  +static void rtreeCheckCellCoord(
         3812  +  RtreeCheck *pCheck, 
         3813  +  i64 iNode,                      /* Node id to use in error messages */
         3814  +  int iCell,                      /* Cell number to use in error messages */
         3815  +  u8 *pCell,                      /* Pointer to cell coordinates */
         3816  +  u8 *pParent                     /* Pointer to parent coordinates */
         3817  +){
         3818  +  RtreeCoord c1, c2;
         3819  +  RtreeCoord p1, p2;
         3820  +  int i;
         3821  +
         3822  +  for(i=0; i<pCheck->nDim; i++){
         3823  +    readCoord(&pCell[4*2*i], &c1);
         3824  +    readCoord(&pCell[4*(2*i + 1)], &c2);
         3825  +
         3826  +    /* printf("%e, %e\n", c1.u.f, c2.u.f); */
         3827  +    if( pCheck->bInt ? c1.i>c2.i : c1.f>c2.f ){
         3828  +      rtreeCheckAppendMsg(pCheck, 
         3829  +          "Dimension %d of cell %d on node %lld is corrupt", i, iCell, iNode
         3830  +      );
         3831  +    }
         3832  +
         3833  +    if( pParent ){
         3834  +      readCoord(&pParent[4*2*i], &p1);
         3835  +      readCoord(&pParent[4*(2*i + 1)], &p2);
         3836  +
         3837  +      if( (pCheck->bInt ? c1.i<p1.i : c1.f<p1.f) 
         3838  +       || (pCheck->bInt ? c2.i>p2.i : c2.f>p2.f)
         3839  +      ){
         3840  +        rtreeCheckAppendMsg(pCheck, 
         3841  +            "Dimension %d of cell %d on node %lld is corrupt relative to parent"
         3842  +            , i, iCell, iNode
         3843  +        );
         3844  +      }
         3845  +    }
         3846  +  }
         3847  +}
         3848  +
         3849  +/*
         3850  +** Run rtreecheck() checks on node iNode, which is at depth iDepth within
         3851  +** the r-tree structure. Argument aParent points to the array of coordinates
         3852  +** that bound node iNode on the parent node.
         3853  +**
         3854  +** If any problems are discovered, an error message is appended to the
         3855  +** report accumulated in the RtreeCheck object.
         3856  +*/
         3857  +static void rtreeCheckNode(
         3858  +  RtreeCheck *pCheck,
         3859  +  int iDepth,                     /* Depth of iNode (0==leaf) */
         3860  +  u8 *aParent,                    /* Buffer containing parent coords */
         3861  +  i64 iNode                       /* Node to check */
         3862  +){
         3863  +  u8 *aNode = 0;
         3864  +  int nNode = 0;
         3865  +
         3866  +  assert( iNode==1 || aParent!=0 );
         3867  +  assert( pCheck->nDim>0 );
         3868  +
         3869  +  aNode = rtreeCheckGetNode(pCheck, iNode, &nNode);
         3870  +  if( aNode ){
         3871  +    if( nNode<4 ){
         3872  +      rtreeCheckAppendMsg(pCheck, 
         3873  +          "Node %lld is too small (%d bytes)", iNode, nNode
         3874  +      );
         3875  +    }else{
         3876  +      int nCell;                  /* Number of cells on page */
         3877  +      int i;                      /* Used to iterate through cells */
         3878  +      if( aParent==0 ){
         3879  +        iDepth = readInt16(aNode);
         3880  +        if( iDepth>RTREE_MAX_DEPTH ){
         3881  +          rtreeCheckAppendMsg(pCheck, "Rtree depth out of range (%d)", iDepth);
         3882  +          sqlite3_free(aNode);
         3883  +          return;
         3884  +        }
         3885  +      }
         3886  +      nCell = readInt16(&aNode[2]);
         3887  +      if( (4 + nCell*(8 + pCheck->nDim*2*4))>nNode ){
         3888  +        rtreeCheckAppendMsg(pCheck, 
         3889  +            "Node %lld is too small for cell count of %d (%d bytes)", 
         3890  +            iNode, nCell, nNode
         3891  +        );
         3892  +      }else{
         3893  +        for(i=0; i<nCell; i++){
         3894  +          u8 *pCell = &aNode[4 + i*(8 + pCheck->nDim*2*4)];
         3895  +          i64 iVal = readInt64(pCell);
         3896  +          rtreeCheckCellCoord(pCheck, iNode, i, &pCell[8], aParent);
         3897  +
         3898  +          if( iDepth>0 ){
         3899  +            rtreeCheckMapping(pCheck, 0, iVal, iNode);
         3900  +            rtreeCheckNode(pCheck, iDepth-1, &pCell[8], iVal);
         3901  +            pCheck->nNonLeaf++;
         3902  +          }else{
         3903  +            rtreeCheckMapping(pCheck, 1, iVal, iNode);
         3904  +            pCheck->nLeaf++;
         3905  +          }
         3906  +        }
         3907  +      }
         3908  +    }
         3909  +    sqlite3_free(aNode);
         3910  +  }
         3911  +}
         3912  +
         3913  +/*
         3914  +** The second argument to this function must be either "_rowid" or
         3915  +** "_parent". This function checks that the number of entries in the
         3916  +** %_rowid or %_parent table is exactly nExpect. If not, it adds
         3917  +** an error message to the report in the RtreeCheck object indicated
         3918  +** by the first argument.
         3919  +*/
         3920  +static void rtreeCheckCount(RtreeCheck *pCheck, const char *zTbl, i64 nExpect){
         3921  +  if( pCheck->rc==SQLITE_OK ){
         3922  +    sqlite3_stmt *pCount;
         3923  +    pCount = rtreeCheckPrepare(pCheck, "SELECT count(*) FROM %Q.'%q%s'",
         3924  +        pCheck->zDb, pCheck->zTab, zTbl
         3925  +    );
         3926  +    if( pCount ){
         3927  +      if( sqlite3_step(pCount)==SQLITE_ROW ){
         3928  +        i64 nActual = sqlite3_column_int64(pCount, 0);
         3929  +        if( nActual!=nExpect ){
         3930  +          rtreeCheckAppendMsg(pCheck, "Wrong number of entries in %%%s table"
         3931  +              " - expected %lld, actual %lld" , zTbl, nExpect, nActual
         3932  +          );
         3933  +        }
         3934  +      }
         3935  +      pCheck->rc = sqlite3_finalize(pCount);
         3936  +    }
         3937  +  }
         3938  +}
         3939  +
         3940  +/*
         3941  +** This function does the bulk of the work for the rtree integrity-check.
         3942  +** It is called by rtreecheck(), which is the SQL function implementation.
         3943  +*/
         3944  +static int rtreeCheckTable(
         3945  +  sqlite3 *db,                    /* Database handle to access db through */
         3946  +  const char *zDb,                /* Name of db ("main", "temp" etc.) */
         3947  +  const char *zTab,               /* Name of rtree table to check */
         3948  +  char **pzReport                 /* OUT: sqlite3_malloc'd report text */
         3949  +){
         3950  +  RtreeCheck check;               /* Common context for various routines */
         3951  +  sqlite3_stmt *pStmt = 0;        /* Used to find column count of rtree table */
         3952  +  int bEnd = 0;                   /* True if transaction should be closed */
         3953  +
         3954  +  /* Initialize the context object */
         3955  +  memset(&check, 0, sizeof(check));
         3956  +  check.db = db;
         3957  +  check.zDb = zDb;
         3958  +  check.zTab = zTab;
         3959  +
         3960  +  /* If there is not already an open transaction, open one now. This is
         3961  +  ** to ensure that the queries run as part of this integrity-check operate
         3962  +  ** on a consistent snapshot.  */
         3963  +  if( sqlite3_get_autocommit(db) ){
         3964  +    check.rc = sqlite3_exec(db, "BEGIN", 0, 0, 0);
         3965  +    bEnd = 1;
         3966  +  }
         3967  +
         3968  +  /* Find number of dimensions in the rtree table. */
         3969  +  pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.%Q", zDb, zTab);
         3970  +  if( pStmt ){
         3971  +    int rc;
         3972  +    check.nDim = (sqlite3_column_count(pStmt) - 1) / 2;
         3973  +    if( check.nDim<1 ){
         3974  +      rtreeCheckAppendMsg(&check, "Schema corrupt or not an rtree");
         3975  +    }else if( SQLITE_ROW==sqlite3_step(pStmt) ){
         3976  +      check.bInt = (sqlite3_column_type(pStmt, 1)==SQLITE_INTEGER);
         3977  +    }
         3978  +    rc = sqlite3_finalize(pStmt);
         3979  +    if( rc!=SQLITE_CORRUPT ) check.rc = rc;
         3980  +  }
         3981  +
         3982  +  /* Do the actual integrity-check */
         3983  +  if( check.nDim>=1 ){
         3984  +    if( check.rc==SQLITE_OK ){
         3985  +      rtreeCheckNode(&check, 0, 0, 1);
         3986  +    }
         3987  +    rtreeCheckCount(&check, "_rowid", check.nLeaf);
         3988  +    rtreeCheckCount(&check, "_parent", check.nNonLeaf);
         3989  +  }
         3990  +
         3991  +  /* Finalize SQL statements used by the integrity-check */
         3992  +  sqlite3_finalize(check.pGetNode);
         3993  +  sqlite3_finalize(check.aCheckMapping[0]);
         3994  +  sqlite3_finalize(check.aCheckMapping[1]);
         3995  +
         3996  +  /* If one was opened, close the transaction */
         3997  +  if( bEnd ){
         3998  +    int rc = sqlite3_exec(db, "END", 0, 0, 0);
         3999  +    if( check.rc==SQLITE_OK ) check.rc = rc;
         4000  +  }
         4001  +  *pzReport = check.zReport;
         4002  +  return check.rc;
         4003  +}
         4004  +
         4005  +/*
         4006  +** Usage:
         4007  +**
         4008  +**   rtreecheck(<rtree-table>);
         4009  +**   rtreecheck(<database>, <rtree-table>);
         4010  +**
         4011  +** Invoking this SQL function runs an integrity-check on the named rtree
         4012  +** table. The integrity-check verifies the following:
         4013  +**
         4014  +**   1. For each cell in the r-tree structure (%_node table), that:
         4015  +**
         4016  +**       a) for each dimension, (coord1 <= coord2).
         4017  +**
         4018  +**       b) unless the cell is on the root node, that the cell is bounded
         4019  +**          by the parent cell on the parent node.
         4020  +**
         4021  +**       c) for leaf nodes, that there is an entry in the %_rowid 
         4022  +**          table corresponding to the cell's rowid value that 
         4023  +**          points to the correct node.
         4024  +**
         4025  +**       d) for cells on non-leaf nodes, that there is an entry in the 
         4026  +**          %_parent table mapping from the cell's child node to the
         4027  +**          node that it resides on.
         4028  +**
         4029  +**   2. That there are the same number of entries in the %_rowid table
         4030  +**      as there are leaf cells in the r-tree structure, and that there
         4031  +**      is a leaf cell that corresponds to each entry in the %_rowid table.
         4032  +**
         4033  +**   3. That there are the same number of entries in the %_parent table
         4034  +**      as there are non-leaf cells in the r-tree structure, and that 
         4035  +**      there is a non-leaf cell that corresponds to each entry in the 
         4036  +**      %_parent table.
         4037  +*/
         4038  +static void rtreecheck(
         4039  +  sqlite3_context *ctx, 
         4040  +  int nArg, 
         4041  +  sqlite3_value **apArg
         4042  +){
         4043  +  if( nArg!=1 && nArg!=2 ){
         4044  +    sqlite3_result_error(ctx, 
         4045  +        "wrong number of arguments to function rtreecheck()", -1
         4046  +    );
         4047  +  }else{
         4048  +    int rc;
         4049  +    char *zReport = 0;
         4050  +    const char *zDb = (const char*)sqlite3_value_text(apArg[0]);
         4051  +    const char *zTab;
         4052  +    if( nArg==1 ){
         4053  +      zTab = zDb;
         4054  +      zDb = "main";
         4055  +    }else{
         4056  +      zTab = (const char*)sqlite3_value_text(apArg[1]);
         4057  +    }
         4058  +    rc = rtreeCheckTable(sqlite3_context_db_handle(ctx), zDb, zTab, &zReport);
         4059  +    if( rc==SQLITE_OK ){
         4060  +      sqlite3_result_text(ctx, zReport ? zReport : "ok", -1, SQLITE_TRANSIENT);
         4061  +    }else{
         4062  +      sqlite3_result_error_code(ctx, rc);
         4063  +    }
         4064  +    sqlite3_free(zReport);
         4065  +  }
         4066  +}
         4067  +
  3611   4068   
  3612   4069   /*
  3613   4070   ** Register the r-tree module with database handle db. This creates the
  3614   4071   ** virtual table module "rtree" and the debugging/analysis scalar 
  3615   4072   ** function "rtreenode".
  3616   4073   */
  3617   4074   int sqlite3RtreeInit(sqlite3 *db){
................................................................................
  3618   4075     const int utf8 = SQLITE_UTF8;
  3619   4076     int rc;
  3620   4077   
  3621   4078     rc = sqlite3_create_function(db, "rtreenode", 2, utf8, 0, rtreenode, 0, 0);
  3622   4079     if( rc==SQLITE_OK ){
  3623   4080       rc = sqlite3_create_function(db, "rtreedepth", 1, utf8, 0,rtreedepth, 0, 0);
  3624   4081     }
         4082  +  if( rc==SQLITE_OK ){
         4083  +    rc = sqlite3_create_function(db, "rtreecheck", -1, utf8, 0,rtreecheck, 0,0);
         4084  +  }
  3625   4085     if( rc==SQLITE_OK ){
  3626   4086   #ifdef SQLITE_RTREE_INT_ONLY
  3627   4087       void *c = (void *)RTREE_COORD_INT32;
  3628   4088   #else
  3629   4089       void *c = (void *)RTREE_COORD_REAL32;
  3630   4090   #endif
  3631   4091       rc = sqlite3_create_module_v2(db, "rtree", &rtreeModule, c, 0);

Changes to ext/rtree/rtree1.test.

   515    515       set res(1) {1 {UNIQUE constraint failed: t1.idx}}
   516    516       set res(2) {1 {rtree constraint failed: t1.(x1<=x2)}}
   517    517   
   518    518       do_catchsql_test $testname.1 $sql $res($error)
   519    519       do_test $testname.2 [list sql_uses_stmt db $sql] $uses
   520    520       do_execsql_test $testname.3 { SELECT * FROM t1 ORDER BY idx } $data
   521    521   
   522         -    do_test $testname.4 { rtree_check db t1 } 0
          522  +    do_rtree_integrity_test $testname.4 t1
   523    523       db close
   524    524     }
   525    525   }
   526    526   
   527    527   #-------------------------------------------------------------------------
   528    528   # Test that bug [d2889096e7bdeac6d] has been fixed.
   529    529   #

Changes to ext/rtree/rtree2.test.

    77     77         if {$rc != 1} {
    78     78           puts $t1
    79     79           puts $t2
    80     80         }
    81     81         set rc
    82     82       } {1}
    83     83     
    84         -    do_test rtree2-$module.$nDim.3 {
    85         -      rtree_check db t1
    86         -    } 0
           84  +    do_rtree_integrity_test rtree2-$module.$nDim.3 t1
    87     85     
    88     86       set OPS [list < > <= >= =]
    89     87       for {set ii 0} {$ii < $::NSELECT} {incr ii} {
    90     88         do_test rtree2-$module.$nDim.4.$ii.1 {
    91     89           set where [list]
    92     90           foreach look_three_dots! {. . .} {
    93     91             set colidx [expr int(rand()*($nDim*2+1))-1]
................................................................................
   129    127           set rc [expr {$t1 eq $t2}]
   130    128           if {$rc != 1} {
   131    129             puts $t1
   132    130             puts $t2
   133    131           }
   134    132           set rc
   135    133         } {1}
   136         -      do_test rtree2-$module.$nDim.5.$ii.2 {
   137         -        rtree_check db t1
   138         -      } {0}
          134  +      do_rtree_integrity_test rtree2-$module.$nDim.5.$ii.2 t1
   139    135       }
   140    136     
   141    137       do_test rtree2-$module.$nDim.6 {
   142    138         execsql {
   143    139           DROP TABLE t1;
   144    140           DROP TABLE t2;
   145    141         }
   146    142       } {}
   147    143     }
   148    144   }
   149    145   
   150    146   finish_test

Changes to ext/rtree/rtree4.test.

    11     11   #
    12     12   # Randomized test cases for the rtree extension.
    13     13   #
    14     14   
    15     15   if {![info exists testdir]} {
    16     16     set testdir [file join [file dirname [info script]] .. .. test]
    17     17   } 
           18  +source [file join [file dirname [info script]] rtree_util.tcl]
    18     19   source $testdir/tester.tcl
    19     20   
    20     21   ifcapable !rtree {
    21     22     finish_test
    22     23     return
    23     24   }
    24     25   
................................................................................
   242    243       }
   243    244       set where "WHERE [join [scramble $where] { AND }]"
   244    245       do_test rtree4-$nDim.2.$i.8 {
   245    246         list $where [db eval "SELECT id FROM rx $where ORDER BY id"]
   246    247       } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]]
   247    248     }
   248    249   
          250  +  do_rtree_integrity_test rtree4-$nDim.3 rx
   249    251   }
   250    252   
   251    253   finish_test

Changes to ext/rtree/rtree5.test.

    12     12   # The focus of this file is testing the r-tree extension when it is
    13     13   # configured to store values as 32 bit integers.
    14     14   #
    15     15   
    16     16   if {![info exists testdir]} {
    17     17     set testdir [file join [file dirname [info script]] .. .. test]
    18     18   } 
           19  +source [file join [file dirname [info script]] rtree_util.tcl]
    19     20   source $testdir/tester.tcl
    20     21   
    21     22   ifcapable !rtree {
    22     23     finish_test
    23     24     return
    24     25   }
    25     26   
................................................................................
    72     73   do_test rtree5-1.13 { 
    73     74     execsql { 
    74     75       SELECT * FROM t1 WHERE 
    75     76           x1=2147483643 AND x2=2147483647 AND 
    76     77           y1=-2147483648 AND y2=-2147483643
    77     78     }
    78     79   } {2 2147483643 2147483647 -2147483648 -2147483643}
           80  +do_rtree_integrity_test rtree5-1.14 t1
    79     81   
    80     82   finish_test

Changes to ext/rtree/rtree7.test.

    13     13   # database page-size is modified. At one point (3.6.22), this was causing
    14     14   # malfunctions.
    15     15   #
    16     16   
    17     17   if {![info exists testdir]} {
    18     18     set testdir [file join [file dirname [info script]] .. .. test]
    19     19   } 
           20  +source [file join [file dirname [info script]] rtree_util.tcl]
    20     21   source $testdir/tester.tcl
    21     22   
    22     23   ifcapable !rtree||!vacuum {
    23     24     finish_test
    24     25     return
    25     26   }
    26     27   
................................................................................
    62     63   do_test rtree7-1.5 {
    63     64     execsql_intout { 
    64     65       PRAGMA page_size = 512;
    65     66       VACUUM;
    66     67       SELECT sum(x1), sum(x2), sum(y1), sum(y2) FROM rt
    67     68     }
    68     69   } {51 102 153 204}
           70  +
           71  +do_rtree_integrity_test rtree7-1.6 rt
    69     72   
    70     73   finish_test

Changes to ext/rtree/rtree8.test.

    10     10   #***********************************************************************
    11     11   # 
    12     12   #
    13     13   
    14     14   if {![info exists testdir]} {
    15     15     set testdir [file join [file dirname [info script]] .. .. test]
    16     16   } 
           17  +source [file join [file dirname [info script]] rtree_util.tcl]
    17     18   source $testdir/tester.tcl
    18     19   ifcapable !rtree { finish_test ; return }
    19     20   
    20     21   #-------------------------------------------------------------------------
    21     22   # The following block of tests - rtree8-1.* - feature reading and writing
    22     23   # an r-tree table while there exist open cursors on it.
    23     24   #
................................................................................
    60     61   do_test rtree8-1.2.2 { nested_select 1 } {51}
    61     62   
    62     63   # This test runs many SELECT queries simultaneously against a large 
    63     64   # table, causing a collision in the hash-table used to store r-tree 
    64     65   # nodes internally.
    65     66   #
    66     67   populate_t1 1500
           68  +do_rtree_integrity_test rtree8-1.3.0 t1
    67     69   do_execsql_test rtree8-1.3.1 { SELECT max(nodeno) FROM t1_node } {164}
    68     70   do_test rtree8-1.3.2 {
    69     71     set rowids [execsql {SELECT min(rowid) FROM t1_rowid GROUP BY nodeno}]
    70     72     set stmt_list [list]
    71     73     foreach row $rowids {
    72     74       set stmt [sqlite3_prepare db "SELECT * FROM t1 WHERE id = $row" -1 tail]
    73     75       sqlite3_step $stmt
................................................................................
   154    156       execsql { INSERT INTO t2 VALUES($i, 100, 101) }
   155    157     }
   156    158     for {set i 100} {$i < 200} {incr i} {
   157    159       execsql { INSERT INTO t2 VALUES($i, 1000, 1001) }
   158    160     }
   159    161     execsql COMMIT
   160    162   } {}
   161         -do_test rtree8-5.3 {
          163  +do_rtree_integrity_test rtree8-5.3 t2
          164  +do_test rtree8-5.4 {
   162    165     execsql BEGIN
   163    166     for {set i 0} {$i < 200} {incr i} {
   164    167       execsql { DELETE FROM t2 WHERE id = $i }
   165    168     }
   166    169     execsql COMMIT
   167    170   } {}
          171  +do_rtree_integrity_test rtree8-5.5 t2
   168    172   
   169    173   
   170    174   finish_test

Changes to ext/rtree/rtree9.test.

    11     11   # This file contains tests for the r-tree module. Specifically, it tests
    12     12   # that custom r-tree queries (geometry callbacks) work.
    13     13   # 
    14     14   
    15     15   if {![info exists testdir]} {
    16     16     set testdir [file join [file dirname [info script]] .. .. test]
    17     17   } 
           18  +source [file join [file dirname [info script]] rtree_util.tcl]
    18     19   source $testdir/tester.tcl
    19     20   ifcapable !rtree { finish_test ; return }
    20     21   ifcapable rtree_int_only { finish_test; return }
    21     22   
    22     23   register_cube_geom db
    23     24   
    24     25   do_execsql_test rtree9-1.1 {
................................................................................
    38     39   
    39     40   for {set i 0} {$i < 1000} {incr i} {
    40     41     set x [expr $i%10]
    41     42     set y [expr ($i/10)%10]
    42     43     set z [expr ($i/100)%10]
    43     44     execsql { INSERT INTO rt VALUES($i, $x, $x+1, $y, $y+1, $z, $z+1) }
    44     45   }
           46  +do_rtree_integrity_test rtree9-2.0 rt
    45     47   do_execsql_test rtree9-2.1 {
    46     48     SELECT id FROM rt WHERE id MATCH cube(2.5, 2.5, 2.5, 1, 1, 1) ORDER BY id;
    47     49   } {222 223 232 233 322 323 332 333}
    48     50   do_execsql_test rtree9-2.2 {
    49     51     SELECT id FROM rt WHERE id MATCH cube(5.5, 5.5, 5.5, 1, 1, 1) ORDER BY id;
    50     52   } {555 556 565 566 655 656 665 666}
    51     53   
    52     54   
    53         -do_execsql_test rtree9-3.1 {
           55  +do_execsql_test rtree9-3.0 {
    54     56     CREATE VIRTUAL TABLE rt32 USING rtree_i32(id, x1, x2, y1, y2, z1, z2);
    55     57   } {} 
    56     58   for {set i 0} {$i < 1000} {incr i} {
    57     59     set x [expr $i%10]
    58     60     set y [expr ($i/10)%10]
    59     61     set z [expr ($i/100)%10]
    60     62     execsql { INSERT INTO rt32 VALUES($i, $x, $x+1, $y, $y+1, $z, $z+1) }
    61     63   }
           64  +do_rtree_integrity_test rtree9-3.1 rt32
    62     65   do_execsql_test rtree9-3.2 {
    63     66     SELECT id FROM rt32 WHERE id MATCH cube(3, 3, 3, 1, 1, 1) ORDER BY id;
    64     67   } {222 223 224 232 233 234 242 243 244 322 323 324 332 333 334 342 343 344 422 423 424 432 433 434 442 443 444}
    65     68   do_execsql_test rtree9-3.3 {
    66     69     SELECT id FROM rt32 WHERE id MATCH cube(5.5, 5.5, 5.5, 1, 1, 1) ORDER BY id;
    67     70   } {555 556 565 566 655 656 665 666}
    68     71   
................................................................................
   117    120     SELECT id FROM rt2 WHERE id MATCH circle(0.0, 0.0, 2.0);
   118    121   } {1 2 3 4 13 14 15 16 17}
   119    122   
   120    123   do_execsql_test rtree9-5.3 {
   121    124     UPDATE rt2 SET xmin=xmin+5, ymin=ymin+5, xmax=xmax+5, ymax=ymax+5;
   122    125     SELECT id FROM rt2 WHERE id MATCH circle(5.0, 5.0, 2.0);
   123    126   } {1 2 3 4 13 14 15 16 17}
          127  +do_rtree_integrity_test rtree9-5.4 rt2
   124    128   
   125    129   finish_test

Changes to ext/rtree/rtreeA.test.

   104    104   do_corruption_tests rtreeA-1.1 {
   105    105     1   "SELECT * FROM t1"
   106    106     2   "SELECT * FROM t1 WHERE rowid=5"
   107    107     3   "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
   108    108     4   "SELECT * FROM t1 WHERE x1<10 AND x2>12"
   109    109   }
   110    110   
          111  +do_execsql_test rtreeA-1.1.1 {
          112  +  SELECT rtreecheck('main', 't1')
          113  +} {{Node 1 missing from database
          114  +Wrong number of entries in %_rowid table - expected 0, actual 500
          115  +Wrong number of entries in %_parent table - expected 0, actual 23}}
          116  +
   111    117   do_execsql_test  rtreeA-1.2.0 { DROP TABLE t1_node } {}
   112    118   do_corruption_tests rtreeA-1.2 -error "database disk image is malformed" {
   113    119     1   "SELECT * FROM t1"
   114    120     2   "SELECT * FROM t1 WHERE rowid=5"
   115    121     3   "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
   116    122     4   "SELECT * FROM t1 WHERE x1<10 AND x2>12"
   117    123   }
................................................................................
   152    158   do_test rtreeA-3.1.0.1 { set_tree_depth t1 } {1}
   153    159   do_test rtreeA-3.1.0.2 { set_tree_depth t1 3 } {3}
   154    160   do_corruption_tests rtreeA-3.1 {
   155    161     1   "SELECT * FROM t1"
   156    162     2   "SELECT * FROM t1 WHERE rowid=5"
   157    163     3   "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
   158    164   }
          165  +
          166  +do_execsql_test rtreeA-3.1.0.3 {
          167  +  SELECT rtreecheck('main', 't1')!="ok"
          168  +} {1}
   159    169   
   160    170   do_test rtreeA-3.2.0 { set_tree_depth t1 1000 } {1000}
   161    171   do_corruption_tests rtreeA-3.2 {
   162    172     1   "SELECT * FROM t1"
   163    173     2   "SELECT * FROM t1 WHERE rowid=5"
   164    174     3   "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
   165    175   }
................................................................................
   172    182   } {65535}
   173    183   do_corruption_tests rtreeA-3.3 {
   174    184     1   "SELECT * FROM t1"
   175    185     2   "SELECT * FROM t1 WHERE rowid=5"
   176    186     3   "INSERT INTO t1 VALUES(1000, 1, 2, 3, 4)"
   177    187   }
   178    188   
          189  +do_execsql_test rtreeA-3.3.3.4 {
          190  +  SELECT rtreecheck('main', 't1')
          191  +} {{Rtree depth out of range (65535)
          192  +Wrong number of entries in %_rowid table - expected 0, actual 499
          193  +Wrong number of entries in %_parent table - expected 0, actual 23}}
          194  +
   179    195   #-------------------------------------------------------------------------
   180    196   # Set the "number of entries" field on some nodes incorrectly.
   181    197   #
   182    198   create_t1
   183    199   populate_t1
   184    200   do_test rtreeA-4.1.0 { 
   185    201     set_entry_count t1 1 4000
................................................................................
   198    214   create_t1
   199    215   populate_t1
   200    216   do_execsql_test rtreeA-5.1.0 { DELETE FROM t1_parent } {}
   201    217   do_corruption_tests rtreeA-5.1 {
   202    218     1   "DELETE FROM t1 WHERE rowid = 5"
   203    219     2   "DELETE FROM t1"
   204    220   }
          221  +
          222  +do_execsql_test rtreeA-5.2 {
          223  +  SELECT rtreecheck('main', 't1')!="ok"
          224  +} {1}
   205    225   
   206    226   #-------------------------------------------------------------------------
   207    227   # Add some bad entries to the %_parent table.
   208    228   #
   209    229   create_t1
   210    230   populate_t1
   211    231   do_execsql_test rtreeA-6.1.0 { 
   212    232     UPDATE t1_parent set parentnode = parentnode+1
   213    233   } {}
   214    234   do_corruption_tests rtreeA-6.1 {
   215    235     1   "DELETE FROM t1 WHERE rowid = 5"
   216    236     2   "UPDATE t1 SET x1=x1+1, x2=x2+1"
   217    237   }
          238  +
          239  +do_execsql_test rtreeA-6.2 {
          240  +  SELECT rtreecheck('main', 't1')!="ok"
          241  +} {1}
   218    242   
   219    243   #-------------------------------------------------------------------------
   220    244   # Truncated blobs in the _node table.
   221    245   #
   222    246   create_t1
   223    247   populate_t1
   224    248   sqlite3 db test.db
................................................................................
   229    253     SELECT * FROM t1 WHERE x1>0 AND x1<100 AND x2>0 AND x2<100;
   230    254   } {1 {undersize RTree blobs in "t1_node"}}
   231    255   do_test rtreeA-7.120 {
   232    256     sqlite3_extended_errcode db
   233    257   } {SQLITE_CORRUPT_VTAB}
   234    258   
   235    259   
   236         -
   237    260   finish_test
          261  +

Changes to ext/rtree/rtreeB.test.

    11     11   # Make sure the rtreenode() testing function can handle entries with
    12     12   # 64-bit rowids.
    13     13   # 
    14     14   
    15     15   if {![info exists testdir]} {
    16     16     set testdir [file join [file dirname [info script]] .. .. test]
    17     17   } 
           18  +source [file join [file dirname [info script]] rtree_util.tcl]
    18     19   source $testdir/tester.tcl
    19     20   ifcapable !rtree { finish_test ; return }
    20     21   
    21     22   ifcapable rtree_int_only {
    22     23     do_test rtreeB-1.1-intonly {
    23     24       db eval {
    24     25         CREATE VIRTUAL TABLE t1 USING rtree(ii, x0, y0, x1, y1);
................................................................................
    39     40         INSERT INTO t1 VALUES(4294967296, 0.0, 0.0, 300.0, 300.0);
    40     41         INSERT INTO t1 VALUES(8589934592, 20.0, 20.0, 150.0, 150.0);
    41     42         INSERT INTO t1 VALUES(9223372036854775807, 150, 150, 400, 400);
    42     43         SELECT rtreenode(2, data) FROM t1_node;
    43     44       }
    44     45     } {{{1073741824 0 0 100 100} {2147483646 0 0 200 200} {4294967296 0 0 300 300} {8589934592 20 20 150 150} {9223372036854775807 150 150 400 400}}}
    45     46   }
           47  +
           48  +do_rtree_integrity_test rtreeB-1.2 t1
    46     49   
    47     50   finish_test

Changes to ext/rtree/rtreeC.test.

    11     11   # Make sure the rtreenode() testing function can handle entries with
    12     12   # 64-bit rowids.
    13     13   # 
    14     14   
    15     15   if {![info exists testdir]} {
    16     16     set testdir [file join [file dirname [info script]] .. .. test]
    17     17   } 
           18  +source [file join [file dirname [info script]] rtree_util.tcl]
    18     19   source $testdir/tester.tcl
    19     20   ifcapable !rtree { finish_test ; return }
    20     21   set testprefix rtreeC
    21     22   
    22     23   do_execsql_test 1.0 {
    23     24     CREATE VIRTUAL TABLE r_tree USING rtree(id, min_x, max_x, min_y, max_y);
    24     25     CREATE TABLE t(x, y);
................................................................................
   176    177     INSERT INTO t1(x) SELECT x+64 FROM t1;  -- 128
   177    178     INSERT INTO t1(x) SELECT x+128 FROM t1; -- 256
   178    179     INSERT INTO t1(x) SELECT x+256 FROM t1; -- 512
   179    180     INSERT INTO t1(x) SELECT x+512 FROM t1; --1024
   180    181   
   181    182     INSERT INTO rt SELECT x, x, x+1 FROM t1 WHERE x<=5;
   182    183   }
          184  +do_rtree_integrity_test 5.1.1 rt
   183    185   
   184    186   # First test a query with no ANALYZE data at all. The outer loop is
   185    187   # real table "t1".
   186    188   #
   187    189   do_eqp_test 5.2 {
   188    190     SELECT * FROM t1, rt WHERE x==id;
   189    191   } {

Changes to ext/rtree/rtreeE.test.

    11     11   # This file contains tests for the r-tree module. Specifically, it tests
    12     12   # that new-style custom r-tree queries (geometry callbacks) work.
    13     13   # 
    14     14   
    15     15   if {![info exists testdir]} {
    16     16     set testdir [file join [file dirname [info script]] .. .. test]
    17     17   } 
           18  +source [file join [file dirname [info script]] rtree_util.tcl]
    18     19   source $testdir/tester.tcl
    19     20   ifcapable !rtree { finish_test ; return }
    20     21   ifcapable rtree_int_only { finish_test; return }
    21     22   
    22     23   
    23     24   #-------------------------------------------------------------------------
    24     25   # Test the example 2d "circle" geometry callback.
    25     26   #
    26     27   register_circle_geom db
    27     28   
    28         -do_execsql_test rtreeE-1.1 {
           29  +do_execsql_test rtreeE-1.0.0 {
    29     30     PRAGMA page_size=512;
    30     31     CREATE VIRTUAL TABLE rt1 USING rtree(id,x0,x1,y0,y1);
    31     32     
    32     33     /* A tight pattern of small boxes near 0,0 */
    33     34     WITH RECURSIVE
    34     35       x(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM x WHERE x<4),
    35     36       y(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM y WHERE y<4)
................................................................................
    43     44   
    44     45     /* A looser pattern of larger boxes near 0, 200 */
    45     46     WITH RECURSIVE
    46     47       x(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM x WHERE x<4),
    47     48       y(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM y WHERE y<4)
    48     49     INSERT INTO rt1 SELECT 200+x+5*y, x*7, x*7+15, y*7+200, y*7+215 FROM x, y;
    49     50   } {}
           51  +do_rtree_integrity_test rtreeE-1.0.1 rt1
    50     52   
    51     53   # Queries against each of the three clusters */
    52     54   do_execsql_test rtreeE-1.1 {
    53     55     SELECT id FROM rt1 WHERE id MATCH Qcircle(0.0, 0.0, 50.0, 3) ORDER BY id;
    54     56   } {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24}
    55     57   do_execsql_test rtreeE-1.1x {
    56     58     SELECT id FROM rt1 WHERE id MATCH Qcircle('x:0 y:0 r:50.0 e:3') ORDER BY id;
................................................................................
   107    109       db eval {INSERT INTO t2 VALUES($id,$x0,$x1,$y0,$y1)}
   108    110     }
   109    111     db eval {
   110    112       INSERT INTO rt2 SELECT * FROM t2;
   111    113       COMMIT;
   112    114     }
   113    115   } {}
          116  +do_rtree_integrity_test rtreeE-2.1.1 rt2
   114    117   
   115    118   for {set i 1} {$i<=200} {incr i} {
   116    119     set dx [expr {int(rand()*100)}]
   117    120     set dy [expr {int(rand()*100)}]
   118    121     set x0 [expr {int(rand()*(10000 - $dx))}]
   119    122     set x1 [expr {$x0+$dx}]
   120    123     set y0 [expr {int(rand()*(10000 - $dy))}]

Changes to ext/rtree/rtreeF.test.

    24     24   #     END;
    25     25   #     DELETE FROM t2 WHERE y=1;
    26     26   # 
    27     27   
    28     28   if {![info exists testdir]} {
    29     29     set testdir [file join [file dirname [info script]] .. .. test]
    30     30   } 
           31  +source [file join [file dirname [info script]] rtree_util.tcl]
    31     32   source $testdir/tester.tcl
    32     33   ifcapable !rtree { finish_test ; return }
    33     34   
    34     35   do_execsql_test rtreeF-1.1 {
    35     36     CREATE TABLE t1(x);
    36     37     CREATE TABLE t2(y);
    37     38     CREATE VIRTUAL TABLE t3 USING rtree(a,b,c);
................................................................................
    73     74   do_execsql_test rtreeF-1.5 {
    74     75     DELETE FROM t2 WHERE y=2;
    75     76   
    76     77     SELECT a FROM t3 ORDER BY a;
    77     78     SELECT '|';
    78     79     SELECT y FROM t2 ORDER BY y;
    79     80   } {1 4 5 | 1 4}
           81  +
           82  +do_rtree_integrity_test rtreeF-1.6 t3
    80     83   
    81     84   finish_test

Changes to ext/rtree/rtreeG.test.

    11     11   # This file contains tests for the r-tree module.
    12     12   #
    13     13   # Verify that no invalid SQL is run during initialization
    14     14   
    15     15   if {![info exists testdir]} {
    16     16     set testdir [file join [file dirname [info script]] .. .. test]
    17     17   } 
           18  +source [file join [file dirname [info script]] rtree_util.tcl]
    18     19   source $testdir/tester.tcl
    19     20   ifcapable !rtree { finish_test ; return }
    20     21   
    21     22   db close
    22     23   sqlite3_shutdown
    23     24   test_sqlite3_log [list lappend ::log]
    24     25   set ::log [list]
................................................................................
    33     34     set ::log
    34     35   } {}
    35     36   
    36     37   do_execsql_test rtreeG-1.2 {
    37     38     INSERT INTO t1 VALUES(1,10,15,5,23),(2,20,21,5,23),(3,10,15,20,30);
    38     39     SELECT id from t1 WHERE x0>8 AND x1<16 AND y0>2 AND y1<25;
    39     40   } {1}
           41  +do_rtree_integrity_test rtreeG-1.2.integrity t1
    40     42   do_test rtreeG-1.2log {
    41     43     set ::log
    42     44   } {}
    43     45   
    44     46   db close
    45     47   sqlite3 db test.db
    46     48   do_execsql_test rtreeG-1.3 {

Changes to ext/rtree/rtree_util.tcl.

   186    186     set ret
   187    187   }
   188    188   
   189    189   proc rtree_treedump {db zTab} {
   190    190     set d [rtree_depth $db $zTab]
   191    191     rtree_nodetreedump $db $zTab "" $d 1
   192    192   }
          193  +
          194  +proc do_rtree_integrity_test {tn tbl} {
          195  +  uplevel [list do_execsql_test $tn "SELECT rtreecheck('$tbl')" ok]
          196  +}
          197  +

Added ext/rtree/rtreecheck.test.

            1  +# 2017 August 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  +#
           12  +#
           13  +
           14  +
           15  +if {![info exists testdir]} {
           16  +  set testdir [file join [file dirname [info script]] .. .. test]
           17  +} 
           18  +source $testdir/tester.tcl
           19  +set testprefix rtreecheck
           20  +
           21  +ifcapable !rtree {
           22  +  finish_test
           23  +  return
           24  +}
           25  +
           26  +proc swap_int32 {blob i0 i1} {
           27  +  binary scan $blob I* L
           28  +
           29  +  set a [lindex $L $i0]
           30  +  set b [lindex $L $i1]
           31  +
           32  +  lset L $i0 $b
           33  +  lset L $i1 $a
           34  +
           35  +  binary format I* $L
           36  +}
           37  +
           38  +proc set_int32 {blob idx val} {
           39  +  binary scan $blob I* L
           40  +  lset L $idx $val
           41  +  binary format I* $L
           42  +}
           43  +
           44  +do_catchsql_test 1.0 {
           45  +  SELECT rtreecheck();
           46  +} {1 {wrong number of arguments to function rtreecheck()}}
           47  +
           48  +do_catchsql_test 1.1 {
           49  +  SELECT rtreecheck(0,0,0);
           50  +} {1 {wrong number of arguments to function rtreecheck()}}
           51  +
           52  +
           53  +proc setup_simple_db {{module rtree}} {
           54  +  reset_db
           55  +  db func swap_int32 swap_int32
           56  +  execsql "
           57  +    CREATE VIRTUAL TABLE r1 USING $module (id, x1, x2, y1, y2);
           58  +    INSERT INTO r1 VALUES(1,  5, 5, 5, 5);  --  3
           59  +    INSERT INTO r1 VALUES(2,  6, 6, 6, 6);  --  9
           60  +    INSERT INTO r1 VALUES(3,  7, 7, 7, 7);  -- 15
           61  +    INSERT INTO r1 VALUES(4,  8, 8, 8, 8);  -- 21
           62  +    INSERT INTO r1 VALUES(5,  9, 9, 9, 9);  -- 27
           63  +  "
           64  +}
           65  +
           66  +setup_simple_db
           67  +do_execsql_test 2.1 { 
           68  +  SELECT rtreecheck('r1') 
           69  +} {ok}
           70  +
           71  +do_execsql_test 2.2 {
           72  +  UPDATE r1_node SET data = swap_int32(data, 3, 9);
           73  +  UPDATE r1_node SET data = swap_int32(data, 23, 29);
           74  +}
           75  +
           76  +do_execsql_test 2.3 { 
           77  +  SELECT rtreecheck('r1') 
           78  +} {{Dimension 0 of cell 0 on node 1 is corrupt
           79  +Dimension 1 of cell 3 on node 1 is corrupt}}
           80  +
           81  +setup_simple_db
           82  +do_execsql_test 2.4 {
           83  +  DELETE FROM r1_rowid WHERE rowid = 3;
           84  +  SELECT rtreecheck('r1') 
           85  +} {{Mapping (3 -> 1) missing from %_rowid table
           86  +Wrong number of entries in %_rowid table - expected 5, actual 4}}
           87  +
           88  +setup_simple_db
           89  +do_execsql_test 2.5 {
           90  +  UPDATE r1_rowid SET nodeno=2 WHERE rowid=3;
           91  +  SELECT rtreecheck('r1') 
           92  +} {{Found (3 -> 2) in %_rowid table, expected (3 -> 1)}}
           93  +
           94  +reset_db
           95  +do_execsql_test 3.0 { 
           96  +  CREATE VIRTUAL TABLE r1 USING rtree_i32(id, x1, x2);
           97  +  INSERT INTO r1 VALUES(1, 0x7FFFFFFF*-1, 0x7FFFFFFF);
           98  +  INSERT INTO r1 VALUES(2, 0x7FFFFFFF*-1, 5);
           99  +  INSERT INTO r1 VALUES(3, -5, 5);
          100  +  INSERT INTO r1 VALUES(4, 5, 0x11111111);
          101  +  INSERT INTO r1 VALUES(5, 5, 0x00800000);
          102  +  INSERT INTO r1 VALUES(6, 5, 0x00008000);
          103  +  INSERT INTO r1 VALUES(7, 5, 0x00000080);
          104  +  INSERT INTO r1 VALUES(8, 5, 0x40490fdb);
          105  +  INSERT INTO r1 VALUES(9, 0x7f800000, 0x7f900000);
          106  +  SELECT rtreecheck('r1') 
          107  +} {ok}
          108  +
          109  +do_execsql_test 3.1 { 
          110  +  CREATE VIRTUAL TABLE r2 USING rtree_i32(id, x1, x2);
          111  +  INSERT INTO r2 VALUES(2, -1*(1<<31), -1*(1<<31)+5);
          112  +  SELECT rtreecheck('r2') 
          113  +} {ok}
          114  +
          115  +do_execsql_test 3.2 {
          116  +  BEGIN;
          117  +    UPDATE r2_node SET data = X'123456';
          118  +    SELECT rtreecheck('r2')!="ok";
          119  +} {1}
          120  +
          121  +do_execsql_test 3.3 {
          122  +  ROLLBACK;
          123  +  UPDATE r2_node SET data = X'00001234';
          124  +  SELECT rtreecheck('r2')!="ok";
          125  +} {1}
          126  +
          127  +do_execsql_test 4.0 {
          128  +  CREATE TABLE notanrtree(i);
          129  +  SELECT rtreecheck('notanrtree');
          130  +} {{Schema corrupt or not an rtree}}
          131  +
          132  +#-------------------------------------------------------------------------
          133  +#
          134  +reset_db
          135  +db func set_int32 set_int32
          136  +do_execsql_test 5.0 {
          137  +  CREATE VIRTUAL TABLE r3 USING rtree_i32(id, x1, x2, y1, y2);
          138  +  WITH x(i) AS (
          139  +    SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<1000
          140  +  )
          141  +  INSERT INTO r3 SELECT i, i, i, i, i FROM x;
          142  +}
          143  +do_execsql_test 5.1 {
          144  +  BEGIN;
          145  +    UPDATE r3_node SET data = set_int32(data, 3, 5000);
          146  +    UPDATE r3_node SET data = set_int32(data, 4, 5000);
          147  +    SELECT rtreecheck('r3')=='ok'
          148  +} 0
          149  +do_execsql_test 5.2 {
          150  +  ROLLBACK;
          151  +  BEGIN;
          152  +    UPDATE r3_node SET data = set_int32(data, 3, 0);
          153  +    UPDATE r3_node SET data = set_int32(data, 4, 0);
          154  +    SELECT rtreecheck('r3')=='ok'
          155  +} 0
          156  +
          157  +finish_test
          158  +

Changes to main.mk.

   448    448   
   449    449   # executables needed for testing
   450    450   #
   451    451   TESTPROGS = \
   452    452     testfixture$(EXE) \
   453    453     sqlite3$(EXE) \
   454    454     sqlite3_analyzer$(EXE) \
          455  +  sqlite3_checker$(EXE) \
   455    456     sqldiff$(EXE) \
   456    457     dbhash$(EXE)
   457    458   
   458    459   # Databases containing fuzzer test cases
   459    460   #
   460    461   FUZZDATA = \
   461    462     $(TOP)/test/fuzzdata1.db \
................................................................................
   566    567   	tclsh $(TOP)/tool/vdbe-compress.tcl $(OPTS) <tsrc/vdbe.c >vdbe.new
   567    568   	mv vdbe.new tsrc/vdbe.c
   568    569   	cp fts5.c fts5.h tsrc
   569    570   	touch target_source
   570    571   
   571    572   sqlite3.c:	target_source $(TOP)/tool/mksqlite3c.tcl
   572    573   	tclsh $(TOP)/tool/mksqlite3c.tcl
   573         -	cp tsrc/shell.c tsrc/sqlite3ext.h .
          574  +	cp tsrc/sqlite3ext.h .
   574    575   	cp $(TOP)/ext/session/sqlite3session.h .
   575    576   	echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c
   576    577   	cat sqlite3.c >>tclsqlite3.c
   577    578   	echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c
   578    579   	cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c
   579    580   
   580    581   sqlite3ext.h:	target_source
................................................................................
   770    771   
   771    772   sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/sqlite3_analyzer.c.in $(TOP)/tool/mkccode.tcl
   772    773   	tclsh $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c
   773    774   
   774    775   sqlite3_analyzer$(EXE): sqlite3_analyzer.c
   775    776   	$(TCCX) $(TCL_FLAGS) sqlite3_analyzer.c -o $@ $(LIBTCL) $(THREADLIB) 
   776    777   
          778  +CHECKER_DEPS =\
          779  +  $(TOP)/tool/mkccode.tcl \
          780  +  sqlite3.c \
          781  +  $(TOP)/src/tclsqlite.c \
          782  +  $(TOP)/ext/repair/sqlite3_checker.tcl \
          783  +  $(TOP)/ext/repair/checkindex.c \
          784  +  $(TOP)/ext/repair/checkfreelist.c \
          785  +  $(TOP)/ext/misc/btreeinfo.c \
          786  +  $(TOP)/ext/repair/sqlite3_checker.c.in
          787  +
          788  +sqlite3_checker.c:	$(CHECKER_DEPS)
          789  +	tclsh $(TOP)/tool/mkccode.tcl $(TOP)/ext/repair/sqlite3_checker.c.in >$@
          790  +
          791  +sqlite3_checker$(TEXE):	sqlite3_checker.c
          792  +	$(TCCX) $(TCL_FLAGS) sqlite3_checker.c -o $@ $(LIBTCL) $(THREADLIB)
          793  +
   777    794   dbdump$(EXE):	$(TOP)/ext/misc/dbdump.c sqlite3.o
   778    795   	$(TCCX) -DDBDUMP_STANDALONE -o dbdump$(EXE) \
   779    796               $(TOP)/ext/misc/dbdump.c sqlite3.o $(THREADLIB)
   780    797   
   781    798   # Rules to build the 'testfixture' application.
   782    799   #
   783    800   TESTFIXTURE_FLAGS  = -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
................................................................................
   892    909   	$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o showjournal$(EXE) \
   893    910   		$(TOP)/tool/showjournal.c sqlite3.o $(THREADLIB)
   894    911   
   895    912   showwal$(EXE):	$(TOP)/tool/showwal.c sqlite3.o
   896    913   	$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o showwal$(EXE) \
   897    914   		$(TOP)/tool/showwal.c sqlite3.o $(THREADLIB)
   898    915   
          916  +showshm$(EXE):	$(TOP)/tool/showshm.c
          917  +	$(TCC) -o showshm$(EXE) $(TOP)/tool/showshm.c
          918  +
   899    919   changeset$(EXE):	$(TOP)/ext/session/changeset.c sqlite3.o
   900    920   	$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o changeset$(EXE) \
   901    921   		$(TOP)/ext/session/changeset.c sqlite3.o $(THREADLIB)
   902    922   
   903    923   fts3view$(EXE):	$(TOP)/ext/fts3/tool/fts3view.c sqlite3.o
   904    924   	$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o fts3view$(EXE) \
   905    925   		$(TOP)/ext/fts3/tool/fts3view.c sqlite3.o $(THREADLIB)

Changes to src/build.c.

  3848   3848     if( !p && (pOn || pUsing) ){
  3849   3849       sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s", 
  3850   3850         (pOn ? "ON" : "USING")
  3851   3851       );
  3852   3852       goto append_from_error;
  3853   3853     }
  3854   3854     p = sqlite3SrcListAppend(db, p, pTable, pDatabase);
  3855         -  if( p==0 || NEVER(p->nSrc==0) ){
         3855  +  if( p==0 ){
  3856   3856       goto append_from_error;
  3857   3857     }
         3858  +  assert( p->nSrc>0 );
  3858   3859     pItem = &p->a[p->nSrc-1];
  3859   3860     assert( pAlias!=0 );
  3860   3861     if( pAlias->n ){
  3861   3862       pItem->zAlias = sqlite3NameFromToken(db, pAlias);
  3862   3863     }
  3863   3864     pItem->pSelect = pSubquery;
  3864   3865     pItem->pOn = pOn;

Changes to src/dbpage.c.

    38     38   typedef struct DbpageTable DbpageTable;
    39     39   typedef struct DbpageCursor DbpageCursor;
    40     40   
    41     41   struct DbpageCursor {
    42     42     sqlite3_vtab_cursor base;       /* Base class.  Must be first */
    43     43     int pgno;                       /* Current page number */
    44     44     int mxPgno;                     /* Last page to visit on this scan */
           45  +  Pager *pPager;                  /* Pager being read/written */
           46  +  DbPage *pPage1;                 /* Page 1 of the database */
           47  +  int iDb;                        /* Index of database to analyze */
           48  +  int szPage;                     /* Size of each page in bytes */
    45     49   };
    46     50   
    47     51   struct DbpageTable {
    48     52     sqlite3_vtab base;              /* Base class.  Must be first */
    49     53     sqlite3 *db;                    /* The database */
    50         -  Pager *pPager;                  /* Pager being read/written */
    51         -  int iDb;                        /* Index of database to analyze */
    52         -  int szPage;                     /* Size of each page in bytes */
    53         -  int nPage;                      /* Number of pages in the file */
    54     54   };
           55  +
           56  +/* Columns */
           57  +#define DBPAGE_COLUMN_PGNO    0
           58  +#define DBPAGE_COLUMN_DATA    1
           59  +#define DBPAGE_COLUMN_SCHEMA  2
           60  +
           61  +
    55     62   
    56     63   /*
    57     64   ** Connect to or create a dbpagevfs virtual table.
    58     65   */
    59     66   static int dbpageConnect(
    60     67     sqlite3 *db,
    61     68     void *pAux,
    62     69     int argc, const char *const*argv,
    63     70     sqlite3_vtab **ppVtab,
    64     71     char **pzErr
    65     72   ){
    66     73     DbpageTable *pTab = 0;
    67     74     int rc = SQLITE_OK;
    68         -  int iDb;
    69     75   
    70         -  if( argc>=4 ){
    71         -    Token nm;
    72         -    sqlite3TokenInit(&nm, (char*)argv[3]);
    73         -    iDb = sqlite3FindDb(db, &nm);
    74         -    if( iDb<0 ){
    75         -      *pzErr = sqlite3_mprintf("no such schema: %s", argv[3]);
    76         -      return SQLITE_ERROR;
    77         -    }
    78         -  }else{
    79         -    iDb = 0;
    80         -  }
    81     76     rc = sqlite3_declare_vtab(db, 
    82     77             "CREATE TABLE x(pgno INTEGER PRIMARY KEY, data BLOB, schema HIDDEN)");
    83     78     if( rc==SQLITE_OK ){
    84     79       pTab = (DbpageTable *)sqlite3_malloc64(sizeof(DbpageTable));
    85     80       if( pTab==0 ) rc = SQLITE_NOMEM_BKPT;
    86     81     }
    87     82   
    88     83     assert( rc==SQLITE_OK || pTab==0 );
    89     84     if( rc==SQLITE_OK ){
    90         -    Btree *pBt = db->aDb[iDb].pBt;
    91     85       memset(pTab, 0, sizeof(DbpageTable));
    92     86       pTab->db = db;
    93         -    pTab->iDb = iDb;
    94         -    pTab->pPager = pBt ? sqlite3BtreePager(pBt) : 0;
    95     87     }
    96     88   
    97     89     *ppVtab = (sqlite3_vtab*)pTab;
    98     90     return rc;
    99     91   }
   100     92   
   101     93   /*
................................................................................
   105     97     sqlite3_free(pVtab);
   106     98     return SQLITE_OK;
   107     99   }
   108    100   
   109    101   /*
   110    102   ** idxNum:
   111    103   **
   112         -**     0     full table scan
   113         -**     1     pgno=?1
          104  +**     0     schema=main, full table scan
          105  +**     1     schema=main, pgno=?1
          106  +**     2     schema=?1, full table scan
          107  +**     3     schema=?1, pgno=?2
   114    108   */
   115    109   static int dbpageBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
   116    110     int i;
   117         -  pIdxInfo->estimatedCost = 1.0e6;  /* Initial cost estimate */
          111  +  int iPlan = 0;
          112  +
          113  +  /* If there is a schema= constraint, it must be honored.  Report a
          114  +  ** ridiculously large estimated cost if the schema= constraint is
          115  +  ** unavailable
          116  +  */
          117  +  for(i=0; i<pIdxInfo->nConstraint; i++){
          118  +    struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
          119  +    if( p->iColumn!=DBPAGE_COLUMN_SCHEMA ) continue;
          120  +    if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
          121  +    if( !p->usable ){
          122  +      /* No solution.  Use the default SQLITE_BIG_DBL cost */
          123  +      pIdxInfo->estimatedRows = 0x7fffffff;
          124  +      return SQLITE_OK;
          125  +    }
          126  +    iPlan = 2;
          127  +    pIdxInfo->aConstraintUsage[i].argvIndex = 1;
          128  +    pIdxInfo->aConstraintUsage[i].omit = 1;
          129  +    break;
          130  +  }
          131  +
          132  +  /* If we reach this point, it means that either there is no schema=
          133  +  ** constraint (in which case we use the "main" schema) or else the
          134  +  ** schema constraint was accepted.  Lower the estimated cost accordingly
          135  +  */
          136  +  pIdxInfo->estimatedCost = 1.0e6;
          137  +
          138  +  /* Check for constraints against pgno */
   118    139     for(i=0; i<pIdxInfo->nConstraint; i++){
   119    140       struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
   120    141       if( p->usable && p->iColumn<=0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
   121    142         pIdxInfo->estimatedRows = 1;
   122    143         pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE;
   123    144         pIdxInfo->estimatedCost = 1.0;
   124         -      pIdxInfo->idxNum = 1;
   125         -      pIdxInfo->aConstraintUsage[i].argvIndex = 1;
          145  +      pIdxInfo->aConstraintUsage[i].argvIndex = iPlan ? 2 : 1;
   126    146         pIdxInfo->aConstraintUsage[i].omit = 1;
          147  +      iPlan |= 1;
   127    148         break;
   128    149       }
   129    150     }
          151  +  pIdxInfo->idxNum = iPlan;
          152  +
   130    153     if( pIdxInfo->nOrderBy>=1
   131    154      && pIdxInfo->aOrderBy[0].iColumn<=0
   132    155      && pIdxInfo->aOrderBy[0].desc==0
   133    156     ){
   134    157       pIdxInfo->orderByConsumed = 1;
   135    158     }
   136    159     return SQLITE_OK;
................................................................................
   156    179   }
   157    180   
   158    181   /*
   159    182   ** Close a dbpagevfs cursor.
   160    183   */
   161    184   static int dbpageClose(sqlite3_vtab_cursor *pCursor){
   162    185     DbpageCursor *pCsr = (DbpageCursor *)pCursor;
          186  +  if( pCsr->pPage1 ) sqlite3PagerUnrefPageOne(pCsr->pPage1);
   163    187     sqlite3_free(pCsr);
   164    188     return SQLITE_OK;
   165    189   }
   166    190   
   167    191   /*
   168    192   ** Move a dbpagevfs cursor to the next entry in the file.
   169    193   */
................................................................................
   175    199   }
   176    200   
   177    201   static int dbpageEof(sqlite3_vtab_cursor *pCursor){
   178    202     DbpageCursor *pCsr = (DbpageCursor *)pCursor;
   179    203     return pCsr->pgno > pCsr->mxPgno;
   180    204   }
   181    205   
          206  +/*
          207  +** idxNum:
          208  +**
          209  +**     0     schema=main, full table scan
          210  +**     1     schema=main, pgno=?1
          211  +**     2     schema=?1, full table scan
          212  +**     3     schema=?1, pgno=?2
          213  +**
          214  +** idxStr is not used
          215  +*/
   182    216   static int dbpageFilter(
   183    217     sqlite3_vtab_cursor *pCursor, 
   184    218     int idxNum, const char *idxStr,
   185    219     int argc, sqlite3_value **argv
   186    220   ){
   187    221     DbpageCursor *pCsr = (DbpageCursor *)pCursor;
   188    222     DbpageTable *pTab = (DbpageTable *)pCursor->pVtab;
   189         -  int rc = SQLITE_OK;
   190         -  Btree *pBt = pTab->db->aDb[pTab->iDb].pBt;
          223  +  int rc;
          224  +  sqlite3 *db = pTab->db;
          225  +  Btree *pBt;
          226  +
          227  +  /* Default setting is no rows of result */
          228  +  pCsr->pgno = 1; 
          229  +  pCsr->mxPgno = 0;
   191    230   
   192         -  pTab->szPage = sqlite3BtreeGetPageSize(pBt);
   193         -  pTab->nPage = sqlite3BtreeLastPage(pBt);
   194         -  if( idxNum==1 ){
   195         -    pCsr->pgno = sqlite3_value_int(argv[0]);
   196         -    if( pCsr->pgno<1 || pCsr->pgno>pTab->nPage ){
          231  +  if( idxNum & 2 ){
          232  +    const char *zSchema;
          233  +    assert( argc>=1 );
          234  +    zSchema = (const char*)sqlite3_value_text(argv[0]);
          235  +    pCsr->iDb = sqlite3FindDbName(db, zSchema);
          236  +    if( pCsr->iDb<0 ) return SQLITE_OK;
          237  +  }else{
          238  +    pCsr->iDb = 0;
          239  +  }
          240  +  pBt = db->aDb[pCsr->iDb].pBt;
          241  +  if( pBt==0 ) return SQLITE_OK;
          242  +  pCsr->pPager = sqlite3BtreePager(pBt);
          243  +  pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
          244  +  pCsr->mxPgno = sqlite3BtreeLastPage(pBt);
          245  +  if( idxNum & 1 ){
          246  +    assert( argc>(idxNum>>1) );
          247  +    pCsr->pgno = sqlite3_value_int(argv[idxNum>>1]);
          248  +    if( pCsr->pgno<1 || pCsr->pgno>pCsr->mxPgno ){
   197    249         pCsr->pgno = 1;
   198    250         pCsr->mxPgno = 0;
   199    251       }else{
   200    252         pCsr->mxPgno = pCsr->pgno;
   201    253       }
   202    254     }else{
   203         -    pCsr->pgno = 1;
   204         -    pCsr->mxPgno = pTab->nPage;
          255  +    assert( pCsr->pgno==1 );
   205    256     }
          257  +  if( pCsr->pPage1 ) sqlite3PagerUnrefPageOne(pCsr->pPage1);
          258  +  rc = sqlite3PagerGet(pCsr->pPager, 1, &pCsr->pPage1, 0);
   206    259     return rc;
   207    260   }
   208    261   
   209    262   static int dbpageColumn(
   210    263     sqlite3_vtab_cursor *pCursor, 
   211    264     sqlite3_context *ctx, 
   212    265     int i
   213    266   ){
   214    267     DbpageCursor *pCsr = (DbpageCursor *)pCursor;
   215         -  DbpageTable *pTab = (DbpageTable *)pCursor->pVtab;
   216    268     int rc = SQLITE_OK;
   217    269     switch( i ){
   218    270       case 0: {           /* pgno */
   219    271         sqlite3_result_int(ctx, pCsr->pgno);
   220    272         break;
   221    273       }
   222    274       case 1: {           /* data */
   223    275         DbPage *pDbPage = 0;
   224         -      rc = sqlite3PagerGet(pTab->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0);
          276  +      rc = sqlite3PagerGet(pCsr->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0);
   225    277         if( rc==SQLITE_OK ){
   226         -        sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pTab->szPage,
          278  +        sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pCsr->szPage,
   227    279                               SQLITE_TRANSIENT);
   228    280         }
   229    281         sqlite3PagerUnref(pDbPage);
   230    282         break;
   231    283       }
   232    284       default: {          /* schema */
   233    285         sqlite3 *db = sqlite3_context_db_handle(ctx);
   234         -      sqlite3_result_text(ctx, db->aDb[pTab->iDb].zDbSName, -1, SQLITE_STATIC);
          286  +      sqlite3_result_text(ctx, db->aDb[pCsr->iDb].zDbSName, -1, SQLITE_STATIC);
   235    287         break;
   236    288       }
   237    289     }
   238    290     return SQLITE_OK;
   239    291   }
   240    292   
   241    293   static int dbpageRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
................................................................................
   247    299   static int dbpageUpdate(
   248    300     sqlite3_vtab *pVtab,
   249    301     int argc,
   250    302     sqlite3_value **argv,
   251    303     sqlite_int64 *pRowid
   252    304   ){
   253    305     DbpageTable *pTab = (DbpageTable *)pVtab;
   254         -  int pgno;
          306  +  Pgno pgno;
   255    307     DbPage *pDbPage = 0;
   256    308     int rc = SQLITE_OK;
   257    309     char *zErr = 0;
          310  +  const char *zSchema;
          311  +  int iDb;
          312  +  Btree *pBt;
          313  +  Pager *pPager;
          314  +  int szPage;
   258    315   
   259    316     if( argc==1 ){
   260    317       zErr = "cannot delete";
   261    318       goto update_fail;
   262    319     }
   263    320     pgno = sqlite3_value_int(argv[0]);
   264         -  if( pgno<1 || pgno>pTab->nPage ){
   265         -    zErr = "bad page number";
   266         -    goto update_fail;
   267         -  }
   268         -  if( sqlite3_value_int(argv[1])!=pgno ){
          321  +  if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){
   269    322       zErr = "cannot insert";
   270    323       goto update_fail;
   271    324     }
          325  +  zSchema = (const char*)sqlite3_value_text(argv[4]);
          326  +  iDb = zSchema ? sqlite3FindDbName(pTab->db, zSchema) : -1;
          327  +  if( iDb<0 ){
          328  +    zErr = "no such schema";
          329  +    goto update_fail;
          330  +  }
          331  +  pBt = pTab->db->aDb[iDb].pBt;
          332  +  if( pgno<1 || pBt==0 || pgno>(int)sqlite3BtreeLastPage(pBt) ){
          333  +    zErr = "bad page number";
          334  +    goto update_fail;
          335  +  }
          336  +  szPage = sqlite3BtreeGetPageSize(pBt);
   272    337     if( sqlite3_value_type(argv[3])!=SQLITE_BLOB 
   273         -   || sqlite3_value_bytes(argv[3])!=pTab->szPage 
          338  +   || sqlite3_value_bytes(argv[3])!=szPage
   274    339     ){
   275    340       zErr = "bad page value";
   276    341       goto update_fail;
   277    342     }
   278         -  rc = sqlite3PagerGet(pTab->pPager, pgno, (DbPage**)&pDbPage, 0);
          343  +  pPager = sqlite3BtreePager(pBt);
          344  +  rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pDbPage, 0);
   279    345     if( rc==SQLITE_OK ){
   280    346       rc = sqlite3PagerWrite(pDbPage);
   281    347       if( rc==SQLITE_OK ){
   282    348         memcpy(sqlite3PagerGetData(pDbPage),
   283    349                sqlite3_value_blob(argv[3]),
   284         -             pTab->szPage);
          350  +             szPage);
   285    351       }
   286    352     }
   287    353     sqlite3PagerUnref(pDbPage);
   288    354     return rc;
   289    355   
   290    356   update_fail:
   291    357     sqlite3_free(pVtab->zErrMsg);
   292    358     pVtab->zErrMsg = sqlite3_mprintf("%s", zErr);
   293    359     return SQLITE_ERROR;
   294    360   }
          361  +
          362  +/* Since we do not know in advance which database files will be
          363  +** written by the sqlite_dbpage virtual table, start a write transaction
          364  +** on them all.
          365  +*/
          366  +static int dbpageBegin(sqlite3_vtab *pVtab){
          367  +  DbpageTable *pTab = (DbpageTable *)pVtab;
          368  +  sqlite3 *db = pTab->db;
          369  +  int i;
          370  +  for(i=0; i<db->nDb; i++){
          371  +    Btree *pBt = db->aDb[i].pBt;
          372  +    if( pBt ) sqlite3BtreeBeginTrans(pBt, 1);
          373  +  }
          374  +  return SQLITE_OK;
          375  +}
          376  +
   295    377   
   296    378   /*
   297    379   ** Invoke this routine to register the "dbpage" virtual table module
   298    380   */
   299    381   int sqlite3DbpageRegister(sqlite3 *db){
   300    382     static sqlite3_module dbpage_module = {
   301    383       0,                            /* iVersion */
................................................................................
   308    390       dbpageClose,                  /* xClose - close a cursor */
   309    391       dbpageFilter,                 /* xFilter - configure scan constraints */
   310    392       dbpageNext,                   /* xNext - advance a cursor */
   311    393       dbpageEof,                    /* xEof - check for end of scan */
   312    394       dbpageColumn,                 /* xColumn - read data */
   313    395       dbpageRowid,                  /* xRowid - read data */
   314    396       dbpageUpdate,                 /* xUpdate */
   315         -    0,                            /* xBegin */
          397  +    dbpageBegin,                  /* xBegin */
   316    398       0,                            /* xSync */
   317    399       0,                            /* xCommit */
   318    400       0,                            /* xRollback */
   319    401       0,                            /* xFindMethod */
   320    402       0,                            /* xRename */
   321    403       0,                            /* xSavepoint */
   322    404       0,                            /* xRelease */

Changes to src/delete.c.

    86     86   ** pWhere argument is an optional WHERE clause that restricts the
    87     87   ** set of rows in the view that are to be added to the ephemeral table.
    88     88   */
    89     89   void sqlite3MaterializeView(
    90     90     Parse *pParse,       /* Parsing context */
    91     91     Table *pView,        /* View definition */
    92     92     Expr *pWhere,        /* Optional WHERE clause to be added */
           93  +  ExprList *pOrderBy,  /* Optional ORDER BY clause */
           94  +  Expr *pLimit,        /* Optional LIMIT clause */
           95  +  Expr *pOffset,       /* Optional OFFSET clause */
    93     96     int iCur             /* Cursor number for ephemeral table */
    94     97   ){
    95     98     SelectDest dest;
    96     99     Select *pSel;
    97    100     SrcList *pFrom;
    98    101     sqlite3 *db = pParse->db;
    99    102     int iDb = sqlite3SchemaToIndex(db, pView->pSchema);
................................................................................
   102    105     if( pFrom ){
   103    106       assert( pFrom->nSrc==1 );
   104    107       pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
   105    108       pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
   106    109       assert( pFrom->a[0].pOn==0 );
   107    110       assert( pFrom->a[0].pUsing==0 );
   108    111     }
   109         -  pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 
   110         -                          SF_IncludeHidden, 0, 0);
          112  +  pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, pOrderBy, 
          113  +                          SF_IncludeHidden, pLimit, pOffset);
   111    114     sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
   112    115     sqlite3Select(pParse, pSel, &dest);
   113    116     sqlite3SelectDelete(db, pSel);
   114    117   }
   115    118   #endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */
   116    119   
   117    120   #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
................................................................................
   128    131     SrcList *pSrc,               /* the FROM clause -- which tables to scan */
   129    132     Expr *pWhere,                /* The WHERE clause.  May be null */
   130    133     ExprList *pOrderBy,          /* The ORDER BY clause.  May be null */
   131    134     Expr *pLimit,                /* The LIMIT clause.  May be null */
   132    135     Expr *pOffset,               /* The OFFSET clause.  May be null */
   133    136     char *zStmtType              /* Either DELETE or UPDATE.  For err msgs. */
   134    137   ){
   135         -  Expr *pWhereRowid = NULL;    /* WHERE rowid .. */
          138  +  sqlite3 *db = pParse->db;
          139  +  Expr *pLhs = NULL;           /* LHS of IN(SELECT...) operator */
   136    140     Expr *pInClause = NULL;      /* WHERE rowid IN ( select ) */
   137         -  Expr *pSelectRowid = NULL;   /* SELECT rowid ... */
   138    141     ExprList *pEList = NULL;     /* Expression list contaning only pSelectRowid */
   139    142     SrcList *pSelectSrc = NULL;  /* SELECT rowid FROM x ... (dup of pSrc) */
   140    143     Select *pSelect = NULL;      /* Complete SELECT tree */
          144  +  Table *pTab;
   141    145   
   142    146     /* Check that there isn't an ORDER BY without a LIMIT clause.
   143    147     */
   144         -  if( pOrderBy && (pLimit == 0) ) {
          148  +  if( pOrderBy && pLimit==0 ) {
   145    149       sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType);
   146         -    goto limit_where_cleanup;
          150  +    sqlite3ExprDelete(pParse->db, pWhere);
          151  +    sqlite3ExprListDelete(pParse->db, pOrderBy);
          152  +    sqlite3ExprDelete(pParse->db, pLimit);
          153  +    sqlite3ExprDelete(pParse->db, pOffset);
          154  +    return 0;
   147    155     }
   148    156   
   149    157     /* We only need to generate a select expression if there
   150    158     ** is a limit/offset term to enforce.
   151    159     */
   152    160     if( pLimit == 0 ) {
   153    161       /* if pLimit is null, pOffset will always be null as well. */
................................................................................
   160    168     **   DELETE FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
   161    169     ** becomes:
   162    170     **   DELETE FROM table_a WHERE rowid IN ( 
   163    171     **     SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
   164    172     **   );
   165    173     */
   166    174   
   167         -  pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0);
   168         -  if( pSelectRowid == 0 ) goto limit_where_cleanup;
   169         -  pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid);
   170         -  if( pEList == 0 ) goto limit_where_cleanup;
          175  +  pTab = pSrc->a[0].pTab;
          176  +  if( HasRowid(pTab) ){
          177  +    pLhs = sqlite3PExpr(pParse, TK_ROW, 0, 0);
          178  +    pEList = sqlite3ExprListAppend(
          179  +        pParse, 0, sqlite3PExpr(pParse, TK_ROW, 0, 0)
          180  +    );
          181  +  }else{
          182  +    Index *pPk = sqlite3PrimaryKeyIndex(pTab);
          183  +    if( pPk->nKeyCol==1 ){
          184  +      const char *zName = pTab->aCol[pPk->aiColumn[0]].zName;
          185  +      pLhs = sqlite3Expr(db, TK_ID, zName);
          186  +      pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, zName));
          187  +    }else{
          188  +      int i;
          189  +      for(i=0; i<pPk->nKeyCol; i++){
          190  +        Expr *p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zName);
          191  +        pEList = sqlite3ExprListAppend(pParse, pEList, p);
          192  +      }
          193  +      pLhs = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
          194  +      if( pLhs ){
          195  +        pLhs->x.pList = sqlite3ExprListDup(db, pEList, 0);
          196  +      }
          197  +    }
          198  +  }
   171    199   
   172    200     /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
   173    201     ** and the SELECT subtree. */
          202  +  pSrc->a[0].pTab = 0;
   174    203     pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0);
   175         -  if( pSelectSrc == 0 ) {
   176         -    sqlite3ExprListDelete(pParse->db, pEList);
   177         -    goto limit_where_cleanup;
   178         -  }
          204  +  pSrc->a[0].pTab = pTab;
          205  +  pSrc->a[0].pIBIndex = 0;
   179    206   
   180    207     /* generate the SELECT expression tree. */
   181         -  pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0,
   182         -                             pOrderBy,0,pLimit,pOffset);
   183         -  if( pSelect == 0 ) return 0;
          208  +  pSelect = sqlite3SelectNew(pParse, pEList, pSelectSrc, pWhere, 0 ,0, 
          209  +      pOrderBy,0,pLimit,pOffset
          210  +  );
   184    211   
   185    212     /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */
   186         -  pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0);
   187         -  pInClause = pWhereRowid ? sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0) : 0;
          213  +  pInClause = sqlite3PExpr(pParse, TK_IN, pLhs, 0);
   188    214     sqlite3PExprAddSelect(pParse, pInClause, pSelect);
   189    215     return pInClause;
   190         -
   191         -limit_where_cleanup:
   192         -  sqlite3ExprDelete(pParse->db, pWhere);
   193         -  sqlite3ExprListDelete(pParse->db, pOrderBy);
   194         -  sqlite3ExprDelete(pParse->db, pLimit);
   195         -  sqlite3ExprDelete(pParse->db, pOffset);
   196         -  return 0;
   197    216   }
   198    217   #endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) */
   199    218          /*      && !defined(SQLITE_OMIT_SUBQUERY) */
   200    219   
   201    220   /*
   202    221   ** Generate code for a DELETE FROM statement.
   203    222   **
................................................................................
   204    223   **     DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL;
   205    224   **                 \________/       \________________/
   206    225   **                  pTabList              pWhere
   207    226   */
   208    227   void sqlite3DeleteFrom(
   209    228     Parse *pParse,         /* The parser context */
   210    229     SrcList *pTabList,     /* The table from which we should delete things */
   211         -  Expr *pWhere           /* The WHERE clause.  May be null */
          230  +  Expr *pWhere,          /* The WHERE clause.  May be null */
          231  +  ExprList *pOrderBy,    /* ORDER BY clause. May be null */
          232  +  Expr *pLimit,          /* LIMIT clause. May be null */
          233  +  Expr *pOffset          /* OFFSET clause. May be null */
   212    234   ){
   213    235     Vdbe *v;               /* The virtual database engine */
   214    236     Table *pTab;           /* The table from which records will be deleted */
   215    237     int i;                 /* Loop counter */
   216    238     WhereInfo *pWInfo;     /* Information about the WHERE clause */
   217    239     Index *pIdx;           /* For looping over indices of the table */
   218    240     int iTabCur;           /* Cursor number for the table */
................................................................................
   248    270   
   249    271     memset(&sContext, 0, sizeof(sContext));
   250    272     db = pParse->db;
   251    273     if( pParse->nErr || db->mallocFailed ){
   252    274       goto delete_from_cleanup;
   253    275     }
   254    276     assert( pTabList->nSrc==1 );
          277  +
   255    278   
   256    279     /* Locate the table which we want to delete.  This table has to be
   257    280     ** put in an SrcList structure because some of the subroutines we
   258    281     ** will be calling are designed to work with multiple tables and expect
   259    282     ** an SrcList* parameter instead of just a Table* parameter.
   260    283     */
   261    284     pTab = sqlite3SrcListLookup(pParse, pTabList);
................................................................................
   272    295   # define pTrigger 0
   273    296   # define isView 0
   274    297   #endif
   275    298   #ifdef SQLITE_OMIT_VIEW
   276    299   # undef isView
   277    300   # define isView 0
   278    301   #endif
          302  +
          303  +#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
          304  +  if( !isView ){
          305  +    pWhere = sqlite3LimitWhere(
          306  +        pParse, pTabList, pWhere, pOrderBy, pLimit, pOffset, "DELETE"
          307  +    );
          308  +    pOrderBy = 0;
          309  +    pLimit = pOffset = 0;
          310  +  }
          311  +#endif
   279    312   
   280    313     /* If pTab is really a view, make sure it has been initialized.
   281    314     */
   282    315     if( sqlite3ViewGetColumnNames(pParse, pTab) ){
   283    316       goto delete_from_cleanup;
   284    317     }
   285    318   
................................................................................
   320    353     sqlite3BeginWriteOperation(pParse, 1, iDb);
   321    354   
   322    355     /* If we are trying to delete from a view, realize that view into
   323    356     ** an ephemeral table.
   324    357     */
   325    358   #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
   326    359     if( isView ){
   327         -    sqlite3MaterializeView(pParse, pTab, pWhere, iTabCur);
          360  +    sqlite3MaterializeView(pParse, pTab, 
          361  +        pWhere, pOrderBy, pLimit, pOffset, iTabCur
          362  +    );
   328    363       iDataCur = iIdxCur = iTabCur;
          364  +    pOrderBy = 0;
          365  +    pLimit = pOffset = 0;
   329    366     }
   330    367   #endif
   331    368   
   332    369     /* Resolve the column names in the WHERE clause.
   333    370     */
   334    371     memset(&sNC, 0, sizeof(sNC));
   335    372     sNC.pParse = pParse;
................................................................................
   565    602       sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC);
   566    603     }
   567    604   
   568    605   delete_from_cleanup:
   569    606     sqlite3AuthContextPop(&sContext);
   570    607     sqlite3SrcListDelete(db, pTabList);
   571    608     sqlite3ExprDelete(db, pWhere);
          609  +#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) 
          610  +  sqlite3ExprListDelete(db, pOrderBy);
          611  +  sqlite3ExprDelete(db, pLimit);
          612  +  sqlite3ExprDelete(db, pOffset);
          613  +#endif
   572    614     sqlite3DbFree(db, aToOpen);
   573    615     return;
   574    616   }
   575    617   /* Make sure "isView" and other macros defined above are undefined. Otherwise
   576    618   ** they may interfere with compilation of other functions in this file
   577    619   ** (or in another file, if this file becomes part of the amalgamation).  */
   578    620   #ifdef isView

Changes to src/expr.c.

   948    948     assert( pToken );
   949    949     pNew = sqlite3ExprAlloc(db, TK_FUNCTION, pToken, 1);
   950    950     if( pNew==0 ){
   951    951       sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */
   952    952       return 0;
   953    953     }
   954    954     pNew->x.pList = pList;
          955  +  ExprSetProperty(pNew, EP_HasFunc);
   955    956     assert( !ExprHasProperty(pNew, EP_xIsSelect) );
   956    957     sqlite3ExprSetHeightAndFlags(pParse, pNew);
   957    958     return pNew;
   958    959   }
   959    960   
   960    961   /*
   961    962   ** Assign a variable number to an expression that encodes a wildcard

Changes to src/fkey.c.

   721    721         }
   722    722         if( !p ) return;
   723    723         iSkip = sqlite3VdbeMakeLabel(v);
   724    724         sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); VdbeCoverage(v);
   725    725       }
   726    726   
   727    727       pParse->disableTriggers = 1;
   728         -    sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0);
          728  +    sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0, 0, 0, 0);
   729    729       pParse->disableTriggers = 0;
   730    730   
   731    731       /* If the DELETE has generated immediate foreign key constraint 
   732    732       ** violations, halt the VDBE and return an error at this point, before
   733    733       ** any modifications to the schema are made. This is because statement
   734    734       ** transactions are not able to rollback schema changes.  
   735    735       **

Changes to src/func.c.

   694    694         ** that point.
   695    695         **
   696    696         ** For a case-insensitive search, set variable cx to be the same as
   697    697         ** c but in the other case and search the input string for either
   698    698         ** c or cx.
   699    699         */
   700    700         if( c<=0x80 ){
   701         -        u32 cx;
          701  +        char zStop[3];
   702    702           int bMatch;
   703    703           if( noCase ){
   704         -          cx = sqlite3Toupper(c);
   705         -          c = sqlite3Tolower(c);
          704  +          zStop[0] = sqlite3Toupper(c);
          705  +          zStop[1] = sqlite3Tolower(c);
          706  +          zStop[2] = 0;
   706    707           }else{
   707         -          cx = c;
          708  +          zStop[0] = c;
          709  +          zStop[1] = 0;
   708    710           }
   709         -        while( (c2 = *(zString++))!=0 ){
   710         -          if( c2!=c && c2!=cx ) continue;
          711  +        while(1){
          712  +          zString += strcspn((const char*)zString, zStop);
          713  +          if( zString[0]==0 ) break;
          714  +          zString++;
   711    715             bMatch = patternCompare(zPattern,zString,pInfo,matchOther);
   712    716             if( bMatch!=SQLITE_NOMATCH ) return bMatch;
   713    717           }
   714    718         }else{
   715    719           int bMatch;
   716    720           while( (c2 = Utf8Read(zString))!=0 ){
   717    721             if( c2!=c ) continue;

Changes to src/insert.c.

   905    905           sqlite3VdbeAddOp3(v, OP_Column, srcTab, ipkColumn, regRowid);
   906    906         }else if( pSelect ){
   907    907           sqlite3VdbeAddOp2(v, OP_Copy, regFromSelect+ipkColumn, regRowid);
   908    908         }else{
   909    909           VdbeOp *pOp;
   910    910           sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regRowid);
   911    911           pOp = sqlite3VdbeGetOp(v, -1);
   912         -        if( ALWAYS(pOp) && pOp->opcode==OP_Null && !IsVirtual(pTab) ){
          912  +        assert( pOp!=0 );
          913  +        if( pOp->opcode==OP_Null && !IsVirtual(pTab) ){
   913    914             appendFlag = 1;
   914    915             pOp->opcode = OP_NewRowid;
   915    916             pOp->p1 = iDataCur;
   916    917             pOp->p2 = regRowid;
   917    918             pOp->p3 = regAutoinc;
   918    919           }
   919    920         }

Changes to src/os_unix.c.

   797    797   #if defined(HAVE_LSTAT)
   798    798     { "lstat",         (sqlite3_syscall_ptr)lstat,          0 },
   799    799   #else
   800    800     { "lstat",         (sqlite3_syscall_ptr)0,              0 },
   801    801   #endif
   802    802   #define osLstat      ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent)
   803    803   
          804  +#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
   804    805     { "ioctl",         (sqlite3_syscall_ptr)ioctl,          0 },
          806  +#else
          807  +  { "ioctl",         (sqlite3_syscall_ptr)0,              0 },
          808  +#endif
   805    809   #define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent)
   806    810   
   807    811   }; /* End of the overrideable system calls */
   808    812   
   809    813   
   810    814   /*
   811    815   ** On some systems, calls to fchown() will trigger a message in a security

Changes to src/parse.y.

   749    749   /////////////////////////// The DELETE statement /////////////////////////////
   750    750   //
   751    751   %ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
   752    752   cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W) 
   753    753           orderby_opt(O) limit_opt(L). {
   754    754     sqlite3WithPush(pParse, C, 1);
   755    755     sqlite3SrcListIndexedBy(pParse, X, &I);
   756         -  W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "DELETE");
   757         -  sqlite3DeleteFrom(pParse,X,W);
          756  +  sqlite3DeleteFrom(pParse,X,W,O,L.pLimit,L.pOffset); 
   758    757   }
   759    758   %endif
   760    759   %ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
   761    760   cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W). {
   762    761     sqlite3WithPush(pParse, C, 1);
   763    762     sqlite3SrcListIndexedBy(pParse, X, &I);
   764         -  sqlite3DeleteFrom(pParse,X,W);
          763  +  sqlite3DeleteFrom(pParse,X,W,0,0,0);
   765    764   }
   766    765   %endif
   767    766   
   768    767   %type where_opt {Expr*}
   769    768   %destructor where_opt {sqlite3ExprDelete(pParse->db, $$);}
   770    769   
   771    770   where_opt(A) ::= .                    {A = 0;}
................................................................................
   775    774   //
   776    775   %ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
   777    776   cmd ::= with(C) UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y)
   778    777           where_opt(W) orderby_opt(O) limit_opt(L).  {
   779    778     sqlite3WithPush(pParse, C, 1);
   780    779     sqlite3SrcListIndexedBy(pParse, X, &I);
   781    780     sqlite3ExprListCheckLength(pParse,Y,"set list"); 
   782         -  W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "UPDATE");
   783         -  sqlite3Update(pParse,X,Y,W,R);
          781  +  sqlite3Update(pParse,X,Y,W,R,O,L.pLimit,L.pOffset);
   784    782   }
   785    783   %endif
   786    784   %ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
   787    785   cmd ::= with(C) UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y)
   788    786           where_opt(W).  {
   789    787     sqlite3WithPush(pParse, C, 1);
   790    788     sqlite3SrcListIndexedBy(pParse, X, &I);
   791    789     sqlite3ExprListCheckLength(pParse,Y,"set list"); 
   792         -  sqlite3Update(pParse,X,Y,W,R);
          790  +  sqlite3Update(pParse,X,Y,W,R,0,0,0);
   793    791   }
   794    792   %endif
   795    793   
   796    794   %type setlist {ExprList*}
   797    795   %destructor setlist {sqlite3ExprListDelete(pParse->db, $$);}
   798    796   
   799    797   setlist(A) ::= setlist(A) COMMA nm(X) EQ expr(Y). {

Changes to src/pcache.c.

   562    562   
   563    563   /*
   564    564   ** Make sure the page is marked as clean. If it isn't clean already,
   565    565   ** make it so.
   566    566   */
   567    567   void sqlite3PcacheMakeClean(PgHdr *p){
   568    568     assert( sqlite3PcachePageSanity(p) );
   569         -  if( ALWAYS((p->flags & PGHDR_DIRTY)!=0) ){
   570         -    assert( (p->flags & PGHDR_CLEAN)==0 );
   571         -    pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE);
   572         -    p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC|PGHDR_WRITEABLE);
   573         -    p->flags |= PGHDR_CLEAN;
   574         -    pcacheTrace(("%p.CLEAN %d\n",p->pCache,p->pgno));
   575         -    assert( sqlite3PcachePageSanity(p) );
   576         -    if( p->nRef==0 ){
   577         -      pcacheUnpin(p);
   578         -    }
          569  +  assert( (p->flags & PGHDR_DIRTY)!=0 );
          570  +  assert( (p->flags & PGHDR_CLEAN)==0 );
          571  +  pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE);
          572  +  p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC|PGHDR_WRITEABLE);
          573  +  p->flags |= PGHDR_CLEAN;
          574  +  pcacheTrace(("%p.CLEAN %d\n",p->pCache,p->pgno));
          575  +  assert( sqlite3PcachePageSanity(p) );
          576  +  if( p->nRef==0 ){
          577  +    pcacheUnpin(p);
   579    578     }
   580    579   }
   581    580   
   582    581   /*
   583    582   ** Make every page in the cache clean.
   584    583   */
   585    584   void sqlite3PcacheCleanAll(PCache *pCache){

Changes to src/prepare.c.

   472    472     ** We return -1000000 instead of the more usual -1 simply because using
   473    473     ** -1000000 as the incorrect index into db->aDb[] is much 
   474    474     ** more likely to cause a segfault than -1 (of course there are assert()
   475    475     ** statements too, but it never hurts to play the odds).
   476    476     */
   477    477     assert( sqlite3_mutex_held(db->mutex) );
   478    478     if( pSchema ){
   479         -    for(i=0; ALWAYS(i<db->nDb); i++){
          479  +    for(i=0; 1; i++){
          480  +      assert( i<db->nDb );
   480    481         if( db->aDb[i].pSchema==pSchema ){
   481    482           break;
   482    483         }
   483    484       }
   484    485       assert( i>=0 && i<db->nDb );
   485    486     }
   486    487     return i;

Changes to src/resolve.c.

   592    592       ** column in the FROM clause.  This is used by the LIMIT and ORDER BY
   593    593       ** clause processing on UPDATE and DELETE statements.
   594    594       */
   595    595       case TK_ROW: {
   596    596         SrcList *pSrcList = pNC->pSrcList;
   597    597         struct SrcList_item *pItem;
   598    598         assert( pSrcList && pSrcList->nSrc==1 );
   599         -      pItem = pSrcList->a; 
          599  +      pItem = pSrcList->a;
          600  +      assert( HasRowid(pItem->pTab) && pItem->pTab->pSelect==0 );
   600    601         pExpr->op = TK_COLUMN;
   601    602         pExpr->pTab = pItem->pTab;
   602    603         pExpr->iTable = pItem->iCursor;
   603    604         pExpr->iColumn = -1;
   604    605         pExpr->affinity = SQLITE_AFF_INTEGER;
   605    606         break;
   606    607       }

Changes to src/select.c.

  3379   3379   **  (18)  If the sub-query is a compound select, then all terms of the
  3380   3380   **        ORDER BY clause of the parent must be simple references to 
  3381   3381   **        columns of the sub-query.
  3382   3382   **
  3383   3383   **  (19)  If the subquery uses LIMIT then the outer query may not
  3384   3384   **        have a WHERE clause.
  3385   3385   **
  3386         -**  (**)  Subsumed into (17d3).  Was: If the sub-query is a compound select,
  3387         -**        then it must not use an ORDER BY clause - Ticket #3773.  Because
  3388         -**        of (17d3), then only way to have a compound subquery is if it is
  3389         -**        the only term in the FROM clause of the outer query.  But if the
  3390         -**        only term in the FROM clause has an ORDER BY, then it will be
  3391         -**        implemented as a co-routine and the flattener will never be called.
         3386  +**  (20)  If the sub-query is a compound select, then it must not use
         3387  +**        an ORDER BY clause.  Ticket #3773.  We could relax this constraint
         3388  +**        somewhat by saying that the terms of the ORDER BY clause must
         3389  +**        appear as unmodified result columns in the outer query.  But we
         3390  +**        have other optimizations in mind to deal with that case.
  3392   3391   **
  3393   3392   **  (21)  If the subquery uses LIMIT then the outer query may not be
  3394   3393   **        DISTINCT.  (See ticket [752e1646fc]).
  3395   3394   **
  3396   3395   **  (22)  The subquery may not be a recursive CTE.
  3397   3396   **
  3398   3397   **  (**)  Subsumed into restriction (17d3).  Was: If the outer query is
................................................................................
  3518   3517   
  3519   3518     /* Restriction (17): If the sub-query is a compound SELECT, then it must
  3520   3519     ** use only the UNION ALL operator. And none of the simple select queries
  3521   3520     ** that make up the compound SELECT are allowed to be aggregate or distinct
  3522   3521     ** queries.
  3523   3522     */
  3524   3523     if( pSub->pPrior ){
         3524  +    if( pSub->pOrderBy ){
         3525  +      return 0;  /* Restriction (20) */
         3526  +    }
  3525   3527       if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
  3526   3528         return 0; /* (17d1), (17d2), or (17d3) */
  3527   3529       }
  3528   3530       for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
  3529   3531         testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
  3530   3532         testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
  3531   3533         assert( pSub->pSrc!=0 );
................................................................................
  3552   3554     ** The only way that the recursive part of a CTE can contain a compound
  3553   3555     ** subquery is for the subquery to be one term of a join.  But if the
  3554   3556     ** subquery is a join, then the flattening has already been stopped by
  3555   3557     ** restriction (17d3)
  3556   3558     */
  3557   3559     assert( (p->selFlags & SF_Recursive)==0 || pSub->pPrior==0 );
  3558   3560   
  3559         -  /* Ex-restriction (20):
  3560         -  ** A compound subquery must be the only term in the FROM clause of the
  3561         -  ** outer query by restriction (17d3).  But if that term also has an
  3562         -  ** ORDER BY clause, then the subquery will be implemented by co-routine
  3563         -  ** and so the flattener will never be invoked.  Hence, it is not possible
  3564         -  ** for the subquery to be a compound and have an ORDER BY clause.
  3565         -  */
  3566         -  assert( pSub->pPrior==0 || pSub->pOrderBy==0 );
  3567         -
  3568   3561     /***** If we reach this point, flattening is permitted. *****/
  3569   3562     SELECTTRACE(1,pParse,p,("flatten %s.%p from term %d\n",
  3570   3563                      pSub->zSelName, pSub, iFrom));
  3571   3564   
  3572   3565     /* Authorize the subquery */
  3573   3566     pParse->zAuthContext = pSubitem->zName;
  3574   3567     TESTONLY(i =) sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0);
................................................................................
  3915   3908       }
  3916   3909     }
  3917   3910     return nChng;
  3918   3911   }
  3919   3912   #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
  3920   3913   
  3921   3914   /*
  3922         -** Based on the contents of the AggInfo structure indicated by the first
  3923         -** argument, this function checks if the following are true:
  3924         -**
  3925         -**    * the query contains just a single aggregate function,
  3926         -**    * the aggregate function is either min() or max(), and
  3927         -**    * the argument to the aggregate function is a column value.
  3928         -**
  3929         -** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX
  3930         -** is returned as appropriate. Also, *ppMinMax is set to point to the 
  3931         -** list of arguments passed to the aggregate before returning.
  3932         -**
  3933         -** Or, if the conditions above are not met, *ppMinMax is set to 0 and
  3934         -** WHERE_ORDERBY_NORMAL is returned.
  3935         -*/
  3936         -static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){
  3937         -  int eRet = WHERE_ORDERBY_NORMAL;          /* Return value */
  3938         -
  3939         -  *ppMinMax = 0;
  3940         -  if( pAggInfo->nFunc==1 ){
  3941         -    Expr *pExpr = pAggInfo->aFunc[0].pExpr; /* Aggregate function */
  3942         -    ExprList *pEList = pExpr->x.pList;      /* Arguments to agg function */
  3943         -
  3944         -    assert( pExpr->op==TK_AGG_FUNCTION );
  3945         -    if( pEList && pEList->nExpr==1 && pEList->a[0].pExpr->op==TK_AGG_COLUMN ){
  3946         -      const char *zFunc = pExpr->u.zToken;
  3947         -      if( sqlite3StrICmp(zFunc, "min")==0 ){
  3948         -        eRet = WHERE_ORDERBY_MIN;
  3949         -        *ppMinMax = pEList;
  3950         -      }else if( sqlite3StrICmp(zFunc, "max")==0 ){
  3951         -        eRet = WHERE_ORDERBY_MAX;
  3952         -        *ppMinMax = pEList;
  3953         -      }
  3954         -    }
  3955         -  }
  3956         -
  3957         -  assert( *ppMinMax==0 || (*ppMinMax)->nExpr==1 );
         3915  +** The pFunc is the only aggregate function in the query.  Check to see
         3916  +** if the query is a candidate for the min/max optimization. 
         3917  +**
         3918  +** If the query is a candidate for the min/max optimization, then set
         3919  +** *ppMinMax to be an ORDER BY clause to be used for the optimization
         3920  +** and return either WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX depending on
         3921  +** whether pFunc is a min() or max() function.
         3922  +**
         3923  +** If the query is not a candidate for the min/max optimization, return
         3924  +** WHERE_ORDERBY_NORMAL (which must be zero).
         3925  +**
         3926  +** This routine must be called after aggregate functions have been
         3927  +** located but before their arguments have been subjected to aggregate
         3928  +** analysis.
         3929  +*/
         3930  +static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){
         3931  +  int eRet = WHERE_ORDERBY_NORMAL;      /* Return value */
         3932  +  ExprList *pEList = pFunc->x.pList;    /* Arguments to agg function */
         3933  +  const char *zFunc;                    /* Name of aggregate function pFunc */
         3934  +  ExprList *pOrderBy;
         3935  +  u8 sortOrder;
         3936  +
         3937  +  assert( *ppMinMax==0 );
         3938  +  assert( pFunc->op==TK_AGG_FUNCTION );
         3939  +  if( pEList==0 || pEList->nExpr!=1 ) return eRet;
         3940  +  zFunc = pFunc->u.zToken;
         3941  +  if( sqlite3StrICmp(zFunc, "min")==0 ){
         3942  +    eRet = WHERE_ORDERBY_MIN;
         3943  +    sortOrder = SQLITE_SO_ASC;
         3944  +  }else if( sqlite3StrICmp(zFunc, "max")==0 ){
         3945  +    eRet = WHERE_ORDERBY_MAX;
         3946  +    sortOrder = SQLITE_SO_DESC;
         3947  +  }else{
         3948  +    return eRet;
         3949  +  }
         3950  +  *ppMinMax = pOrderBy = sqlite3ExprListDup(db, pEList, 0);
         3951  +  assert( pOrderBy!=0 || db->mallocFailed );
         3952  +  if( pOrderBy ) pOrderBy->a[0].sortOrder = sortOrder;
  3958   3953     return eRet;
  3959   3954   }
  3960   3955   
  3961   3956   /*
  3962   3957   ** The select statement passed as the first argument is an aggregate query.
  3963   3958   ** The second argument is the associated aggregate-info object. This 
  3964   3959   ** function tests if the SELECT is of the form:
................................................................................
  4337   4332     int i, j, k;
  4338   4333     SrcList *pTabList;
  4339   4334     ExprList *pEList;
  4340   4335     struct SrcList_item *pFrom;
  4341   4336     sqlite3 *db = pParse->db;
  4342   4337     Expr *pE, *pRight, *pExpr;
  4343   4338     u16 selFlags = p->selFlags;
         4339  +  u32 elistFlags = 0;
  4344   4340   
  4345   4341     p->selFlags |= SF_Expanded;
  4346   4342     if( db->mallocFailed  ){
  4347   4343       return WRC_Abort;
  4348   4344     }
  4349         -  if( NEVER(p->pSrc==0) || (selFlags & SF_Expanded)!=0 ){
         4345  +  assert( p->pSrc!=0 );
         4346  +  if( (selFlags & SF_Expanded)!=0 ){
  4350   4347       return WRC_Prune;
  4351   4348     }
  4352   4349     pTabList = p->pSrc;
  4353   4350     pEList = p->pEList;
  4354   4351     if( OK_IF_ALWAYS_TRUE(p->pWith) ){
  4355   4352       sqlite3WithPush(pParse, p->pWith, 0);
  4356   4353     }
................................................................................
  4449   4446     */
  4450   4447     for(k=0; k<pEList->nExpr; k++){
  4451   4448       pE = pEList->a[k].pExpr;
  4452   4449       if( pE->op==TK_ASTERISK ) break;
  4453   4450       assert( pE->op!=TK_DOT || pE->pRight!=0 );
  4454   4451       assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) );
  4455   4452       if( pE->op==TK_DOT && pE->pRight->op==TK_ASTERISK ) break;
         4453  +    elistFlags |= pE->flags;
  4456   4454     }
  4457   4455     if( k<pEList->nExpr ){
  4458   4456       /*
  4459   4457       ** If we get here it means the result set contains one or more "*"
  4460   4458       ** operators that need to be expanded.  Loop through each expression
  4461   4459       ** in the result set and expand them one by one.
  4462   4460       */
................................................................................
  4464   4462       ExprList *pNew = 0;
  4465   4463       int flags = pParse->db->flags;
  4466   4464       int longNames = (flags & SQLITE_FullColNames)!=0
  4467   4465                         && (flags & SQLITE_ShortColNames)==0;
  4468   4466   
  4469   4467       for(k=0; k<pEList->nExpr; k++){
  4470   4468         pE = a[k].pExpr;
         4469  +      elistFlags |= pE->flags;
  4471   4470         pRight = pE->pRight;
  4472   4471         assert( pE->op!=TK_DOT || pRight!=0 );
  4473   4472         if( pE->op!=TK_ASTERISK
  4474   4473          && (pE->op!=TK_DOT || pRight->op!=TK_ASTERISK)
  4475   4474         ){
  4476   4475           /* This particular expression does not need to be expanded.
  4477   4476           */
................................................................................
  4593   4592             }
  4594   4593           }
  4595   4594         }
  4596   4595       }
  4597   4596       sqlite3ExprListDelete(db, pEList);
  4598   4597       p->pEList = pNew;
  4599   4598     }
  4600         -  if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
  4601         -    sqlite3ErrorMsg(pParse, "too many columns in result set");
  4602         -    return WRC_Abort;
         4599  +  if( p->pEList ){
         4600  +    if( p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
         4601  +      sqlite3ErrorMsg(pParse, "too many columns in result set");
         4602  +      return WRC_Abort;
         4603  +    }
         4604  +    if( (elistFlags & (EP_HasFunc|EP_Subquery))!=0 ){
         4605  +      p->selFlags |= SF_ComplexResult;
         4606  +    }
  4603   4607     }
  4604   4608     return WRC_Continue;
  4605   4609   }
  4606   4610   
  4607   4611   /*
  4608   4612   ** No-op routine for the parse-tree walker.
  4609   4613   **
................................................................................
  5131   5135     Expr *pHaving;         /* The HAVING clause.  May be NULL */
  5132   5136     int rc = 1;            /* Value to return from this function */
  5133   5137     DistinctCtx sDistinct; /* Info on how to code the DISTINCT keyword */
  5134   5138     SortCtx sSort;         /* Info on how to code the ORDER BY clause */
  5135   5139     AggInfo sAggInfo;      /* Information used by aggregate queries */
  5136   5140     int iEnd;              /* Address of the end of the query */
  5137   5141     sqlite3 *db;           /* The database connection */
         5142  +  ExprList *pMinMaxOrderBy = 0;  /* Added ORDER BY for min/max queries */
         5143  +  u8 minMaxFlag;                 /* Flag for min/max queries */
  5138   5144   
  5139   5145   #ifndef SQLITE_OMIT_EXPLAIN
  5140   5146     int iRestoreSelectId = pParse->iSelectId;
  5141   5147     pParse->iSelectId = pParse->iNextSelectId++;
  5142   5148   #endif
  5143   5149   
  5144   5150     db = pParse->db;
................................................................................
  5217   5223       ** is not a join.  But if the outer query is not a join, then the subquery
  5218   5224       ** will be implemented as a co-routine and there is no advantage to
  5219   5225       ** flattening in that case.
  5220   5226       */
  5221   5227       if( (pSub->selFlags & SF_Aggregate)!=0 ) continue;
  5222   5228       assert( pSub->pGroupBy==0 );
  5223   5229   
  5224         -    /* If the subquery contains an ORDER BY clause and if
         5230  +    /* If the outer query contains a "complex" result set (that is,
         5231  +    ** if the result set of the outer query uses functions or subqueries)
         5232  +    ** and if the subquery contains an ORDER BY clause and if
  5225   5233       ** it will be implemented as a co-routine, then do not flatten.  This
  5226   5234       ** restriction allows SQL constructs like this:
  5227   5235       **
  5228   5236       **  SELECT expensive_function(x)
  5229   5237       **    FROM (SELECT x FROM tab ORDER BY y LIMIT 10);
  5230   5238       **
  5231   5239       ** The expensive_function() is only computed on the 10 rows that
  5232   5240       ** are output, rather than every row of the table.
         5241  +    **
         5242  +    ** The requirement that the outer query have a complex result set
         5243  +    ** means that flattening does occur on simpler SQL constraints without
         5244  +    ** the expensive_function() like:
         5245  +    **
         5246  +    **  SELECT x FROM (SELECT x FROM tab ORDER BY y LIMIT 10);
  5233   5247       */
  5234   5248       if( pSub->pOrderBy!=0
  5235   5249        && i==0
         5250  +     && (p->selFlags & SF_ComplexResult)!=0
  5236   5251        && (pTabList->nSrc==1
  5237   5252            || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0)
  5238   5253       ){
  5239   5254         continue;
  5240   5255       }
  5241   5256   
  5242   5257       if( flattenSubquery(pParse, p, i, isAgg) ){
................................................................................
  5647   5662           assert( pWhere==p->pWhere );
  5648   5663           havingToWhere(pParse, pGroupBy, pHaving, &p->pWhere);
  5649   5664           pWhere = p->pWhere;
  5650   5665         }
  5651   5666         sqlite3ExprAnalyzeAggregates(&sNC, pHaving);
  5652   5667       }
  5653   5668       sAggInfo.nAccumulator = sAggInfo.nColumn;
         5669  +    if( p->pGroupBy==0 && p->pHaving==0 && sAggInfo.nFunc==1 ){
         5670  +      minMaxFlag = minMaxQuery(db, sAggInfo.aFunc[0].pExpr, &pMinMaxOrderBy);
         5671  +    }else{
         5672  +      minMaxFlag = WHERE_ORDERBY_NORMAL;
         5673  +    }
  5654   5674       for(i=0; i<sAggInfo.nFunc; i++){
  5655   5675         assert( !ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsSelect) );
  5656   5676         sNC.ncFlags |= NC_InAggFunc;
  5657   5677         sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList);
  5658   5678         sNC.ncFlags &= ~NC_InAggFunc;
  5659   5679       }
  5660   5680       sAggInfo.mxReg = pParse->nMem;
  5661   5681       if( db->mallocFailed ) goto select_end;
         5682  +#if SELECTTRACE_ENABLED
         5683  +    if( sqlite3SelectTrace & 0x400 ){
         5684  +      int ii;
         5685  +      SELECTTRACE(0x400,pParse,p,("After aggregate analysis:\n"));
         5686  +      sqlite3TreeViewSelect(0, p, 0);
         5687  +      for(ii=0; ii<sAggInfo.nColumn; ii++){
         5688  +        sqlite3DebugPrintf("agg-column[%d] iMem=%d\n",
         5689  +            ii, sAggInfo.aCol[ii].iMem);
         5690  +        sqlite3TreeViewExpr(0, sAggInfo.aCol[ii].pExpr, 0);
         5691  +      }
         5692  +      for(ii=0; ii<sAggInfo.nFunc; ii++){
         5693  +        sqlite3DebugPrintf("agg-func[%d]: iMem=%d\n",
         5694  +            ii, sAggInfo.aFunc[ii].iMem);
         5695  +        sqlite3TreeViewExpr(0, sAggInfo.aFunc[ii].pExpr, 0);
         5696  +      }
         5697  +    }
         5698  +#endif
         5699  +
  5662   5700   
  5663   5701       /* Processing for aggregates with GROUP BY is very different and
  5664   5702       ** much more complex than aggregates without a GROUP BY.
  5665   5703       */
  5666   5704       if( pGroupBy ){
  5667   5705         KeyInfo *pKeyInfo;  /* Keying information for the group by clause */
  5668   5706         int addr1;          /* A-vs-B comparision jump */
................................................................................
  5884   5922         */
  5885   5923         sqlite3VdbeResolveLabel(v, addrReset);
  5886   5924         resetAccumulator(pParse, &sAggInfo);
  5887   5925         sqlite3VdbeAddOp1(v, OP_Return, regReset);
  5888   5926        
  5889   5927       } /* endif pGroupBy.  Begin aggregate queries without GROUP BY: */
  5890   5928       else {
  5891         -      ExprList *pDel = 0;
  5892   5929   #ifndef SQLITE_OMIT_BTREECOUNT
  5893   5930         Table *pTab;
  5894   5931         if( (pTab = isSimpleCount(p, &sAggInfo))!=0 ){
  5895   5932           /* If isSimpleCount() returns a pointer to a Table structure, then
  5896   5933           ** the SQL statement is of the form:
  5897   5934           **
  5898   5935           **   SELECT count(*) FROM <tbl>
................................................................................
  5946   5983           }
  5947   5984           sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem);
  5948   5985           sqlite3VdbeAddOp1(v, OP_Close, iCsr);
  5949   5986           explainSimpleCount(pParse, pTab, pBest);
  5950   5987         }else
  5951   5988   #endif /* SQLITE_OMIT_BTREECOUNT */
  5952   5989         {
  5953         -        /* Check if the query is of one of the following forms:
  5954         -        **
  5955         -        **   SELECT min(x) FROM ...
  5956         -        **   SELECT max(x) FROM ...
  5957         -        **
  5958         -        ** If it is, then ask the code in where.c to attempt to sort results
  5959         -        ** as if there was an "ORDER ON x" or "ORDER ON x DESC" clause. 
  5960         -        ** If where.c is able to produce results sorted in this order, then
  5961         -        ** add vdbe code to break out of the processing loop after the 
  5962         -        ** first iteration (since the first iteration of the loop is 
  5963         -        ** guaranteed to operate on the row with the minimum or maximum 
  5964         -        ** value of x, the only row required).
  5965         -        **
  5966         -        ** A special flag must be passed to sqlite3WhereBegin() to slightly
  5967         -        ** modify behavior as follows:
  5968         -        **
  5969         -        **   + If the query is a "SELECT min(x)", then the loop coded by
  5970         -        **     where.c should not iterate over any values with a NULL value
  5971         -        **     for x.
  5972         -        **
  5973         -        **   + The optimizer code in where.c (the thing that decides which
  5974         -        **     index or indices to use) should place a different priority on 
  5975         -        **     satisfying the 'ORDER BY' clause than it does in other cases.
  5976         -        **     Refer to code and comments in where.c for details.
  5977         -        */
  5978         -        ExprList *pMinMax = 0;
  5979         -        u8 flag = WHERE_ORDERBY_NORMAL;
  5980         -        
  5981         -        assert( p->pGroupBy==0 );
  5982         -        assert( flag==0 );
  5983         -        if( p->pHaving==0 ){
  5984         -          flag = minMaxQuery(&sAggInfo, &pMinMax);
  5985         -        }
  5986         -        assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) );
  5987         -
  5988         -        if( flag ){
  5989         -          pMinMax = sqlite3ExprListDup(db, pMinMax, 0);
  5990         -          pDel = pMinMax;
  5991         -          assert( db->mallocFailed || pMinMax!=0 );
  5992         -          if( !db->mallocFailed ){
  5993         -            pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0;
  5994         -            pMinMax->a[0].pExpr->op = TK_COLUMN;
  5995         -          }
  5996         -        }
  5997         -  
  5998   5990           /* This case runs if the aggregate has no GROUP BY clause.  The
  5999   5991           ** processing is much simpler since there is only a single row
  6000   5992           ** of output.
  6001   5993           */
         5994  +        assert( p->pGroupBy==0 );
  6002   5995           resetAccumulator(pParse, &sAggInfo);
  6003         -        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax, 0,flag,0);
         5996  +
         5997  +        /* If this query is a candidate for the min/max optimization, then
         5998  +        ** minMaxFlag will have been previously set to either
         5999  +        ** WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX and pMinMaxOrderBy will
         6000  +        ** be an appropriate ORDER BY expression for the optimization.
         6001  +        */
         6002  +        assert( minMaxFlag==WHERE_ORDERBY_NORMAL || pMinMaxOrderBy!=0 );
         6003  +        assert( pMinMaxOrderBy==0 || pMinMaxOrderBy->nExpr==1 );
         6004  +
         6005  +        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy,
         6006  +                                   0, minMaxFlag, 0);
  6004   6007           if( pWInfo==0 ){
  6005         -          sqlite3ExprListDelete(db, pDel);
  6006   6008             goto select_end;
  6007   6009           }
  6008   6010           updateAccumulator(pParse, &sAggInfo);
  6009         -        assert( pMinMax==0 || pMinMax->nExpr==1 );
  6010   6011           if( sqlite3WhereIsOrdered(pWInfo)>0 ){
  6011   6012             sqlite3VdbeGoto(v, sqlite3WhereBreakLabel(pWInfo));
  6012   6013             VdbeComment((v, "%s() by index",
  6013         -                (flag==WHERE_ORDERBY_MIN?"min":"max")));
         6014  +                (minMaxFlag==WHERE_ORDERBY_MIN?"min":"max")));
  6014   6015           }
  6015   6016           sqlite3WhereEnd(pWInfo);
  6016   6017           finalizeAggFunctions(pParse, &sAggInfo);
  6017   6018         }
  6018   6019   
  6019   6020         sSort.pOrderBy = 0;
  6020   6021         sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL);
  6021   6022         selectInnerLoop(pParse, p, -1, 0, 0, 
  6022   6023                         pDest, addrEnd, addrEnd);
  6023         -      sqlite3ExprListDelete(db, pDel);
  6024   6024       }
  6025   6025       sqlite3VdbeResolveLabel(v, addrEnd);
  6026   6026       
  6027   6027     } /* endif aggregate query */
  6028   6028   
  6029   6029     if( sDistinct.eTnctType==WHERE_DISTINCT_UNORDERED ){
  6030   6030       explainTempTable(pParse, "DISTINCT");
................................................................................
  6048   6048     rc = (pParse->nErr>0);
  6049   6049   
  6050   6050     /* Control jumps to here if an error is encountered above, or upon
  6051   6051     ** successful coding of the SELECT.
  6052   6052     */
  6053   6053   select_end:
  6054   6054     explainSetInteger(pParse->iSelectId, iRestoreSelectId);
  6055         -
         6055  +  sqlite3ExprListDelete(db, pMinMaxOrderBy);
  6056   6056     sqlite3DbFree(db, sAggInfo.aCol);
  6057   6057     sqlite3DbFree(db, sAggInfo.aFunc);
  6058   6058   #if SELECTTRACE_ENABLED
  6059   6059     SELECTTRACE(1,pParse,p,("end processing\n"));
  6060   6060     pParse->nSelectIndent--;
  6061   6061   #endif
  6062   6062     return rc;
  6063   6063   }

Changes to src/shell.c.in.

  1201   1201       }
  1202   1202     }
  1203   1203     if( bSep ){
  1204   1204       utf8_printf(p->out, "%s", p->colSeparator);
  1205   1205     }
  1206   1206   }
  1207   1207   
  1208         -#ifdef SIGINT
  1209   1208   /*
  1210   1209   ** This routine runs when the user presses Ctrl-C
  1211   1210   */
  1212   1211   static void interrupt_handler(int NotUsed){
  1213   1212     UNUSED_PARAMETER(NotUsed);
  1214   1213     seenInterrupt++;
  1215   1214     if( seenInterrupt>2 ) exit(1);
  1216   1215     if( globalDb ) sqlite3_interrupt(globalDb);
  1217   1216   }
         1217  +
         1218  +#if (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
         1219  +/*
         1220  +** This routine runs for console events (e.g. Ctrl-C) on Win32
         1221  +*/
         1222  +static BOOL WINAPI ConsoleCtrlHandler(
         1223  +  DWORD dwCtrlType /* One of the CTRL_*_EVENT constants */
         1224  +){
         1225  +  if( dwCtrlType==CTRL_C_EVENT ){
         1226  +    interrupt_handler(0);
         1227  +    return TRUE;
         1228  +  }
         1229  +  return FALSE;
         1230  +}
  1218   1231   #endif
  1219   1232   
  1220   1233   #ifndef SQLITE_OMIT_AUTHORIZATION
  1221   1234   /*
  1222   1235   ** When the ".auth ON" is set, the following authorizer callback is
  1223   1236   ** invoked.  It always returns SQLITE_OK.
  1224   1237   */
................................................................................
  6685   6698     Argv0 = argv[0];
  6686   6699   
  6687   6700     /* Make sure we have a valid signal handler early, before anything
  6688   6701     ** else is done.
  6689   6702     */
  6690   6703   #ifdef SIGINT
  6691   6704     signal(SIGINT, interrupt_handler);
         6705  +#elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
         6706  +  SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
  6692   6707   #endif
  6693   6708   
  6694   6709   #ifdef SQLITE_SHELL_DBNAME_PROC
  6695   6710     {
  6696   6711       /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
  6697   6712       ** of a C-function that will provide the name of the database file.  Use
  6698   6713       ** this compile-time option to embed this shell program in larger

Changes to src/sqlite.h.in.

  1128   1128   ** CAPI3REF: OS Interface Object
  1129   1129   **
  1130   1130   ** An instance of the sqlite3_vfs object defines the interface between
  1131   1131   ** the SQLite core and the underlying operating system.  The "vfs"
  1132   1132   ** in the name of the object stands for "virtual file system".  See
  1133   1133   ** the [VFS | VFS documentation] for further information.
  1134   1134   **
  1135         -** The value of the iVersion field is initially 1 but may be larger in
  1136         -** future versions of SQLite.  Additional fields may be appended to this
  1137         -** object when the iVersion value is increased.  Note that the structure
  1138         -** of the sqlite3_vfs object changes in the transaction between
  1139         -** SQLite version 3.5.9 and 3.6.0 and yet the iVersion field was not
  1140         -** modified.
         1135  +** The VFS interface is sometimes extended by adding new methods onto
         1136  +** the end.  Each time such an extension occurs, the iVersion field
         1137  +** is incremented.  The iVersion value started out as 1 in
         1138  +** SQLite [version 3.5.0] on [dateof:3.5.0], then increased to 2
         1139  +** with SQLite [version 3.7.0] on [dateof:3.7.0], and then increased
         1140  +** to 3 with SQLite [version 3.7.6] on [dateof:3.7.6].  Additional fields
         1141  +** may be appended to the sqlite3_vfs object and the iVersion value
         1142  +** may increase again in future versions of SQLite.
         1143  +** Note that the structure
         1144  +** of the sqlite3_vfs object changes in the transition from
         1145  +** SQLite [version 3.5.9] to [version 3.6.0] on [dateof:3.6.0]
         1146  +** and yet the iVersion field was not modified.
  1141   1147   **
  1142   1148   ** The szOsFile field is the size of the subclassed [sqlite3_file]
  1143   1149   ** structure used by this VFS.  mxPathname is the maximum length of
  1144   1150   ** a pathname in this VFS.
  1145   1151   **
  1146   1152   ** Registered sqlite3_vfs objects are kept on a linked list formed by
  1147   1153   ** the pNext pointer.  The [sqlite3_vfs_register()]

Changes to src/sqliteInt.h.

  2398   2398   };
  2399   2399   
  2400   2400   /*
  2401   2401   ** The following are the meanings of bits in the Expr.flags field.
  2402   2402   */
  2403   2403   #define EP_FromJoin  0x000001 /* Originates in ON/USING clause of outer join */
  2404   2404   #define EP_Agg       0x000002 /* Contains one or more aggregate functions */
  2405         -                  /* 0x000004 // available for use */
         2405  +#define EP_HasFunc   0x000004 /* Contains one or more functions of any kind */
  2406   2406                     /* 0x000008 // available for use */
  2407   2407   #define EP_Distinct  0x000010 /* Aggregate function with DISTINCT keyword */
  2408   2408   #define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
  2409   2409   #define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
  2410   2410   #define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
  2411   2411   #define EP_Collate   0x000100 /* Tree contains a TK_COLLATE operator */
  2412   2412   #define EP_Generic   0x000200 /* Ignore COLLATE or affinity on this tree */
................................................................................
  2422   2422   #define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
  2423   2423   #define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
  2424   2424   #define EP_Subquery  0x200000 /* Tree contains a TK_SELECT operator */
  2425   2425   #define EP_Alias     0x400000 /* Is an alias for a result set column */
  2426   2426   #define EP_Leaf      0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
  2427   2427   
  2428   2428   /*
  2429         -** Combinations of two or more EP_* flags
         2429  +** The EP_Propagate mask is a set of properties that automatically propagate
         2430  +** upwards into parent nodes.
  2430   2431   */
  2431         -#define EP_Propagate (EP_Collate|EP_Subquery) /* Propagate these bits up tree */
         2432  +#define EP_Propagate (EP_Collate|EP_Subquery|EP_HasFunc)
  2432   2433   
  2433   2434   /*
  2434   2435   ** These macros can be used to test, set, or clear bits in the
  2435   2436   ** Expr.flags field.
  2436   2437   */
  2437   2438   #define ExprHasProperty(E,P)     (((E)->flags&(P))!=0)
  2438   2439   #define ExprHasAllProperty(E,P)  (((E)->flags&(P))==(P))
................................................................................
  2704   2705   #define NC_PartIdx   0x0002  /* True if resolving a partial index WHERE */
  2705   2706   #define NC_IsCheck   0x0004  /* True if resolving names in a CHECK constraint */
  2706   2707   #define NC_InAggFunc 0x0008  /* True if analyzing arguments to an agg func */
  2707   2708   #define NC_HasAgg    0x0010  /* One or more aggregate functions seen */
  2708   2709   #define NC_IdxExpr   0x0020  /* True if resolving columns of CREATE INDEX */
  2709   2710   #define NC_VarSelect 0x0040  /* A correlated subquery has been seen */
  2710   2711   #define NC_MinMaxAgg 0x1000  /* min/max aggregates seen.  See note above */
         2712  +#define NC_Complex   0x2000  /* True if a function or subquery seen */
  2711   2713   
  2712   2714   /*
  2713   2715   ** An instance of the following structure contains all information
  2714   2716   ** needed to generate code for a single SELECT statement.
  2715   2717   **
  2716   2718   ** nLimit is set to -1 if there is no LIMIT clause.  nOffset is set to 0.
  2717   2719   ** If there is a LIMIT clause, the parser sets nLimit to the value of the
................................................................................
  2774   2776   #define SF_NestedFrom     0x00800  /* Part of a parenthesized FROM clause */
  2775   2777   #define SF_MinMaxAgg      0x01000  /* Aggregate containing min() or max() */
  2776   2778   #define SF_Recursive      0x02000  /* The recursive part of a recursive CTE */
  2777   2779   #define SF_FixedLimit     0x04000  /* nSelectRow set by a constant LIMIT */
  2778   2780   #define SF_MaybeConvert   0x08000  /* Need convertCompoundSelectToSubquery() */
  2779   2781   #define SF_Converted      0x10000  /* By convertCompoundSelectToSubquery() */
  2780   2782   #define SF_IncludeHidden  0x20000  /* Include hidden columns in output */
         2783  +#define SF_ComplexResult  0x40000  /* Result set contains subquery or function */
  2781   2784   
  2782   2785   
  2783   2786   /*
  2784   2787   ** The results of a SELECT can be distributed in several ways, as defined
  2785   2788   ** by one of the following macros.  The "SRT" prefix means "SELECT Result
  2786   2789   ** Type".
  2787   2790   **
................................................................................
  3757   3760   void sqlite3SelectDelete(sqlite3*, Select*);
  3758   3761   Table *sqlite3SrcListLookup(Parse*, SrcList*);
  3759   3762   int sqlite3IsReadOnly(Parse*, Table*, int);
  3760   3763   void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
  3761   3764   #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
  3762   3765   Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*);
  3763   3766   #endif
  3764         -void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
  3765         -void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
         3767  +void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*, Expr*);
         3768  +void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*,Expr*);
  3766   3769   WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
  3767   3770   void sqlite3WhereEnd(WhereInfo*);
  3768   3771   LogEst sqlite3WhereOutputRowCount(WhereInfo*);
  3769   3772   int sqlite3WhereIsDistinct(WhereInfo*);
  3770   3773   int sqlite3WhereIsOrdered(WhereInfo*);
  3771   3774   int sqlite3WhereOrderedInnerLoop(WhereInfo*);
  3772   3775   int sqlite3WhereIsSorted(WhereInfo*);
................................................................................
  3882   3885   void sqlite3RegisterDateTimeFunctions(void);
  3883   3886   void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*);
  3884   3887   int sqlite3SafetyCheckOk(sqlite3*);
  3885   3888   int sqlite3SafetyCheckSickOrOk(sqlite3*);
  3886   3889   void sqlite3ChangeCookie(Parse*, int);
  3887   3890   
  3888   3891   #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
  3889         -void sqlite3MaterializeView(Parse*, Table*, Expr*, int);
         3892  +void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,Expr*,int);
  3890   3893   #endif
  3891   3894   
  3892   3895   #ifndef SQLITE_OMIT_TRIGGER
  3893   3896     void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
  3894   3897                              Expr*,int, int);
  3895   3898     void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*);
  3896   3899     void sqlite3DropTrigger(Parse*, SrcList*, int);

Changes to src/trigger.c.

   707    707   
   708    708       switch( pStep->op ){
   709    709         case TK_UPDATE: {
   710    710           sqlite3Update(pParse, 
   711    711             targetSrcList(pParse, pStep),
   712    712             sqlite3ExprListDup(db, pStep->pExprList, 0), 
   713    713             sqlite3ExprDup(db, pStep->pWhere, 0), 
   714         -          pParse->eOrconf
          714  +          pParse->eOrconf, 0, 0, 0
   715    715           );
   716    716           break;
   717    717         }
   718    718         case TK_INSERT: {
   719    719           sqlite3Insert(pParse, 
   720    720             targetSrcList(pParse, pStep),
   721    721             sqlite3SelectDup(db, pStep->pSelect, 0), 
................................................................................
   723    723             pParse->eOrconf
   724    724           );
   725    725           break;
   726    726         }
   727    727         case TK_DELETE: {
   728    728           sqlite3DeleteFrom(pParse, 
   729    729             targetSrcList(pParse, pStep),
   730         -          sqlite3ExprDup(db, pStep->pWhere, 0)
          730  +          sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0, 0
   731    731           );
   732    732           break;
   733    733         }
   734    734         default: assert( pStep->op==TK_SELECT ); {
   735    735           SelectDest sDest;
   736    736           Select *pSelect = sqlite3SelectDup(db, pStep->pSelect, 0);
   737    737           sqlite3SelectDestInit(&sDest, SRT_Discard, 0);

Changes to src/update.c.

    87     87   *            onError   pTabList      pChanges             pWhere
    88     88   */
    89     89   void sqlite3Update(
    90     90     Parse *pParse,         /* The parser context */
    91     91     SrcList *pTabList,     /* The table in which we should change things */
    92     92     ExprList *pChanges,    /* Things to be changed */
    93     93     Expr *pWhere,          /* The WHERE clause.  May be null */
    94         -  int onError            /* How to handle constraint errors */
           94  +  int onError,           /* How to handle constraint errors */
           95  +  ExprList *pOrderBy,    /* ORDER BY clause. May be null */
           96  +  Expr *pLimit,          /* LIMIT clause. May be null */
           97  +  Expr *pOffset          /* OFFSET clause. May be null */
    95     98   ){
    96     99     int i, j;              /* Loop counters */
    97    100     Table *pTab;           /* The table to be updated */
    98    101     int addrTop = 0;       /* VDBE instruction address of the start of the loop */
    99    102     WhereInfo *pWInfo;     /* Information about the WHERE clause */
   100    103     Vdbe *v;               /* The virtual database engine */
   101    104     Index *pIdx;           /* For looping over indices */
................................................................................
   171    174   # define isView 0
   172    175   # define tmask 0
   173    176   #endif
   174    177   #ifdef SQLITE_OMIT_VIEW
   175    178   # undef isView
   176    179   # define isView 0
   177    180   #endif
          181  +
          182  +#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
          183  +  if( !isView ){
          184  +    pWhere = sqlite3LimitWhere(
          185  +        pParse, pTabList, pWhere, pOrderBy, pLimit, pOffset, "UPDATE"
          186  +    );
          187  +    pOrderBy = 0;
          188  +    pLimit = pOffset = 0;
          189  +  }
          190  +#endif
   178    191   
   179    192     if( sqlite3ViewGetColumnNames(pParse, pTab) ){
   180    193       goto update_cleanup;
   181    194     }
   182    195     if( sqlite3IsReadOnly(pParse, pTab, tmask) ){
   183    196       goto update_cleanup;
   184    197     }
................................................................................
   340    353     }
   341    354   
   342    355     /* If we are trying to update a view, realize that view into
   343    356     ** an ephemeral table.
   344    357     */
   345    358   #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
   346    359     if( isView ){
   347         -    sqlite3MaterializeView(pParse, pTab, pWhere, iDataCur);
          360  +    sqlite3MaterializeView(pParse, pTab, 
          361  +        pWhere, pOrderBy, pLimit, pOffset, iDataCur
          362  +    );
          363  +    pOrderBy = 0;
          364  +    pLimit = pOffset = 0;
   348    365     }
   349    366   #endif
   350    367   
   351    368     /* Resolve the column names in all the expressions in the
   352    369     ** WHERE clause.
   353    370     */
   354    371     if( sqlite3ResolveExprNames(&sNC, pWhere) ){
................................................................................
   724    741   
   725    742   update_cleanup:
   726    743     sqlite3AuthContextPop(&sContext);
   727    744     sqlite3DbFree(db, aXRef); /* Also frees aRegIdx[] and aToOpen[] */
   728    745     sqlite3SrcListDelete(db, pTabList);
   729    746     sqlite3ExprListDelete(db, pChanges);
   730    747     sqlite3ExprDelete(db, pWhere);
          748  +#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) 
          749  +  sqlite3ExprListDelete(db, pOrderBy);
          750  +  sqlite3ExprDelete(db, pLimit);
          751  +  sqlite3ExprDelete(db, pOffset);
          752  +#endif
   731    753     return;
   732    754   }
   733    755   /* Make sure "isView" and other macros defined above are undefined. Otherwise
   734    756   ** they may interfere with compilation of other functions in this file
   735    757   ** (or in another file, if this file becomes part of the amalgamation).  */
   736    758   #ifdef isView
   737    759    #undef isView

Changes to src/util.c.

   383    383     }else if( *z=='+' ){
   384    384       z+=incr;
   385    385     }
   386    386   
   387    387     /* copy max significant digits to significand */
   388    388     while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){
   389    389       s = s*10 + (*z - '0');
   390         -    z+=incr, nDigits++;
          390  +    z+=incr; nDigits++;
   391    391     }
   392    392   
   393    393     /* skip non-significant significand digits
   394    394     ** (increase exponent by d to shift decimal left) */
   395         -  while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++, d++;
          395  +  while( z<zEnd && sqlite3Isdigit(*z) ){ z+=incr; nDigits++; d++; }
   396    396     if( z>=zEnd ) goto do_atof_calc;
   397    397   
   398    398     /* if decimal point is present */
   399    399     if( *z=='.' ){
   400    400       z+=incr;
   401    401       /* copy digits from after decimal to significand
   402    402       ** (decrease exponent by d to shift decimal right) */
   403    403       while( z<zEnd && sqlite3Isdigit(*z) ){
   404    404         if( s<((LARGEST_INT64-9)/10) ){
   405    405           s = s*10 + (*z - '0');
   406    406           d--;
   407    407         }
   408         -      z+=incr, nDigits++;
          408  +      z+=incr; nDigits++;
   409    409       }
   410    410     }
   411    411     if( z>=zEnd ) goto do_atof_calc;
   412    412   
   413    413     /* if exponent is present */
   414    414     if( *z=='e' || *z=='E' ){
   415    415       z+=incr;

Changes to src/vdbeaux.c.

  3039   3039   
  3040   3040   /*
  3041   3041   ** Delete an entire VDBE.
  3042   3042   */
  3043   3043   void sqlite3VdbeDelete(Vdbe *p){
  3044   3044     sqlite3 *db;
  3045   3045   
  3046         -  if( NEVER(p==0) ) return;
         3046  +  assert( p!=0 );
  3047   3047     db = p->db;
  3048   3048     assert( sqlite3_mutex_held(db->mutex) );
  3049   3049     sqlite3VdbeClearObject(db, p);
  3050   3050     if( p->pPrev ){
  3051   3051       p->pPrev->pNext = p->pNext;
  3052   3052     }else{
  3053   3053       assert( db->pVdbe==p );

Changes to src/vdbemem.c.

   346    346   ** This routine calls the finalize method for that function.  The
   347    347   ** result of the aggregate is stored back into pMem.
   348    348   **
   349    349   ** Return SQLITE_ERROR if the finalizer reports an error.  SQLITE_OK
   350    350   ** otherwise.
   351    351   */
   352    352   int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
   353         -  int rc = SQLITE_OK;
   354         -  if( ALWAYS(pFunc && pFunc->xFinalize) ){
   355         -    sqlite3_context ctx;
   356         -    Mem t;
   357         -    assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
   358         -    assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
   359         -    memset(&ctx, 0, sizeof(ctx));
   360         -    memset(&t, 0, sizeof(t));
   361         -    t.flags = MEM_Null;
   362         -    t.db = pMem->db;
   363         -    ctx.pOut = &t;
   364         -    ctx.pMem = pMem;
   365         -    ctx.pFunc = pFunc;
   366         -    pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */
   367         -    assert( (pMem->flags & MEM_Dyn)==0 );
   368         -    if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
   369         -    memcpy(pMem, &t, sizeof(t));
   370         -    rc = ctx.isError;
   371         -  }
   372         -  return rc;
          353  +  sqlite3_context ctx;
          354  +  Mem t;
          355  +  assert( pFunc!=0 );
          356  +  assert( pFunc->xFinalize!=0 );
          357  +  assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
          358  +  assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
          359  +  memset(&ctx, 0, sizeof(ctx));
          360  +  memset(&t, 0, sizeof(t));
          361  +  t.flags = MEM_Null;
          362  +  t.db = pMem->db;
          363  +  ctx.pOut = &t;
          364  +  ctx.pMem = pMem;
          365  +  ctx.pFunc = pFunc;
          366  +  pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */
          367  +  assert( (pMem->flags & MEM_Dyn)==0 );
          368  +  if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
          369  +  memcpy(pMem, &t, sizeof(t));
          370  +  return ctx.isError;
   373    371   }
   374    372   
   375    373   /*
   376    374   ** If the memory cell contains a value that must be freed by
   377    375   ** invoking the external callback in Mem.xDel, then this routine
   378    376   ** will free that value.  It also sets Mem.flags to MEM_Null.
   379    377   **

Changes to src/wal.c.

   127    127   ** WAL-INDEX FORMAT
   128    128   **
   129    129   ** Conceptually, the wal-index is shared memory, though VFS implementations
   130    130   ** might choose to implement the wal-index using a mmapped file.  Because
   131    131   ** the wal-index is shared memory, SQLite does not support journal_mode=WAL 
   132    132   ** on a network filesystem.  All users of the database must be able to
   133    133   ** share memory.
          134  +**
          135  +** In the default unix and windows implementation, the wal-index is a mmapped
          136  +** file whose name is the database name with a "-shm" suffix added.  For that
          137  +** reason, the wal-index is sometimes called the "shm" file.
   134    138   **
   135    139   ** The wal-index is transient.  After a crash, the wal-index can (and should
   136    140   ** be) reconstructed from the original WAL file.  In fact, the VFS is required
   137    141   ** to either truncate or zero the header of the wal-index when the last
   138    142   ** connection to it closes.  Because the wal-index is transient, it can
   139    143   ** use an architecture-specific format; it does not have to be cross-platform.
   140    144   ** Hence, unlike the database and WAL file formats which store all values
................................................................................
   267    271   ** WALINDEX_MAX_VERSION, then no read-transaction is opened and SQLite
   268    272   ** returns SQLITE_CANTOPEN.
   269    273   */
   270    274   #define WAL_MAX_VERSION      3007000
   271    275   #define WALINDEX_MAX_VERSION 3007000
   272    276   
   273    277   /*
   274         -** Indices of various locking bytes.   WAL_NREADER is the number
          278  +** Index numbers for various locking bytes.   WAL_NREADER is the number
   275    279   ** of available reader locks and should be at least 3.  The default
   276    280   ** is SQLITE_SHM_NLOCK==8 and  WAL_NREADER==5.
          281  +**
          282  +** Technically, the various VFSes are free to implement these locks however
          283  +** they see fit.  However, compatibility is encouraged so that VFSes can
          284  +** interoperate.  The standard implemention used on both unix and windows
          285  +** is for the index number to indicate a byte offset into the
          286  +** WalCkptInfo.aLock[] array in the wal-index header.  In other words, all
          287  +** locks are on the shm file.  The WALINDEX_LOCK_OFFSET constant (which
          288  +** should be 120) is the location in the shm file for the first locking
          289  +** byte.
   277    290   */
   278    291   #define WAL_WRITE_LOCK         0
   279    292   #define WAL_ALL_BUT_WRITE      1
   280    293   #define WAL_CKPT_LOCK          1
   281    294   #define WAL_RECOVER_LOCK       2
   282    295   #define WAL_READ_LOCK(I)       (3+(I))
   283    296   #define WAL_NREADER            (SQLITE_SHM_NLOCK-3)
................................................................................
   393    406   #define WALINDEX_LOCK_OFFSET (sizeof(WalIndexHdr)*2+offsetof(WalCkptInfo,aLock))
   394    407   #define WALINDEX_HDR_SIZE    (sizeof(WalIndexHdr)*2+sizeof(WalCkptInfo))
   395    408   
   396    409   /* Size of header before each frame in wal */
   397    410   #define WAL_FRAME_HDRSIZE 24
   398    411   
   399    412   /* Size of write ahead log header, including checksum. */
   400         -/* #define WAL_HDRSIZE 24 */
   401    413   #define WAL_HDRSIZE 32
   402    414   
   403    415   /* WAL magic value. Either this value, or the same value with the least
   404    416   ** significant bit also set (WAL_MAGIC | 0x00000001) is stored in 32-bit
   405    417   ** big-endian format in the first 4 bytes of a WAL file.
   406    418   **
   407    419   ** If the LSB is set, then the checksums for each frame within the WAL
................................................................................
  2146   2158   ** recovery) return a positive error code.
  2147   2159   **
  2148   2160   ** The useWal parameter is true to force the use of the WAL and disable
  2149   2161   ** the case where the WAL is bypassed because it has been completely
  2150   2162   ** checkpointed.  If useWal==0 then this routine calls walIndexReadHdr() 
  2151   2163   ** to make a copy of the wal-index header into pWal->hdr.  If the 
  2152   2164   ** wal-index header has changed, *pChanged is set to 1 (as an indication 
  2153         -** to the caller that the local paget cache is obsolete and needs to be 
         2165  +** to the caller that the local page cache is obsolete and needs to be 
  2154   2166   ** flushed.)  When useWal==1, the wal-index header is assumed to already
  2155   2167   ** be loaded and the pChanged parameter is unused.
  2156   2168   **
  2157   2169   ** The caller must set the cnt parameter to the number of prior calls to
  2158   2170   ** this routine during the current read attempt that returned WAL_RETRY.
  2159   2171   ** This routine will start taking more aggressive measures to clear the
  2160   2172   ** race conditions after multiple WAL_RETRY returns, and after an excessive

Changes to src/walker.c.

   104    104   */
   105    105   int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
   106    106     SrcList *pSrc;
   107    107     int i;
   108    108     struct SrcList_item *pItem;
   109    109   
   110    110     pSrc = p->pSrc;
   111         -  if( ALWAYS(pSrc) ){
   112         -    for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
   113         -      if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){
   114         -        return WRC_Abort;
   115         -      }
   116         -      if( pItem->fg.isTabFunc
   117         -       && sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg)
   118         -      ){
   119         -        return WRC_Abort;
   120         -      }
          111  +  assert( pSrc!=0 );
          112  +  for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
          113  +    if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){
          114  +      return WRC_Abort;
          115  +    }
          116  +    if( pItem->fg.isTabFunc
          117  +     && sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg)
          118  +    ){
          119  +      return WRC_Abort;
   121    120       }
   122    121     }
   123    122     return WRC_Continue;
   124    123   } 
   125    124   
   126    125   /*
   127    126   ** Call sqlite3WalkExpr() for every expression in Select statement p.

Changes to src/where.c.

  1859   1859     sqlite3DbFreeNN(db, p);
  1860   1860   }
  1861   1861   
  1862   1862   /*
  1863   1863   ** Free a WhereInfo structure
  1864   1864   */
  1865   1865   static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
  1866         -  if( ALWAYS(pWInfo) ){
  1867         -    int i;
  1868         -    for(i=0; i<pWInfo->nLevel; i++){
  1869         -      WhereLevel *pLevel = &pWInfo->a[i];
  1870         -      if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE) ){
  1871         -        sqlite3DbFree(db, pLevel->u.in.aInLoop);
  1872         -      }
         1866  +  int i;
         1867  +  assert( pWInfo!=0 );
         1868  +  for(i=0; i<pWInfo->nLevel; i++){
         1869  +    WhereLevel *pLevel = &pWInfo->a[i];
         1870  +    if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE) ){
         1871  +      sqlite3DbFree(db, pLevel->u.in.aInLoop);
  1873   1872       }
  1874         -    sqlite3WhereClauseClear(&pWInfo->sWC);
  1875         -    while( pWInfo->pLoops ){
  1876         -      WhereLoop *p = pWInfo->pLoops;
  1877         -      pWInfo->pLoops = p->pNextLoop;
  1878         -      whereLoopDelete(db, p);
  1879         -    }
  1880         -    sqlite3DbFreeNN(db, pWInfo);
  1881   1873     }
         1874  +  sqlite3WhereClauseClear(&pWInfo->sWC);
         1875  +  while( pWInfo->pLoops ){
         1876  +    WhereLoop *p = pWInfo->pLoops;
         1877  +    pWInfo->pLoops = p->pNextLoop;
         1878  +    whereLoopDelete(db, p);
         1879  +  }
         1880  +  sqlite3DbFreeNN(db, pWInfo);
  1882   1881   }
  1883   1882   
  1884   1883   /*
  1885   1884   ** Return TRUE if all of the following are true:
  1886   1885   **
  1887   1886   **   (1)  X has the same or lower cost that Y
  1888   1887   **   (2)  X uses fewer WHERE clause terms than Y
................................................................................
  2866   2865           pNew->prereq = mPrereq | pTerm->prereqRight;
  2867   2866           rc = whereLoopInsert(pBuilder, pNew);
  2868   2867         }
  2869   2868       }
  2870   2869     }
  2871   2870   #endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
  2872   2871   
  2873         -  /* Loop over all indices
  2874         -  */
  2875         -  for(; rc==SQLITE_OK && pProbe; pProbe=pProbe->pNext, iSortIdx++){
         2872  +  /* Loop over all indices. If there was an INDEXED BY clause, then only 
         2873  +  ** consider index pProbe.  */
         2874  +  for(; rc==SQLITE_OK && pProbe; 
         2875  +      pProbe=(pSrc->pIBIndex ? 0 : pProbe->pNext), iSortIdx++
         2876  +  ){
  2876   2877       if( pProbe->pPartIdxWhere!=0
  2877   2878        && !whereUsablePartialIndex(pSrc->iCursor, pWC, pProbe->pPartIdxWhere) ){
  2878   2879         testcase( pNew->iTab!=pSrc->iCursor );  /* See ticket [98d973b8f5] */
  2879   2880         continue;  /* Partial index inappropriate for this query */
  2880   2881       }
  2881   2882       rSize = pProbe->aiRowLogEst[0];
  2882   2883       pNew->u.btree.nEq = 0;
................................................................................
  2978   2979         pTab->tabFlags |= TF_StatsUsed;
  2979   2980       }
  2980   2981   #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  2981   2982       sqlite3Stat4ProbeFree(pBuilder->pRec);
  2982   2983       pBuilder->nRecValid = 0;
  2983   2984       pBuilder->pRec = 0;
  2984   2985   #endif
  2985         -
  2986         -    /* If there was an INDEXED BY clause, then only that one index is
  2987         -    ** considered. */
  2988         -    if( pSrc->pIBIndex ) break;
  2989   2986     }
  2990   2987     return rc;
  2991   2988   }
  2992   2989   
  2993   2990   #ifndef SQLITE_OMIT_VIRTUALTABLE
  2994   2991   
  2995   2992   /*

Changes to src/wherecode.c.

   290    290   ** term was originally TERM_LIKE, then the parent gets TERM_LIKECOND instead.
   291    291   ** The TERM_LIKECOND marking indicates that the term should be coded inside
   292    292   ** a conditional such that is only evaluated on the second pass of a
   293    293   ** LIKE-optimization loop, when scanning BLOBs instead of strings.
   294    294   */
   295    295   static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
   296    296     int nLoop = 0;
   297         -  while( ALWAYS(pTerm!=0)
   298         -      && (pTerm->wtFlags & TERM_CODED)==0
          297  +  assert( pTerm!=0 );
          298  +  while( (pTerm->wtFlags & TERM_CODED)==0
   299    299         && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
   300    300         && (pLevel->notReady & pTerm->prereqAll)==0
   301    301     ){
   302    302       if( nLoop && (pTerm->wtFlags & TERM_LIKE)!=0 ){
   303    303         pTerm->wtFlags |= TERM_LIKECOND;
   304    304       }else{
   305    305         pTerm->wtFlags |= TERM_CODED;
   306    306       }
   307    307       if( pTerm->iParent<0 ) break;
   308    308       pTerm = &pTerm->pWC->a[pTerm->iParent];
          309  +    assert( pTerm!=0 );
   309    310       pTerm->nChild--;
   310    311       if( pTerm->nChild!=0 ) break;
   311    312       nLoop++;
   312    313     }
   313    314   }
   314    315   
   315    316   /*

Changes to src/whereexpr.c.

   979    979     Bitmask extraRight = 0;          /* Extra dependencies on LEFT JOIN */
   980    980     Expr *pStr1 = 0;                 /* RHS of LIKE/GLOB operator */
   981    981     int isComplete = 0;              /* RHS of LIKE/GLOB ends with wildcard */
   982    982     int noCase = 0;                  /* uppercase equivalent to lowercase */
   983    983     int op;                          /* Top-level operator.  pExpr->op */
   984    984     Parse *pParse = pWInfo->pParse;  /* Parsing context */
   985    985     sqlite3 *db = pParse->db;        /* Database connection */
   986         -  unsigned char eOp2;              /* op2 value for LIKE/REGEXP/GLOB */
          986  +  unsigned char eOp2 = 0;          /* op2 value for LIKE/REGEXP/GLOB */
   987    987     int nLeft;                       /* Number of elements on left side vector */
   988    988   
   989    989     if( db->mallocFailed ){
   990    990       return;
   991    991     }
   992    992     pTerm = &pWC->a[idxTerm];
   993    993     pMaskSet = &pWInfo->sMaskSet;
................................................................................
  1223   1223     ** not normally optimized for ordinary tables.  In other words, OP
  1224   1224     ** is one of MATCH, LIKE, GLOB, REGEXP, !=, IS, IS NOT, or NOT NULL.
  1225   1225     ** This information is used by the xBestIndex methods of
  1226   1226     ** virtual tables.  The native query optimizer does not attempt
  1227   1227     ** to do anything with MATCH functions.
  1228   1228     */
  1229   1229     if( pWC->op==TK_AND ){
  1230         -    Expr *pRight, *pLeft;
         1230  +    Expr *pRight = 0, *pLeft = 0;
  1231   1231       int res = isAuxiliaryVtabOperator(pExpr, &eOp2, &pLeft, &pRight);
  1232   1232       while( res-- > 0 ){
  1233   1233         int idxNew;
  1234   1234         WhereTerm *pNewTerm;
  1235   1235         Bitmask prereqColumn, prereqExpr;
  1236   1236   
  1237   1237         prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight);

Deleted test/checkfreelist.test.

     1         -# 2017-10-11
     2         -#
     3         -# The author disclaims copyright to this source code.  In place of
     4         -# a legal notice, here is a blessing:
     5         -#
     6         -#    May you do good and not evil.
     7         -#    May you find forgiveness for yourself and forgive others.
     8         -#    May you share freely, never taking more than you give.
     9         -#
    10         -#***********************************************************************
    11         -# This file implements regression tests for SQLite library.  The
    12         -# focus of this file is testing the checkfreelist extension.
    13         -#
    14         -
    15         -set testdir [file dirname $argv0]
    16         -source $testdir/tester.tcl
    17         -set testprefix checkfreelist
    18         -
    19         -ifcapable !vtab||!compound {
    20         -  finish_test
    21         -  return
    22         -}
    23         -
    24         -if {[file exists ../checkfreelist.so]==0} {
    25         -  finish_test
    26         -  return
    27         -}
    28         -
    29         -do_execsql_test 1.0 {
    30         -  CREATE TABLE t1(a, b);
    31         -}
    32         -
    33         -db enable_load_extension 1
    34         -do_execsql_test 1.1 {
    35         -  SELECT load_extension('../checkfreelist.so');
    36         -} {{}}
    37         -
    38         -do_execsql_test 1.2 { SELECT checkfreelist('main') } {ok}
    39         -do_execsql_test 1.3 {
    40         -  WITH s(i) AS (
    41         -    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10000
    42         -  )
    43         -  INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM s;
    44         -  DELETE FROM t1 WHERE rowid%3;
    45         -  PRAGMA freelist_count;
    46         -} {6726}
    47         -
    48         -do_execsql_test 1.4 { SELECT checkfreelist('main') } {ok}
    49         -do_execsql_test 1.5 {
    50         -  WITH freelist_trunk(i, d, n) AS (
    51         -    SELECT 1, NULL, sqlite_readint32(data, 32) FROM sqlite_dbpage WHERE pgno=1
    52         -      UNION ALL
    53         -    SELECT n, data, sqlite_readint32(data) 
    54         -    FROM freelist_trunk, sqlite_dbpage WHERE pgno=n
    55         -  )
    56         -  SELECT i FROM freelist_trunk WHERE i!=1;
    57         -} {
    58         -  10010 9716 9344 8970 8596 8223 7848 7475 7103 6728 6355 5983 5609 5235
    59         -  4861 4488 4113 3741 3368 2993 2620 2248 1873 1500 1126 753 378 5
    60         -}
    61         -
    62         -do_execsql_test 1.6 { SELECT checkfreelist('main') } {ok}
    63         -
    64         -proc set_int {blob idx newval} {
    65         -  binary scan $blob I* ints
    66         -  lset ints $idx $newval
    67         -  binary format I* $ints
    68         -}
    69         -db func set_int set_int
    70         -
    71         -proc get_int {blob idx} {
    72         -  binary scan $blob I* ints
    73         -  lindex $ints $idx
    74         -}
    75         -db func get_int get_int
    76         -
    77         -do_execsql_test 1.7 {
    78         -  BEGIN;
    79         -    UPDATE sqlite_dbpage 
    80         -      SET data = set_int(data, 1, get_int(data, 1)-1) 
    81         -      WHERE pgno=4861;
    82         -    SELECT checkfreelist('main');
    83         -  ROLLBACK;
    84         -} {{free-list count mismatch: actual=6725 header=6726}}
    85         -
    86         -do_execsql_test 1.8 {
    87         -  BEGIN;
    88         -    UPDATE sqlite_dbpage 
    89         -      SET data = set_int(data, 5, (SELECT * FROM pragma_page_count)+1)
    90         -      WHERE pgno=4861;
    91         -    SELECT checkfreelist('main');
    92         -  ROLLBACK;
    93         -} {{leaf page 10093 is out of range (child 3 of trunk page 4861)}}
    94         -
    95         -do_execsql_test 1.9 {
    96         -  BEGIN;
    97         -    UPDATE sqlite_dbpage 
    98         -      SET data = set_int(data, 5, 0)
    99         -      WHERE pgno=4861;
   100         -    SELECT checkfreelist('main');
   101         -  ROLLBACK;
   102         -} {{leaf page 0 is out of range (child 3 of trunk page 4861)}}
   103         -
   104         -do_execsql_test 1.10 {
   105         -  BEGIN;
   106         -    UPDATE sqlite_dbpage 
   107         -      SET data = set_int(data, get_int(data, 1)+1, 0)
   108         -      WHERE pgno=5;
   109         -    SELECT checkfreelist('main');
   110         -  ROLLBACK;
   111         -} {{leaf page 0 is out of range (child 247 of trunk page 5)}}
   112         -
   113         -do_execsql_test 1.11 {
   114         -  BEGIN;
   115         -    UPDATE sqlite_dbpage 
   116         -      SET data = set_int(data, 1, 249)
   117         -      WHERE pgno=5;
   118         -    SELECT checkfreelist('main');
   119         -  ROLLBACK;
   120         -} {{leaf count out of range (249) on trunk page 5}}
   121         -
   122         -finish_test
   123         -

Changes to test/dbpage.test.

    45     45   } {4 X'0D00000016'}
    46     46   do_execsql_test 140 {
    47     47     SELECT pgno, quote(substr(data,1,5)) FROM sqlite_dbpage WHERE pgno=5;
    48     48   } {}
    49     49   do_execsql_test 150 {
    50     50     SELECT pgno, quote(substr(data,1,5)) FROM sqlite_dbpage WHERE pgno=0;
    51     51   } {}
           52  +do_execsql_test 160 {
           53  +  ATTACH ':memory:' AS aux1;
           54  +  PRAGMA aux1.page_size=4096;
           55  +  CREATE TABLE aux1.t2(a,b,c);
           56  +  INSERT INTO t2 VALUES(11,12,13);
           57  +  SELECT pgno, quote(substr(data,1,5)) FROM sqlite_dbpage('aux1');
           58  +} {1 X'53514C6974' 2 X'0D00000001'}
           59  +do_execsql_test 170 {
           60  +  CREATE TABLE aux1.x3(x,y,z);
           61  +  INSERT INTO x3(x,y,z) VALUES(1,'main',1),(2,'aux1',1);
           62  +  SELECT pgno, schema, substr(data,1,6)
           63  +    FROM sqlite_dbpage, x3
           64  +   WHERE sqlite_dbpage.schema=x3.y AND sqlite_dbpage.pgno=x3.z
           65  +   ORDER BY x3.x;
           66  +} {1 main SQLite 1 aux1 SQLite}
    52     67   
    53     68   do_execsql_test 200 {
    54     69     CREATE TEMP TABLE saved_content(x);
    55     70     INSERT INTO saved_content(x) SELECT data FROM sqlite_dbpage WHERE pgno=4;
    56     71     UPDATE sqlite_dbpage SET data=zeroblob(4096) WHERE pgno=4;
    57     72   } {}
    58     73   do_catchsql_test 210 {
................................................................................
    63     78   } {1 X'53514C6974' 2 X'0500000001' 3 X'0D0000004E' 4 X'0000000000'}
    64     79   do_execsql_test 230 {
    65     80     UPDATE sqlite_dbpage SET data=(SELECT x FROM saved_content) WHERE pgno=4;
    66     81   } {}
    67     82   do_catchsql_test 230 {
    68     83     PRAGMA integrity_check;
    69     84   } {0 ok}
    70         -
    71         -
    72         -
           85  +do_execsql_test 240 {
           86  +  DELETE FROM saved_content;
           87  +  INSERT INTO saved_content(x) 
           88  +     SELECT data FROM sqlite_dbpage WHERE schema='aux1' AND pgno=2;
           89  +} {}
           90  +do_execsql_test 241 {
           91  +  UPDATE sqlite_dbpage SET data=zeroblob(4096) WHERE pgno=2 AND schema='aux1';
           92  +} {}
           93  +do_catchsql_test 250 {
           94  +  PRAGMA aux1.integrity_check;
           95  +} {1 {database disk image is malformed}}
           96  +do_execsql_test 260 {
           97  +  UPDATE sqlite_dbpage SET data=(SELECT x FROM saved_content)
           98  +   WHERE pgno=2 AND schema='aux1';
           99  +} {}
          100  +do_catchsql_test 270 {
          101  +  PRAGMA aux1.integrity_check;
          102  +} {0 ok}
    73    103   
    74    104   finish_test

Changes to test/indexedby.test.

   359    359   } {1 1 3}
   360    360   do_execsql_test 11.9 {
   361    361     SELECT a,b,c FROM x2 INDEXED BY x2i WHERE a=1 AND b=1 AND c='3.0';
   362    362   } {1 1 3}
   363    363   do_eqp_test 11.10 {
   364    364     SELECT a,b,c FROM x2 INDEXED BY x2i WHERE a=1 AND b=1 AND c='3.0';
   365    365   } {0 0 0 {SEARCH TABLE x2 USING COVERING INDEX x2i (a=? AND b=? AND rowid=?)}}
          366  +
          367  +#-------------------------------------------------------------------------
          368  +# Check INDEXED BY works (throws an exception) with partial indexes that 
          369  +# cannot be used.
          370  +do_execsql_test 12.1 {
          371  +  CREATE TABLE o1(x INTEGER PRIMARY KEY, y, z);
          372  +  CREATE INDEX p1 ON o1(z);
          373  +  CREATE INDEX p2 ON o1(y) WHERE z=1;
          374  +}
          375  +do_catchsql_test 12.2 {
          376  +  SELECT * FROM o1 INDEXED BY p2 ORDER BY 1;
          377  +} {1 {no query solution}}
          378  +do_execsql_test 12.3 {
          379  +  DROP INDEX p1;
          380  +  DROP INDEX p2;
          381  +  CREATE INDEX p2 ON o1(y) WHERE z=1;
          382  +  CREATE INDEX p1 ON o1(z);
          383  +}
          384  +do_catchsql_test 12.4 {
          385  +  SELECT * FROM o1 INDEXED BY p2 ORDER BY 1;
          386  +} {1 {no query solution}}
   366    387   
   367    388   finish_test

Changes to test/json101.test.

   717    717     /* } */
   718    718   } {1}
   719    719   do_execsql_test json-11.3 {
   720    720     /* Too deep by one { */
   721    721     SELECT json_valid(replace(printf('%.2001c0%.2001c','[','}'),'[','{"a":'));
   722    722     /* } */
   723    723   } {0}
          724  +
          725  +# 2017-10-27.  Demonstrate the ability to access an element from
          726  +# a json structure even though the element name constains a "."
          727  +# character, by quoting the element name in the path.
          728  +#
          729  +do_execsql_test json-12.100 {
          730  +  CREATE TABLE t12(x);
          731  +  INSERT INTO t12(x) VALUES(
          732  +    '{"settings":
          733  +        {"layer2":
          734  +           {"hapax.legomenon":
          735  +              {"forceDisplay":true,
          736  +               "transliterate":true,
          737  +               "add.footnote":true,
          738  +               "summary.report":true},
          739  +            "dis.legomenon":
          740  +              {"forceDisplay":true,
          741  +               "transliterate":false,
          742  +               "add.footnote":false,
          743  +               "summary.report":true},
          744  +            "tris.legomenon":
          745  +              {"forceDisplay":true,
          746  +               "transliterate":false,
          747  +               "add.footnote":false,
          748  +               "summary.report":false}
          749  +           }
          750  +        }
          751  +     }');
          752  +} {}
          753  +do_execsql_test json-12.110 {
          754  +  SELECT json_remove(x, '$.settings.layer2."dis.legomenon".forceDisplay')
          755  +    FROM t12;
          756  +} {{{"settings":{"layer2":{"hapax.legomenon":{"forceDisplay":true,"transliterate":true,"add.footnote":true,"summary.report":true},"dis.legomenon":{"transliterate":false,"add.footnote":false,"summary.report":true},"tris.legomenon":{"forceDisplay":true,"transliterate":false,"add.footnote":false,"summary.report":false}}}}}}
          757  +do_execsql_test json-12.120 {
          758  +  SELECT json_extract(x, '$.settings.layer2."tris.legomenon"."summary.report"')
          759  +    FROM t12;
          760  +} {0}
          761  +
          762  +
          763  +
   724    764   
   725    765   finish_test

Changes to test/minmax2.test.

   379    379   }
   380    380   do_test minmax2-10.12 {
   381    381     execsql {
   382    382       SELECT min(x), max(x) FROM t6;
   383    383     }
   384    384   } {{} {}}
   385    385   
          386  +# 2017-10-26.  Extend the min/max optimization to indexes on expressions
          387  +#
          388  +do_execsql_test minmax2-11.100 {
          389  +  CREATE TABLE t11(a,b,c);
          390  +  INSERT INTO t11(a,b,c) VALUES(1,10,5),(2,8,11),(3,1,4),(4,20,1),(5,16,4);
          391  +  CREATE INDEX t11bc ON t11(b+c);
          392  +  SELECT max(b+c) FROM t11;
          393  +} {21}
          394  +do_execsql_test minmax2-11.110 {
          395  +  SELECT a, max(b+c) FROM t11;
          396  +} {4 21}
          397  +do_test minmax2-11.111 {
          398  +  db eval {SELECT max(b+c) FROM t11}
          399  +  db status step
          400  +} {0}
          401  +do_test minmax2-11.112 {
          402  +  db eval {SELECT max(c+b) FROM t11}
          403  +  db status step
          404  +} {4}
          405  +do_execsql_test minmax2-11.120 {
          406  +  SELECT a, min(b+c) FROM t11;
          407  +} {3 5}
          408  +do_test minmax2-11.121 {
          409  +  db eval {SELECT min(b+c) FROM t11}
          410  +  db status step
          411  +} {0}
          412  +do_test minmax2-11.122 {
          413  +  db eval {SELECT min(c+b) FROM t11}
          414  +  db status step
          415  +} {4}
          416  +do_execsql_test minmax2-11.130 {
          417  +  INSERT INTO t11(a,b,c) VALUES(6,NULL,0),(7,0,NULL);
          418  +  SELECT a, min(b+c) FROM t11;
          419  +} {3 5}
   386    420   
   387    421   finish_test

Added test/wherelfault.test.

            1  +# 2008 October 6
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +# This file implements regression tests for SQLite library.  The
           12  +# focus of this file is testing fault-injection with the 
           13  +# LIMIT ... OFFSET ... clause of UPDATE and DELETE statements.
           14  +#
           15  +
           16  +set testdir [file dirname $argv0]
           17  +source $testdir/tester.tcl
           18  +source $testdir/malloc_common.tcl
           19  +set testprefix wherelfault
           20  +
           21  +ifcapable !update_delete_limit {
           22  +  finish_test
           23  +  return
           24  +}
           25  +
           26  +do_execsql_test 1.0 {
           27  +  CREATE TABLE t1(a, b);
           28  +  INSERT INTO t1 VALUES(1, 'f');
           29  +  INSERT INTO t1 VALUES(2, 'e');
           30  +  INSERT INTO t1 VALUES(3, 'd');
           31  +  INSERT INTO t1 VALUES(4, 'c');
           32  +  INSERT INTO t1 VALUES(5, 'b');
           33  +  INSERT INTO t1 VALUES(6, 'a');
           34  +
           35  +  CREATE VIEW v1 AS SELECT a,b FROM t1;
           36  +  CREATE TABLE log(op, a);
           37  +
           38  +  CREATE TRIGGER v1del INSTEAD OF DELETE ON v1 BEGIN
           39  +    INSERT INTO log VALUES('delete', old.a);
           40  +  END;
           41  +
           42  +  CREATE TRIGGER v1upd INSTEAD OF UPDATE ON v1 BEGIN
           43  +    INSERT INTO log VALUES('update', old.a);
           44  +  END;
           45  +}
           46  +
           47  +faultsim_save_and_close
           48  +do_faultsim_test 1.1 -prep {
           49  +  faultsim_restore_and_reopen
           50  +  db eval {SELECT * FROM sqlite_master}
           51  +} -body {
           52  +  execsql { DELETE FROM v1 ORDER BY a LIMIT 3; }
           53  +} -test {
           54  +  faultsim_test_result {0 {}} 
           55  +}
           56  +
           57  +do_faultsim_test 1.2 -prep {
           58  +  faultsim_restore_and_reopen
           59  +  db eval {SELECT * FROM sqlite_master}
           60  +} -body {
           61  +  execsql { UPDATE v1 SET b = 555 ORDER BY a LIMIT 3 }
           62  +} -test {
           63  +  faultsim_test_result {0 {}} 
           64  +}
           65  +
           66  +#-------------------------------------------------------------------------
           67  +sqlite3 db test.db
           68  +do_execsql_test 2.1.0 {
           69  +  CREATE TABLE t2(a, b, c, PRIMARY KEY(a, b)) WITHOUT ROWID;
           70  +}
           71  +faultsim_save_and_close
           72  +
           73  +do_faultsim_test 2.1 -prep {
           74  +  faultsim_restore_and_reopen
           75  +  db eval {SELECT * FROM sqlite_master}
           76  +} -body {
           77  +  execsql { DELETE FROM t2 WHERE c=? ORDER BY a DESC LIMIT 10 }
           78  +} -test {
           79  +  faultsim_test_result {0 {}} 
           80  +}
           81  +
           82  +finish_test

Changes to test/wherelimit.test.

    34     34       COMMIT;
    35     35     }
    36     36     return {}
    37     37   }
    38     38   
    39     39   ifcapable {update_delete_limit} {
    40     40   
           41  +  execsql { CREATE TABLE t1(x, y) }
           42  +
    41     43     # check syntax error support
    42     44     do_test wherelimit-0.1 {
    43     45       catchsql {DELETE FROM t1 ORDER BY x}
    44     46     } {1 {ORDER BY without LIMIT on DELETE}}
    45     47     do_test wherelimit-0.2 {
    46     48       catchsql {DELETE FROM t1 WHERE x=1 ORDER BY x}
    47     49     } {1 {ORDER BY without LIMIT on DELETE}}
    48     50     do_test wherelimit-0.3 {
    49     51       catchsql {UPDATE t1 SET y=1 WHERE x=1 ORDER BY x}
    50     52     } {1 {ORDER BY without LIMIT on UPDATE}}
           53  +
           54  +  execsql { DROP TABLE t1 }
    51     55   
    52     56     # no AS on table sources
    53     57     do_test wherelimit-0.4 {
    54     58       catchsql {DELETE FROM t1 AS a WHERE x=1}
    55     59     } {1 {near "AS": syntax error}}
    56     60     do_test wherelimit-0.5 {
    57     61       catchsql {UPDATE t1 AS a SET y=1 WHERE x=1}
................................................................................
   274    278       execsql {UPDATE t1 SET y=1 WHERE x=2 ORDER BY x LIMIT 30, 50}
   275    279       execsql {SELECT count(*) FROM t1 WHERE y=1}
   276    280     } {6}
   277    281     do_test wherelimit-3.13 {
   278    282       execsql {UPDATE t1 SET y=1 WHERE x=3 ORDER BY x LIMIT 50 OFFSET 50}
   279    283       execsql {SELECT count(*) FROM t1 WHERE y=1}
   280    284     } {6}
          285  +
          286  +  # Cannot use a LIMIT for UPDATE or DELETE against a WITHOUT ROWID table
          287  +  # or a VIEW.  (We should fix this someday).
          288  +  #
          289  +  db close
          290  +  sqlite3 db :memory:
          291  +  do_execsql_test wherelimit-4.1 {
          292  +    CREATE TABLE t1(a int);
          293  +    INSERT INTO t1 VALUES(1);
          294  +    INSERT INTO t1 VALUES(2);
          295  +    INSERT INTO t1 VALUES(3);
          296  +    CREATE TABLE t2(a int);
          297  +    INSERT INTO t2 SELECT a+100 FROM t1;
          298  +    CREATE VIEW tv(r,a) AS
          299  +       SELECT rowid, a FROM t2 UNION ALL SELECT rowid, a FROM t1;
          300  +    CREATE TRIGGER tv_del INSTEAD OF DELETE ON tv
          301  +    BEGIN
          302  +      DELETE FROM t1 WHERE rowid=old.r;
          303  +      DELETE FROM t2 WHERE rowid=old.r;
          304  +    END;
          305  +  } {}
          306  +  do_catchsql_test wherelimit-4.2 {
          307  +    DELETE FROM tv WHERE 1 LIMIT 2;
          308  +  } {0 {}}
          309  +  do_catchsql_test wherelimit-4.3 {
          310  +    DELETE FROM tv WHERE 1 ORDER BY a LIMIT 2;
          311  +  } {0 {}}
          312  +  do_execsql_test wherelimit-4.10 {
          313  +    CREATE TABLE t3(a,b,c,d TEXT, PRIMARY KEY(a,b)) WITHOUT ROWID;
          314  +    INSERT INTO t3(a,b,c,d) VALUES(1,2,3,4),(5,6,7,8),(9,10,11,12);
          315  +  } {}
          316  +  do_catchsql_test wherelimit-4.11 {
          317  +    DELETE FROM t3 WHERE a=5 LIMIT 2;
          318  +  } {0 {}}
          319  +  do_execsql_test wherelimit-4.12 {
          320  +    SELECT a,b,c,d FROM t3 ORDER BY 1;
          321  +  } {1 2 3 4 9 10 11 12}
   281    322   
   282    323   }
   283    324   
   284    325   finish_test

Added test/wherelimit2.test.

            1  +# 2008 October 6
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +# This file implements regression tests for SQLite library.  The
           12  +# focus of this file is testing the LIMIT ... OFFSET ... clause
           13  +#  of UPDATE and DELETE statements.
           14  +#
           15  +
           16  +set testdir [file dirname $argv0]
           17  +source $testdir/tester.tcl
           18  +set testprefix wherelimit2
           19  +
           20  +ifcapable !update_delete_limit {
           21  +  finish_test
           22  +  return
           23  +}
           24  +
           25  +#-------------------------------------------------------------------------
           26  +# Test with views and INSTEAD OF triggers.
           27  +#
           28  +do_execsql_test 1.0 {
           29  +  CREATE TABLE t1(a, b);
           30  +  INSERT INTO t1 VALUES(1, 'f');
           31  +  INSERT INTO t1 VALUES(2, 'e');
           32  +  INSERT INTO t1 VALUES(3, 'd');
           33  +  INSERT INTO t1 VALUES(4, 'c');
           34  +  INSERT INTO t1 VALUES(5, 'b');
           35  +  INSERT INTO t1 VALUES(6, 'a');
           36  +
           37  +  CREATE VIEW v1 AS SELECT a,b FROM t1;
           38  +  CREATE TABLE log(op, a);
           39  +
           40  +  CREATE TRIGGER v1del INSTEAD OF DELETE ON v1 BEGIN
           41  +    INSERT INTO log VALUES('delete', old.a);
           42  +  END;
           43  +
           44  +  CREATE TRIGGER v1upd INSTEAD OF UPDATE ON v1 BEGIN
           45  +    INSERT INTO log VALUES('update', old.a);
           46  +  END;
           47  +}
           48  +
           49  +do_execsql_test 1.1 {
           50  +  DELETE FROM v1 ORDER BY a LIMIT 3;
           51  +  SELECT * FROM log; DELETE FROM log;
           52  +} {
           53  +  delete 1 delete 2 delete 3
           54  +}
           55  +do_execsql_test 1.2 {
           56  +  DELETE FROM v1 ORDER BY b LIMIT 3;
           57  +  SELECT * FROM log; DELETE FROM log;
           58  +} {
           59  +  delete 6 delete 5 delete 4
           60  +}
           61  +do_execsql_test 1.3 {
           62  +  UPDATE v1 SET b = 555 ORDER BY a LIMIT 3;
           63  +  SELECT * FROM log; DELETE FROM log;
           64  +} {
           65  +  update 1 update 2 update 3
           66  +}
           67  +do_execsql_test 1.4 {
           68  +  UPDATE v1 SET b = 555 ORDER BY b LIMIT 3;
           69  +  SELECT * FROM log; DELETE FROM log;
           70  +} {
           71  +  update 6 update 5 update 4
           72  +}
           73  +
           74  +#-------------------------------------------------------------------------
           75  +# Simple test using WITHOUT ROWID table.
           76  +#
           77  +do_execsql_test 2.1.0 {
           78  +  CREATE TABLE t2(a, b, c, PRIMARY KEY(a, b)) WITHOUT ROWID;
           79  +  INSERT INTO t2 VALUES(1, 1, 'h');
           80  +  INSERT INTO t2 VALUES(1, 2, 'g');
           81  +  INSERT INTO t2 VALUES(2, 1, 'f');
           82  +  INSERT INTO t2 VALUES(2, 2, 'e');
           83  +  INSERT INTO t2 VALUES(3, 1, 'd');
           84  +  INSERT INTO t2 VALUES(3, 2, 'c');
           85  +  INSERT INTO t2 VALUES(4, 1, 'b');
           86  +  INSERT INTO t2 VALUES(4, 2, 'a');
           87  +}
           88  +
           89  +do_execsql_test 2.1.1 {
           90  +  BEGIN;
           91  +    DELETE FROM t2 WHERE b=1 ORDER BY c LIMIT 2;
           92  +    SELECT c FROM t2 ORDER BY 1;
           93  +  ROLLBACK;
           94  +} {a c e f g h}
           95  +
           96  +do_execsql_test 2.1.2 {
           97  +  BEGIN;
           98  +    UPDATE t2 SET c=NULL ORDER BY a, b DESC LIMIT 3 OFFSET 1;
           99  +    SELECT a, b, c FROM t2;
          100  +  ROLLBACK;
          101  +} {
          102  +  1 1 {} 
          103  +  1 2 g 
          104  +  2 1 {} 
          105  +  2 2 {} 
          106  +  3 1 d 
          107  +  3 2 c 
          108  +  4 1 b 
          109  +  4 2 a
          110  +}
          111  +
          112  +do_execsql_test 2.2.0 {
          113  +  DROP TABLE t2;
          114  +  CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c) WITHOUT ROWID;
          115  +  INSERT INTO t2 VALUES(1, 1, 'h');
          116  +  INSERT INTO t2 VALUES(2, 2, 'g');
          117  +  INSERT INTO t2 VALUES(3, 1, 'f');
          118  +  INSERT INTO t2 VALUES(4, 2, 'e');
          119  +  INSERT INTO t2 VALUES(5, 1, 'd');
          120  +  INSERT INTO t2 VALUES(6, 2, 'c');
          121  +  INSERT INTO t2 VALUES(7, 1, 'b');
          122  +  INSERT INTO t2 VALUES(8, 2, 'a');
          123  +}
          124  +
          125  +do_execsql_test 2.2.1 {
          126  +  BEGIN;
          127  +    DELETE FROM t2 WHERE b=1 ORDER BY c LIMIT 2;
          128  +    SELECT c FROM t2 ORDER BY 1;
          129  +  ROLLBACK;
          130  +} {a c e f g h}
          131  +
          132  +do_execsql_test 2.2.2 {
          133  +  BEGIN;
          134  +    UPDATE t2 SET c=NULL ORDER BY a DESC LIMIT 3 OFFSET 1;
          135  +    SELECT a, b, c FROM t2;
          136  +  ROLLBACK;
          137  +} {
          138  +  1 1 h
          139  +  2 2 g 
          140  +  3 1 f
          141  +  4 2 e
          142  +  5 1 {}
          143  +  6 2 {} 
          144  +  7 1 {} 
          145  +  8 2 a
          146  +}
          147  +
          148  +#-------------------------------------------------------------------------
          149  +# Test using a virtual table
          150  +#
          151  +ifcapable fts5 {
          152  +  do_execsql_test 3.0 {
          153  +    CREATE VIRTUAL TABLE ft USING fts5(x);
          154  +    INSERT INTO ft(rowid, x) VALUES(-45,   'a a');
          155  +    INSERT INTO ft(rowid, x) VALUES(12,    'a b');
          156  +    INSERT INTO ft(rowid, x) VALUES(444,   'a c');
          157  +    INSERT INTO ft(rowid, x) VALUES(12300, 'a d');
          158  +    INSERT INTO ft(rowid, x) VALUES(25400, 'a c');
          159  +    INSERT INTO ft(rowid, x) VALUES(25401, 'a b');
          160  +    INSERT INTO ft(rowid, x) VALUES(50000, 'a a');
          161  +  }
          162  +
          163  +  do_execsql_test 3.1.1 {
          164  +    BEGIN;
          165  +      DELETE FROM ft ORDER BY rowid LIMIT 3;
          166  +      SELECT x FROM ft;
          167  +    ROLLBACK;
          168  +  } {{a d} {a c} {a b} {a a}}
          169  +
          170  +  do_execsql_test 3.1.2 {
          171  +    BEGIN;
          172  +      DELETE FROM ft WHERE ft MATCH 'a' ORDER BY rowid LIMIT 3;
          173  +      SELECT x FROM ft;
          174  +    ROLLBACK;
          175  +  } {{a d} {a c} {a b} {a a}}
          176  +  
          177  +  do_execsql_test 3.1.3 {
          178  +    BEGIN;
          179  +      DELETE FROM ft WHERE ft MATCH 'b' ORDER BY rowid ASC LIMIT 1 OFFSET 1;
          180  +      SELECT rowid FROM ft;
          181  +    ROLLBACK;
          182  +  } {-45 12 444 12300 25400 50000}
          183  +
          184  +  do_execsql_test 3.2.1 {
          185  +    BEGIN;
          186  +      UPDATE ft SET x='hello' ORDER BY rowid LIMIT 2 OFFSET 2;
          187  +      SELECT x FROM ft;
          188  +    ROLLBACK;
          189  +  } {{a a} {a b} hello hello {a c} {a b} {a a}}
          190  +
          191  +  do_execsql_test 3.2.2 {
          192  +    BEGIN;
          193  +      UPDATE ft SET x='hello' WHERE ft MATCH 'a' 
          194  +          ORDER BY rowid DESC LIMIT 2 OFFSET 2;
          195  +      SELECT x FROM ft;
          196  +    ROLLBACK;
          197  +  } {{a a} {a b} {a c} hello hello {a b} {a a}}
          198  +} ;# fts5
          199  +
          200  +#-------------------------------------------------------------------------
          201  +# Test using INDEXED BY clauses.
          202  +#
          203  +do_execsql_test 4.0 {
          204  +  CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c, d);
          205  +  CREATE INDEX x1bc ON x1(b, c);
          206  +  INSERT INTO x1 VALUES(1,1,1,1);
          207  +  INSERT INTO x1 VALUES(2,1,2,2);
          208  +  INSERT INTO x1 VALUES(3,2,1,3);
          209  +  INSERT INTO x1 VALUES(4,2,2,3);
          210  +  INSERT INTO x1 VALUES(5,3,1,2);
          211  +  INSERT INTO x1 VALUES(6,3,2,1);
          212  +}
          213  +
          214  +do_execsql_test 4.1 {
          215  +  BEGIN;
          216  +    DELETE FROM x1 ORDER BY a LIMIT 2;
          217  +    SELECT a FROM x1;
          218  +  ROLLBACK;
          219  +} {3 4 5 6}
          220  +
          221  +do_catchsql_test 4.2 {
          222  +  DELETE FROM x1 INDEXED BY x1bc WHERE d=3 LIMIT 1;
          223  +} {1 {no query solution}}
          224  +
          225  +do_execsql_test 4.3 {
          226  +  DELETE FROM x1 INDEXED BY x1bc WHERE b=3 LIMIT 1;
          227  +  SELECT a FROM x1;
          228  +} {1 2 3 4 6}
          229  +
          230  +do_catchsql_test 4.4 {
          231  +  UPDATE x1 INDEXED BY x1bc SET d=5 WHERE d=3 LIMIT 1;
          232  +} {1 {no query solution}}
          233  +
          234  +do_execsql_test 4.5 {
          235  +  UPDATE x1 INDEXED BY x1bc SET d=5 WHERE b=2 LIMIT 1;
          236  +  SELECT a, d FROM x1;
          237  +} {1 1 2 2 3 5 4 3 6 1}
          238  +
          239  +#-------------------------------------------------------------------------
          240  +# Test using object names that require quoting.
          241  +#
          242  +do_execsql_test 5.0 {
          243  +  CREATE TABLE "x y"("a b" PRIMARY KEY, "c d") WITHOUT ROWID;
          244  +  CREATE INDEX xycd ON "x y"("c d");
          245  +
          246  +  INSERT INTO "x y" VALUES('a', 'a');
          247  +  INSERT INTO "x y" VALUES('b', 'b');
          248  +  INSERT INTO "x y" VALUES('c', 'c');
          249  +  INSERT INTO "x y" VALUES('d', 'd');
          250  +  INSERT INTO "x y" VALUES('e', 'a');
          251  +  INSERT INTO "x y" VALUES('f', 'b');
          252  +  INSERT INTO "x y" VALUES('g', 'c');
          253  +  INSERT INTO "x y" VALUES('h', 'd');
          254  +}
          255  +
          256  +do_execsql_test 5.1 {
          257  +  BEGIN;
          258  +    DELETE FROM "x y" WHERE "c d"!='e' ORDER BY "c d" LIMIT 2 OFFSET 2;
          259  +    SELECT * FROM "x y" ORDER BY 1;
          260  +  ROLLBACK;
          261  +} {
          262  +  a a c c d d e a g c h d
          263  +}
          264  +
          265  +do_execsql_test 5.2 {
          266  +  BEGIN;
          267  +    UPDATE "x y" SET "c d"='e' WHERE "c d"!='e' ORDER BY "c d" LIMIT 2 OFFSET 2;
          268  +    SELECT * FROM "x y" ORDER BY 1;
          269  +  ROLLBACK;
          270  +} {
          271  +  a a b e c c d d e a f e g c h d
          272  +}
          273  +
          274  +proc log {args} { lappend ::log {*}$args }
          275  +db func log log
          276  +do_execsql_test 5.3 {
          277  +  CREATE VIEW "v w" AS SELECT * FROM "x y";
          278  +  CREATE TRIGGER tr1 INSTEAD OF DELETE ON "v w" BEGIN
          279  +    SELECT log(old."a b", old."c d");
          280  +  END;
          281  +  CREATE TRIGGER tr2 INSTEAD OF UPDATE ON "v w" BEGIN
          282  +    SELECT log(new."a b", new."c d");
          283  +  END;
          284  +}
          285  +
          286  +do_test 5.4 {
          287  +  set ::log {}
          288  +  execsql { DELETE FROM "v w" ORDER BY "a b" LIMIT 3 }
          289  +  set ::log
          290  +} {a a b b c c}
          291  +
          292  +do_test 5.5 {
          293  +  set ::log {}
          294  +  execsql { UPDATE "v w" SET "a b" = "a b" || 'x' ORDER BY "a b" LIMIT 5; }
          295  +  set ::log
          296  +} {ax a bx b cx c dx d ex a}
          297  +
          298  +
          299  +finish_test
          300  +

Changes to test/with1.test.

   999    999     WITH
  1000   1000       x1(a) AS (values(100))
  1001   1001     INSERT INTO t1(x)
  1002   1002       SELECT * FROM (WITH x2(y) AS (SELECT * FROM x1) SELECT y+a FROM x1, x2);
  1003   1003     SELECT * FROM t1;
  1004   1004   } {0 0 0 {SCAN SUBQUERY 1} 0 1 1 {SCAN SUBQUERY 1}}
  1005   1005   
  1006         -
         1006  +# 2017-10-28.
         1007  +# See check-in https://sqlite.org/src/info/0926df095faf72c2
         1008  +# Tried to optimize co-routine processing by changing a Copy opcode
         1009  +# into SCopy.  But OSSFuzz found two (similar) cases where that optimization
         1010  +# does not work.
         1011  +#
         1012  +do_execsql_test 20.1 {
         1013  +  WITH c(i)AS(VALUES(9)UNION SELECT~i FROM c)SELECT max(5)>i fROM c;
         1014  +} {0}
         1015  +do_execsql_test 20.2 {
         1016  +  WITH c(i)AS(VALUES(5)UNIoN SELECT 0)SELECT min(1)-i fROM c;
         1017  +} {1}
  1007   1018   
  1008   1019   finish_test

Changes to tool/mkmsvcmin.tcl.

    50     50   #
    51     51   # NOTE: This block is used to replace the section marked <<block1>> in
    52     52   #       the Makefile, if it exists.
    53     53   #
    54     54   set blocks(1) [string trimleft [string map [list \\\\ \\] {
    55     55   _HASHCHAR=^#
    56     56   !IF ![echo !IFNDEF VERSION > rcver.vc] && \\
    57         -    ![for /F "delims=" %V in ('type "$(SQLITE3H)" ^| find "$(_HASHCHAR)define SQLITE_VERSION "') do (echo VERSION = ^^%V >> rcver.vc)] && \\
           57  +    ![for /F "delims=" %V in ('type "$(SQLITE3H)" ^| "%SystemRoot%\System32\find.exe" "$(_HASHCHAR)define SQLITE_VERSION "') do (echo VERSION = ^^%V >> rcver.vc)] && \\
    58     58       ![echo !ENDIF >> rcver.vc]
    59     59   !INCLUDE rcver.vc
    60     60   !ENDIF
    61     61   
    62     62   RESOURCE_VERSION = $(VERSION:^#=)
    63     63   RESOURCE_VERSION = $(RESOURCE_VERSION:define=)
    64     64   RESOURCE_VERSION = $(RESOURCE_VERSION:SQLITE_VERSION=)

Added tool/showshm.c.

            1  +/*
            2  +** A utility for printing content from the wal-index or "shm" file.
            3  +*/
            4  +#include <stdio.h>
            5  +#include <ctype.h>
            6  +#include <sys/types.h>
            7  +#include <sys/stat.h>
            8  +#include <fcntl.h>
            9  +#include <assert.h>
           10  +
           11  +#define ISDIGIT(X)  isdigit((unsigned char)(X))
           12  +#define ISPRINT(X)  isprint((unsigned char)(X))
           13  +
           14  +#if !defined(_MSC_VER)
           15  +#include <unistd.h>
           16  +#include <sys/types.h>
           17  +#else
           18  +#include <io.h>
           19  +#endif
           20  +
           21  +#include <stdlib.h>
           22  +#include <string.h>
           23  +
           24  +static int fd = -1;             /* The open SHM file */
           25  +
           26  +/* Report an out-of-memory error and die.
           27  +*/
           28  +static void out_of_memory(void){
           29  +  fprintf(stderr,"Out of memory...\n");
           30  +  exit(1);
           31  +}
           32  +
           33  +/*
           34  +** Read content from the file.
           35  +**
           36  +** Space to hold the content is obtained from malloc() and needs to be
           37  +** freed by the caller.
           38  +*/
           39  +static unsigned char *getContent(int ofst, int nByte){
           40  +  unsigned char *aData;
           41  +  aData = malloc(nByte);
           42  +  if( aData==0 ) out_of_memory();
           43  +  lseek(fd, ofst, SEEK_SET);
           44  +  read(fd, aData, nByte);
           45  +  return aData;
           46  +}
           47  +
           48  +/*
           49  +** Flags values
           50  +*/
           51  +#define FG_HEX     1    /* Show as hex */
           52  +#define FG_NBO     2    /* Native byte order */
           53  +#define FG_PGSZ    4    /* Show as page-size */
           54  +
           55  +/* Print a line of decode output showing a 4-byte integer.
           56  +*/
           57  +static void print_decode_line(
           58  +  unsigned char *aData,      /* Content being decoded */
           59  +  int ofst, int nByte,       /* Start and size of decode */
           60  +  unsigned flg,              /* Display flags */
           61  +  const char *zMsg           /* Message to append */
           62  +){
           63  +  int i, j;
           64  +  int val = aData[ofst];
           65  +  char zBuf[100];
           66  +  sprintf(zBuf, " %03x: %02x", ofst, aData[ofst]);
           67  +  i = (int)strlen(zBuf);
           68  +  for(j=1; j<4; j++){
           69  +    if( j>=nByte ){
           70  +      sprintf(&zBuf[i], "   ");
           71  +    }else{
           72  +      sprintf(&zBuf[i], " %02x", aData[ofst+j]);
           73  +      val = val*256 + aData[ofst+j];
           74  +    }
           75  +    i += (int)strlen(&zBuf[i]);
           76  +  }
           77  +  if( nByte==8 ){
           78  +    for(j=4; j<8; j++){
           79  +      sprintf(&zBuf[i], " %02x", aData[ofst+j]);
           80  +      i += (int)strlen(&zBuf[i]);
           81  +    }
           82  +  }
           83  +  if( flg & FG_NBO ){
           84  +    assert( nByte==4 );
           85  +    memcpy(&val, aData+ofst, 4);
           86  +  }
           87  +  sprintf(&zBuf[i], "            ");
           88  +  i += 12;
           89  +  if( flg & FG_PGSZ ){
           90  +    unsigned short sz;
           91  +    memcpy(&sz, aData+ofst, 2);
           92  +    sprintf(&zBuf[i], "   %9d", sz==1 ? 65536 : sz);
           93  +  }else if( flg & FG_HEX ){
           94  +    sprintf(&zBuf[i], "  0x%08x", val);
           95  +  }else if( nByte<8 ){
           96  +    sprintf(&zBuf[i], "   %9d", val);
           97  +  }
           98  +  printf("%s  %s\n", zBuf, zMsg);
           99  +}
          100  +
          101  +/*
          102  +** Print an instance of the WalIndexHdr object.  ix is either 0 or 1
          103  +** to select which header to print.
          104  +*/
          105  +static void print_index_hdr(unsigned char *aData, int ix){
          106  +  int i;
          107  +  assert( ix==0 || ix==1 );
          108  +  i = ix ? 48 : 0;
          109  +  print_decode_line(aData, 0+i, 4, FG_NBO,  "Wal-index version");
          110  +  print_decode_line(aData, 4+i, 4, 0,       "unused padding");
          111  +  print_decode_line(aData, 8+i, 4, FG_NBO,  "transaction counter");
          112  +  print_decode_line(aData,12+i, 1, 0,       "1 when initialized");
          113  +  print_decode_line(aData,13+i, 1, 0,       "true if WAL cksums are bigendian");
          114  +  print_decode_line(aData,14+i, 2, FG_PGSZ, "database page size");
          115  +  print_decode_line(aData,16+i, 4, FG_NBO,  "mxFrame");
          116  +  print_decode_line(aData,20+i, 4, FG_NBO,  "Size of database in pages");
          117  +  print_decode_line(aData,24+i, 8, 0, "Cksum of last frame in -wal");
          118  +  print_decode_line(aData,32+i, 8, 0,  "Salt values from the -wal");
          119  +  print_decode_line(aData,40+i, 8, 0,  "Cksum over all prior fields");
          120  +}
          121  +
          122  +/*
          123  +** Print the WalCkptInfo object
          124  +*/
          125  +static void print_ckpt_info(unsigned char *aData){
          126  +  const int i = 96;
          127  +  int j;
          128  +  print_decode_line(aData, 0+i, 4, FG_NBO,  "nBackfill");
          129  +  for(j=0; j<5; j++){
          130  +    char zLabel[100];
          131  +    sprintf(zLabel, "aReadMark[%d]", j);
          132  +    print_decode_line(aData, 4*j+4+i, 4, FG_NBO, zLabel);
          133  +  }
          134  +  print_decode_line(aData,24+i, 8, 0,       "aLock");
          135  +  print_decode_line(aData,32+i, 4, FG_NBO,  "nBackfillAttempted");
          136  +  print_decode_line(aData,36+i, 4, FG_NBO,  "notUsed0");
          137  +}
          138  +
          139  +
          140  +int main(int argc, char **argv){
          141  +  unsigned char *aData;
          142  +  if( argc<2 ){
          143  +    fprintf(stderr,"Usage: %s FILENAME\n", argv[0]);
          144  +    exit(1);
          145  +  }
          146  +  fd = open(argv[1], O_RDONLY);
          147  +  if( fd<0 ){
          148  +    fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]);
          149  +    exit(1);
          150  +  }
          151  +  aData = getContent(0, 136);
          152  +  print_index_hdr(aData, 0);
          153  +  print_index_hdr(aData, 1);
          154  +  print_ckpt_info(aData);
          155  +  free(aData);
          156  +  close(fd);
          157  +  return 0;
          158  +}

Changes to tool/spaceanal.tcl.

     1         -# Run this TCL script using "testfixture" in order get a report that shows
     2         -# how much disk space is used by a particular data to actually store data
            1  +# Run this TCL script using an SQLite-enabled TCL interpreter to get a report
            2  +# on how much disk space is used by a particular data to actually store data
     3      3   # versus how much space is unused.
            4  +#
            5  +# The dbstat virtual table is required.
     4      6   #
     5      7   
     6      8   if {[catch {
     7      9   
     8     10   # Argument $tname is the name of a table within the database opened by
     9     11   # database handle [db]. Return true if it is a WITHOUT ROWID table, or
    10     12   # false otherwise.
................................................................................
   142    144     puts stderr "error trying to open $file_to_analyze: $msg"
   143    145     exit 1
   144    146   }
   145    147   if {$flags(-debug)} {
   146    148     proc dbtrace {txt} {puts $txt; flush stdout;}
   147    149     db trace ::dbtrace
   148    150   }
          151  +
          152  +# Make sure all required compile-time options are available
          153  +#
          154  +if {![db exists {SELECT 1 FROM pragma_compile_options
          155  +                WHERE compile_options='ENABLE_DBSTAT_VTAB'}]} {
          156  +  puts "The SQLite database engine linked with this application\
          157  +        lacks required capabilities. Recompile using the\
          158  +        -DSQLITE_ENABLE_DBSTAT_VTAB compile-time option to fix\
          159  +        this problem."
          160  +  exit 1
          161  +}
   149    162   
   150    163   db eval {SELECT count(*) FROM sqlite_master}
   151    164   set pageSize [expr {wide([db one {PRAGMA page_size}])}]
   152    165   
   153    166   if {$flags(-pageinfo)} {
   154    167     db eval {CREATE VIRTUAL TABLE temp.stat USING dbstat}
   155    168     db eval {SELECT name, path, pageno FROM temp.stat ORDER BY pageno} {

Changes to tool/sqlite3_analyzer.c.in.

    10     10   #define SQLITE_OMIT_DECLTYPE 1
    11     11   #define SQLITE_OMIT_DEPRECATED 1
    12     12   #define SQLITE_OMIT_PROGRESS_CALLBACK 1
    13     13   #define SQLITE_OMIT_SHARED_CACHE 1
    14     14   #define SQLITE_DEFAULT_MEMSTATUS 0
    15     15   #define SQLITE_MAX_EXPR_DEPTH 0
    16     16   #define SQLITE_OMIT_LOAD_EXTENSION 1
           17  +#ifndef USE_EXTERNAL_SQLITE
    17     18   INCLUDE sqlite3.c
           19  +#endif
    18     20   INCLUDE $ROOT/src/tclsqlite.c
    19     21   
    20     22   const char *sqlite3_analyzer_init_proc(Tcl_Interp *interp){
    21     23     (void)interp;
    22     24     return
    23     25   BEGIN_STRING
    24     26   INCLUDE $ROOT/tool/spaceanal.tcl
    25     27   END_STRING
    26     28   ;
    27     29   }