/ Check-in [1ccae39b]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Merge all changes through the first 3.9.0 beta from trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | apple-osx
Files: files | file ages | folders
SHA1: 1ccae39b8a7094c2cee2f3fea57c847d0063fa81
User & Date: drh 2015-10-09 17:28:56
Context
2015-10-13
17:49
Merge 3.9.0 prerelease changes into the apple-osx branch. check-in: 1900ce01 user: drh tags: apple-osx
2015-10-09
17:28
Merge all changes through the first 3.9.0 beta from trunk. check-in: 1ccae39b user: drh tags: apple-osx
14:37
Add --enable-fts5 and --enable-json1 options to the amalgamation autoconf package. check-in: 8a4e1988 user: dan tags: trunk
2015-09-24
14:43
Merge recent trunk enhancements into the apple-osx branch. check-in: 4dd06d8b user: drh tags: apple-osx
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Makefile.in.

    61     61   
    62     62   # Should the database engine be compiled threadsafe
    63     63   #
    64     64   #TCC += -DSQLITE_THREADSAFE=@SQLITE_THREADSAFE@
    65     65   
    66     66   # Any target libraries which libsqlite must be linked against
    67     67   # 
    68         -TLIBS = @LIBS@
           68  +TLIBS = @LIBS@ $(LIBS)
    69     69   
    70     70   # Flags controlling use of the in memory btree implementation
    71     71   #
    72     72   # SQLITE_TEMP_STORE is 0 to force temporary tables to be in a file, 1 to
    73     73   # default to file, 2 to default to memory, and 3 to force temporary
    74     74   # tables to always be in memory.
    75     75   #
................................................................................
   171    171            expr.lo fault.lo fkey.lo \
   172    172            fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
   173    173            fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
   174    174            fts3_tokenize_vtab.lo \
   175    175            fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \
   176    176   	 fts5.lo \
   177    177            func.lo global.lo hash.lo \
   178         -         icu.lo insert.lo journal.lo legacy.lo loadext.lo \
          178  +         icu.lo insert.lo journal.lo json1.lo legacy.lo loadext.lo \
   179    179            main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
   180    180            memjournal.lo \
   181    181            mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
   182    182            notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
   183    183            pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
   184    184            random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \
   185    185            table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
................................................................................
   268    268     $(TOP)/src/status.c \
   269    269     $(TOP)/src/shell.c \
   270    270     $(TOP)/src/sqlite.h.in \
   271    271     $(TOP)/src/sqlite3ext.h \
   272    272     $(TOP)/src/sqliteInt.h \
   273    273     $(TOP)/src/sqliteLimit.h \
   274    274     $(TOP)/src/table.c \
   275         -  $(TOP)/src/threads.c \
   276    275     $(TOP)/src/tclsqlite.c \
          276  +  $(TOP)/src/threads.c \
   277    277     $(TOP)/src/tokenize.c \
   278    278     $(TOP)/src/treeview.c \
   279    279     $(TOP)/src/trigger.c \
   280    280     $(TOP)/src/utf.c \
   281    281     $(TOP)/src/update.c \
   282    282     $(TOP)/src/util.c \
   283    283     $(TOP)/src/vacuum.c \
................................................................................
   345    345     $(TOP)/ext/rtree/rtree.h \
   346    346     $(TOP)/ext/rtree/rtree.c
   347    347   SRC += \
   348    348     $(TOP)/ext/sqlrr/sqlrr.h \
   349    349     $(TOP)/ext/sqlrr/sqlrr.c \
   350    350     $(TOP)/ext/rbu/sqlite3rbu.h \
   351    351     $(TOP)/ext/rbu/sqlite3rbu.c
          352  +SRC += \
          353  +  $(TOP)/ext/misc/json1.c
          354  +
   352    355   
   353    356   
   354    357   # Generated source code files
   355    358   #
   356    359   SRC += \
   357    360     keywordhash.h \
   358    361     opcodes.c \
................................................................................
   415    418     $(TOP)/ext/misc/closure.c \
   416    419     $(TOP)/ext/misc/eval.c \
   417    420     $(TOP)/ext/misc/fileio.c \
   418    421     $(TOP)/ext/misc/fuzzer.c \
   419    422     $(TOP)/ext/fts5/fts5_tcl.c \
   420    423     $(TOP)/ext/fts5/fts5_test_mi.c \
   421    424     $(TOP)/ext/misc/ieee754.c \
   422         -  $(TOP)/ext/misc/json1.c \
   423    425     $(TOP)/ext/misc/nextchar.c \
   424    426     $(TOP)/ext/misc/percentile.c \
   425    427     $(TOP)/ext/misc/regexp.c \
   426    428     $(TOP)/ext/misc/series.c \
   427    429     $(TOP)/ext/misc/spellfix.c \
   428    430     $(TOP)/ext/misc/totype.c \
   429    431     $(TOP)/ext/misc/wholenumber.c
................................................................................
   550    552   #
   551    553   FUZZDATA = \
   552    554     $(TOP)/test/fuzzdata1.db \
   553    555     $(TOP)/test/fuzzdata2.db \
   554    556     $(TOP)/test/fuzzdata3.db \
   555    557     $(TOP)/test/fuzzdata4.db
   556    558   
   557         -# Extra arguments for including json1 in the build of tools
   558         -#
   559         -JSON1_DEP = $(TOP)/ext/misc/json1.c sqlite3ext.h
   560         -JSON1_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_CORE
   561         -JSON1_SRC = $(TOP)/ext/misc/json1.c
   562         -
   563    559   # Standard options to testfixture
   564    560   #
   565    561   TESTOPTS = --verbose=file --output=test-out.txt
          562  +
          563  +# Extra compiler options for various shell tools
          564  +#
          565  +SHELL_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
          566  +FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
          567  +FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1
   566    568   
   567    569   # This is the default Makefile target.  The objects listed here
   568    570   # are what get build when you type just "make" with no arguments.
   569    571   #
   570    572   all:	sqlite3.h libsqlite3.la sqlite3$(TEXE) $(HAVE_TCL:1=libtclsqlite3.la)
   571    573   
   572    574   Makefile: $(TOP)/Makefile.in
................................................................................
   581    583   
   582    584   libtclsqlite3.la:	tclsqlite.lo libsqlite3.la
   583    585   	$(LTLINK) -no-undefined -o $@ tclsqlite.lo \
   584    586   		libsqlite3.la @TCL_STUB_LIB_SPEC@ $(TLIBS) \
   585    587                   -rpath "$(TCLLIBDIR)/sqlite3" \
   586    588   		-version-info "8:6:8"
   587    589   
   588         -sqlite3$(TEXE):	$(TOP)/src/shell.c libsqlite3.la sqlite3.h $(JSON1_DEP)
   589         -	$(LTLINK) $(READLINE_FLAGS) $(JSON1_OPT) -o $@ \
   590         -		$(TOP)/src/shell.c $(JSON1_SRC) libsqlite3.la \
          590  +sqlite3$(TEXE):	$(TOP)/src/shell.c libsqlite3.la sqlite3.h
          591  +	$(LTLINK) $(READLINE_FLAGS) $(SHELL_OPT) -o $@ \
          592  +		$(TOP)/src/shell.c libsqlite3.la \
   591    593   		$(LIBREADLINE) $(TLIBS) -rpath "$(libdir)"
   592    594   
   593    595   sqldiff$(TEXE):	$(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
   594    596   	$(LTLINK) -o $@ $(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS)
   595    597   
   596         -fuzzershell$(TEXE):	$(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h $(JSON1_DEP)
   597         -	$(LTLINK) -o $@ $(JSON1_OPT) \
   598         -	  $(TOP)/tool/fuzzershell.c $(JSON1_SRC) sqlite3.c $(TLIBS)
          598  +fuzzershell$(TEXE):	$(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
          599  +	$(LTLINK) -o $@ $(FUZZERSHELL_OPT) \
          600  +	  $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS)
   599    601   
   600         -fuzzcheck$(TEXE):	$(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h $(JSON1_DEP)
   601         -	$(LTLINK) -o $@ $(JSON1_OPT) $(TOP)/test/fuzzcheck.c $(JSON1_SRC) sqlite3.c $(TLIBS)
          602  +fuzzcheck$(TEXE):	$(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h
          603  +	$(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/fuzzcheck.c sqlite3.c $(TLIBS)
   602    604   
   603    605   mptester$(TEXE):	sqlite3.c $(TOP)/mptest/mptest.c
   604    606   	$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
   605    607   		$(TLIBS) -rpath "$(libdir)"
   606    608   
   607    609   MPTEST1=./mptester$(TEXE) mptest.db $(TOP)/mptest/crash01.test --repeat 20
   608    610   MPTEST2=./mptester$(TEXE) mptest.db $(TOP)/mptest/multiwrite01.test --repeat 20
................................................................................
   620    622   
   621    623   # This target creates a directory named "tsrc" and fills it with
   622    624   # copies of all of the C source code and header files needed to
   623    625   # build on the target system.  Some of the C source code and header
   624    626   # files are automatically generated.  This target takes care of
   625    627   # all that automatic generation.
   626    628   #
   627         -.target_source:	$(SRC) $(TOP)/tool/vdbe-compress.tcl
          629  +.target_source:	$(SRC) $(TOP)/tool/vdbe-compress.tcl fts5.c
   628    630   	rm -rf tsrc
   629    631   	mkdir tsrc
   630    632   	cp -f $(SRC) tsrc
   631    633   	rm tsrc/sqlite.h.in tsrc/parse.y
   632    634   	$(TCLSH_CMD) $(TOP)/tool/vdbe-compress.tcl $(OPTS) <tsrc/vdbe.c >vdbe.new
   633    635   	mv vdbe.new tsrc/vdbe.c
          636  +	cp fts5.c fts5.h tsrc
   634    637   	touch .target_source
   635    638   
   636    639   sqlite3.c:	.target_source $(TOP)/tool/mksqlite3c.tcl
   637    640   	$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl
   638    641   	cp tsrc/shell.c tsrc/sqlite3ext.h .
          642  +
          643  +sqlite3ext.h:	.target_source
          644  +	cp tsrc/sqlite3ext.h .
   639    645   
   640    646   tclsqlite3.c:	sqlite3.c
   641    647   	echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c
   642    648   	cat sqlite3.c >>tclsqlite3.c
   643    649   	echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c
   644    650   	cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c
   645    651   
................................................................................
   995   1001   
   996   1002   fts3_write.lo:	$(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
   997   1003   	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_write.c
   998   1004   
   999   1005   rtree.lo:	$(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
  1000   1006   	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c
  1001   1007   
         1008  +json1.lo:	$(TOP)/ext/misc/json1.c
         1009  +	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c
         1010  +
  1002   1011   # FTS5 things
  1003   1012   #
  1004   1013   FTS5_SRC = \
  1005   1014      $(TOP)/ext/fts5/fts5.h \
  1006   1015      $(TOP)/ext/fts5/fts5Int.h \
  1007   1016      $(TOP)/ext/fts5/fts5_aux.c \
  1008   1017      $(TOP)/ext/fts5/fts5_buffer.c \

Changes to Makefile.msc.

   386    386   !ENDIF
   387    387   !ENDIF
   388    388   
   389    389   # These are additional compiler options used for the shell executable.
   390    390   #
   391    391   !IFNDEF SHELL_COMPILE_OPTS
   392    392   !IF $(DYNAMIC_SHELL)!=0
   393         -SHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 $(SHELL_CCONV_OPTS) -DSQLITE_API=__declspec(dllimport)
          393  +SHELL_COMPILE_OPTS = -DSQLITE_SHELL_JSON1 $(SHELL_CCONV_OPTS) -DSQLITE_API=__declspec(dllimport)
   394    394   !ELSE
   395         -SHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 $(SHELL_CCONV_OPTS)
          395  +SHELL_COMPILE_OPTS = -DSQLITE_SHELL_JSON1 $(SHELL_CCONV_OPTS)
   396    396   !ENDIF
   397    397   !ENDIF
   398    398   
   399    399   # This is the core library that the shell executable should depend on.
   400    400   #
   401    401   !IFNDEF SHELL_CORE_DEP
   402    402   !IF $(DYNAMIC_SHELL)!=0
................................................................................
  1004   1004     $(TOP)\ext\fts3\fts3_unicode2.c \
  1005   1005     $(TOP)\ext\fts3\fts3_write.c \
  1006   1006     $(TOP)\ext\icu\sqliteicu.h \
  1007   1007     $(TOP)\ext\icu\icu.c \
  1008   1008     $(TOP)\ext\rtree\rtree.h \
  1009   1009     $(TOP)\ext\rtree\rtree.c \
  1010   1010     $(TOP)\ext\rbu\sqlite3rbu.h \
  1011         -  $(TOP)\ext\rbu\sqlite3rbu.c
         1011  +  $(TOP)\ext\rbu\sqlite3rbu.c \
         1012  +  $(TOP)\ext\misc\json1.c
  1012   1013   
  1013   1014   
  1014   1015   # Generated source code files
  1015   1016   #
  1016   1017   SRC5 = \
  1017   1018     keywordhash.h \
  1018   1019     opcodes.c \
................................................................................
  1206   1207   #
  1207   1208   FUZZDATA = \
  1208   1209     $(TOP)\test\fuzzdata1.db \
  1209   1210     $(TOP)\test\fuzzdata2.db \
  1210   1211     $(TOP)\test\fuzzdata3.db \
  1211   1212     $(TOP)\test\fuzzdata4.db
  1212   1213   
  1213         -# Extra arguments for including json1 in the build of tools
         1214  +# Extra compiler options for various shell tools
  1214   1215   #
  1215         -JSON1_DEP = sqlite3ext.h $(TOP)\ext\misc\json1.c
  1216         -JSON1_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_CORE
  1217         -JSON1_SRC = $(TOP)\ext\misc\json1.c
         1216  +SHELL_COMPILE_OPTS = -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
         1217  +FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
         1218  +FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
  1218   1219   
  1219   1220   # Standard options to testfixture
  1220   1221   #
  1221   1222   TESTOPTS = --verbose=file --output=test-out.txt
  1222   1223   
  1223   1224   # This is the default Makefile target.  The objects listed here
  1224   1225   # are what get build when you type just "make" with no arguments.
................................................................................
  1227   1228   
  1228   1229   libsqlite3.lib:	$(LIBOBJ)
  1229   1230   	$(LTLIB) $(LTLIBOPTS) /OUT:$@ $(LIBOBJ) $(TLIBS)
  1230   1231   
  1231   1232   libtclsqlite3.lib:	tclsqlite.lo libsqlite3.lib
  1232   1233   	$(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCL:tcl=tclstub) $(TLIBS)
  1233   1234   
  1234         -sqlite3.exe:	$(TOP)\src\shell.c $(JSON1_DEP) $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h
  1235         -	$(LTLINK) $(SHELL_COMPILE_OPTS) $(JSON1_OPT) $(READLINE_FLAGS) $(TOP)\src\shell.c $(JSON1_SRC) \
         1235  +sqlite3.exe:	$(TOP)\src\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h
         1236  +	$(LTLINK) $(SHELL_COMPILE_OPTS) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\src\shell.c \
  1236   1237   		/link /pdb:sqlite3sh.pdb $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
  1237   1238   
  1238   1239   sqldiff.exe:	$(TOP)\tool\sqldiff.c sqlite3.c sqlite3.h
  1239   1240   	$(LTLINK) $(NO_WARN) $(TOP)\tool\sqldiff.c sqlite3.c
  1240   1241   
  1241         -fuzzershell.exe:	$(TOP)\tool\fuzzershell.c sqlite3.c sqlite3.h $(JSON1_DEP)
  1242         -	$(LTLINK) $(NO_WARN) $(JSON1_OPT) \
  1243         -	  $(TOP)\tool\fuzzershell.c $(JSON1_SRC) sqlite3.c
         1242  +fuzzershell.exe:	$(TOP)\tool\fuzzershell.c sqlite3.c sqlite3.h
         1243  +	$(LTLINK) $(NO_WARN) $(FUZZERSHELL_COMPILE_OPTS) \
         1244  +	  $(TOP)\tool\fuzzershell.c sqlite3.c
  1244   1245   
  1245         -fuzzcheck.exe:	$(TOP)\test\fuzzcheck.c sqlite3.c sqlite3.h $(JSON1_DEP)
  1246         -	$(LTLINK) $(NO_WARN) $(JSON1_OPT) $(TOP)\test\fuzzcheck.c $(JSON1_SRC) sqlite3.c
         1246  +fuzzcheck.exe:	$(TOP)\test\fuzzcheck.c sqlite3.c sqlite3.h
         1247  +	$(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(TOP)\test\fuzzcheck.c sqlite3.c
  1247   1248   
  1248   1249   mptester.exe:	$(TOP)\mptest\mptest.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h
  1249   1250   	$(LTLINK) $(NO_WARN) $(SHELL_COMPILE_OPTS) $(TOP)\mptest\mptest.c \
  1250   1251   		/link $(LTLINKOPTS) $(LTLIBPATHS) $(SHELL_LINK_OPTS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
  1251   1252   
  1252   1253   MPTEST1 = mptester mptest.db $(TOP)\mptest\crash01.test --repeat 20
  1253   1254   MPTEST2 = mptester mptest.db $(TOP)\mptest\multiwrite01.test --repeat 20
................................................................................
  1265   1266   
  1266   1267   # This target creates a directory named "tsrc" and fills it with
  1267   1268   # copies of all of the C source code and header files needed to
  1268   1269   # build on the target system.  Some of the C source code and header
  1269   1270   # files are automatically generated.  This target takes care of
  1270   1271   # all that automatic generation.
  1271   1272   #
  1272         -.target_source:	$(SRC) $(TOP)\tool\vdbe-compress.tcl
         1273  +.target_source:	$(SRC) $(TOP)\tool\vdbe-compress.tcl fts5.c
  1273   1274   	-rmdir /Q/S tsrc 2>NUL
  1274   1275   	-mkdir tsrc
  1275   1276   	for %i in ($(SRC1)) do copy /Y %i tsrc
  1276   1277   	for %i in ($(SRC2)) do copy /Y %i tsrc
  1277   1278   	for %i in ($(SRC3)) do copy /Y %i tsrc
  1278   1279   	for %i in ($(SRC4)) do copy /Y %i tsrc
  1279   1280   	for %i in ($(SRC5)) do copy /Y %i tsrc
         1281  +	copy /Y fts5.c tsrc
         1282  +	copy /Y fts5.h tsrc
  1280   1283   	del /Q tsrc\sqlite.h.in tsrc\parse.y 2>NUL
  1281   1284   	$(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl $(OPTS) < tsrc\vdbe.c > vdbe.new
  1282   1285   	move vdbe.new tsrc\vdbe.c
  1283   1286   	echo > .target_source
  1284   1287   
  1285   1288   sqlite3.c:	.target_source sqlite3ext.h $(TOP)\tool\mksqlite3c.tcl
  1286   1289   	$(TCLSH_CMD) $(TOP)\tool\mksqlite3c.tcl $(MKSQLITE3C_ARGS)

Changes to VERSION.

     1         -3.8.12
            1  +3.9.0

Changes to autoconf/Makefile.am.

     1      1   
     2         -AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE
            2  +AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE
     3      3   
     4      4   lib_LTLIBRARIES = libsqlite3.la
     5      5   libsqlite3_la_SOURCES = sqlite3.c
     6      6   libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8
     7      7   
     8      8   bin_PROGRAMS = sqlite3
     9      9   sqlite3_SOURCES = shell.c sqlite3.c sqlite3.h

Changes to autoconf/configure.ac.

    73     73   else
    74     74     DYNAMIC_EXTENSION_FLAGS=-DSQLITE_OMIT_LOAD_EXTENSION=1
    75     75   fi
    76     76   AC_MSG_CHECKING([for whether to support dynamic extensions])
    77     77   AC_MSG_RESULT($enable_dynamic_extensions)
    78     78   AC_SUBST(DYNAMIC_EXTENSION_FLAGS)
    79     79   #-----------------------------------------------------------------------
           80  +
           81  +#-----------------------------------------------------------------------
           82  +#   --enable-fts5
           83  +#
           84  +AC_ARG_ENABLE(fts5, [AS_HELP_STRING(
           85  +  [--enable-fts5], [include fts5 support [default=no]])], 
           86  +  [], [enable_fts5=no])
           87  +if test x"$enable_fts5" == "xyes"; then
           88  +  AC_SEARCH_LIBS(log, m)
           89  +  FTS5_FLAGS=-DSQLITE_ENABLE_FTS5
           90  +fi
           91  +AC_SUBST(FTS5_FLAGS)
           92  +#-----------------------------------------------------------------------
           93  +
           94  +#-----------------------------------------------------------------------
           95  +#   --enable-json1
           96  +#
           97  +AC_ARG_ENABLE(json1, [AS_HELP_STRING(
           98  +  [--enable-json1], [include json1 support [default=no]])], 
           99  +  [], [enable_json1=no])
          100  +if test x"$enable_json1" == "xyes"; then
          101  +  JSON1_FLAGS=-DSQLITE_ENABLE_JSON1
          102  +fi
          103  +AC_SUBST(JSON1_FLAGS)
          104  +#-----------------------------------------------------------------------
    80    105   
    81    106   AC_CHECK_FUNCS(posix_fallocate)
    82    107   
    83    108   #-----------------------------------------------------------------------
    84    109   # UPDATE: Maybe it's better if users just set CFLAGS before invoking
    85    110   # configure. This option doesn't really add much...
    86    111   #

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.8.12.
            3  +# Generated by GNU Autoconf 2.69 for sqlite 3.9.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.8.12'
   730         -PACKAGE_STRING='sqlite 3.8.12'
          729  +PACKAGE_VERSION='3.9.0'
          730  +PACKAGE_STRING='sqlite 3.9.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
................................................................................
   898    898   with_tcl
   899    899   enable_readline
   900    900   with_readline_lib
   901    901   with_readline_inc
   902    902   enable_debug
   903    903   enable_amalgamation
   904    904   enable_load_extension
          905  +enable_fts3
          906  +enable_fts4
          907  +enable_fts5
          908  +enable_json1
          909  +enable_rtree
   905    910   enable_gcov
   906    911   '
   907    912         ac_precious_vars='build_alias
   908    913   host_alias
   909    914   target_alias
   910    915   CC
   911    916   CFLAGS
................................................................................
  1450   1455   #
  1451   1456   # Report the --help message.
  1452   1457   #
  1453   1458   if test "$ac_init_help" = "long"; then
  1454   1459     # Omit some internal or obsolete options to make the list less imposing.
  1455   1460     # This message is too long to be a string in the A/UX 3.1 sh.
  1456   1461     cat <<_ACEOF
  1457         -\`configure' configures sqlite 3.8.12 to adapt to many kinds of systems.
         1462  +\`configure' configures sqlite 3.9.0 to adapt to many kinds of systems.
  1458   1463   
  1459   1464   Usage: $0 [OPTION]... [VAR=VALUE]...
  1460   1465   
  1461   1466   To assign environment variables (e.g., CC, CFLAGS...), specify them as
  1462   1467   VAR=VALUE.  See below for descriptions of some of the useful variables.
  1463   1468   
  1464   1469   Defaults for the options are specified in brackets.
................................................................................
  1515   1520     --build=BUILD     configure for building on BUILD [guessed]
  1516   1521     --host=HOST       cross-compile to build programs to run on HOST [BUILD]
  1517   1522   _ACEOF
  1518   1523   fi
  1519   1524   
  1520   1525   if test -n "$ac_init_help"; then
  1521   1526     case $ac_init_help in
  1522         -     short | recursive ) echo "Configuration of sqlite 3.8.12:";;
         1527  +     short | recursive ) echo "Configuration of sqlite 3.9.0:";;
  1523   1528      esac
  1524   1529     cat <<\_ACEOF
  1525   1530   
  1526   1531   Optional Features:
  1527   1532     --disable-option-checking  ignore unrecognized --enable/--with options
  1528   1533     --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
  1529   1534     --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
................................................................................
  1540   1545     --disable-tcl           do not build TCL extension
  1541   1546     --disable-readline      disable readline support [default=detect]
  1542   1547     --enable-debug          enable debugging & verbose explain
  1543   1548     --disable-amalgamation  Disable the amalgamation and instead build all files
  1544   1549                             separately
  1545   1550     --disable-load-extension
  1546   1551                             Disable loading of external extensions
         1552  +  --enable-fts3           Enable the FTS3 extension
         1553  +  --enable-fts4           Enable the FTS4 extension
         1554  +  --enable-fts5           Enable the FTS5 extension
         1555  +  --enable-json1          Enable the JSON1 extension
         1556  +  --enable-rtree          Enable the RTREE extension
  1547   1557     --enable-gcov           Enable coverage testing using gcov
  1548   1558   
  1549   1559   Optional Packages:
  1550   1560     --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
  1551   1561     --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
  1552   1562     --with-pic              try to use only PIC/non-PIC objects [default=use
  1553   1563                             both]
................................................................................
  1630   1640       cd "$ac_pwd" || { ac_status=$?; break; }
  1631   1641     done
  1632   1642   fi
  1633   1643   
  1634   1644   test -n "$ac_init_help" && exit $ac_status
  1635   1645   if $ac_init_version; then
  1636   1646     cat <<\_ACEOF
  1637         -sqlite configure 3.8.12
         1647  +sqlite configure 3.9.0
  1638   1648   generated by GNU Autoconf 2.69
  1639   1649   
  1640   1650   Copyright (C) 2012 Free Software Foundation, Inc.
  1641   1651   This configure script is free software; the Free Software Foundation
  1642   1652   gives unlimited permission to copy, distribute and modify it.
  1643   1653   _ACEOF
  1644   1654     exit
................................................................................
  2049   2059     eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
  2050   2060   
  2051   2061   } # ac_fn_c_check_header_mongrel
  2052   2062   cat >config.log <<_ACEOF
  2053   2063   This file contains any messages produced by compilers while
  2054   2064   running configure, to aid debugging if configure makes a mistake.
  2055   2065   
  2056         -It was created by sqlite $as_me 3.8.12, which was
         2066  +It was created by sqlite $as_me 3.9.0, which was
  2057   2067   generated by GNU Autoconf 2.69.  Invocation command line was
  2058   2068   
  2059   2069     $ $0 $@
  2060   2070   
  2061   2071   _ACEOF
  2062   2072   exec 5>>config.log
  2063   2073   {
................................................................................
  3907   3917   { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
  3908   3918   $as_echo_n "checking the name lister ($NM) interface... " >&6; }
  3909   3919   if ${lt_cv_nm_interface+:} false; then :
  3910   3920     $as_echo_n "(cached) " >&6
  3911   3921   else
  3912   3922     lt_cv_nm_interface="BSD nm"
  3913   3923     echo "int some_variable = 0;" > conftest.$ac_ext
  3914         -  (eval echo "\"\$as_me:3914: $ac_compile\"" >&5)
         3924  +  (eval echo "\"\$as_me:3924: $ac_compile\"" >&5)
  3915   3925     (eval "$ac_compile" 2>conftest.err)
  3916   3926     cat conftest.err >&5
  3917         -  (eval echo "\"\$as_me:3917: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
         3927  +  (eval echo "\"\$as_me:3927: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
  3918   3928     (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
  3919   3929     cat conftest.err >&5
  3920         -  (eval echo "\"\$as_me:3920: output\"" >&5)
         3930  +  (eval echo "\"\$as_me:3930: output\"" >&5)
  3921   3931     cat conftest.out >&5
  3922   3932     if $GREP 'External.*some_variable' conftest.out > /dev/null; then
  3923   3933       lt_cv_nm_interface="MS dumpbin"
  3924   3934     fi
  3925   3935     rm -f conftest*
  3926   3936   fi
  3927   3937   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
................................................................................
  5119   5129   	;;
  5120   5130       esac
  5121   5131     fi
  5122   5132     rm -rf conftest*
  5123   5133     ;;
  5124   5134   *-*-irix6*)
  5125   5135     # Find out which ABI we are using.
  5126         -  echo '#line 5126 "configure"' > conftest.$ac_ext
         5136  +  echo '#line 5136 "configure"' > conftest.$ac_ext
  5127   5137     if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
  5128   5138     (eval $ac_compile) 2>&5
  5129   5139     ac_status=$?
  5130   5140     $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  5131   5141     test $ac_status = 0; }; then
  5132   5142       if test "$lt_cv_prog_gnu_ld" = yes; then
  5133   5143         case `/usr/bin/file conftest.$ac_objext` in
................................................................................
  6644   6654      # Note that $ac_compile itself does not contain backslashes and begins
  6645   6655      # with a dollar sign (not a hyphen), so the echo should work correctly.
  6646   6656      # The option is referenced via a variable to avoid confusing sed.
  6647   6657      lt_compile=`echo "$ac_compile" | $SED \
  6648   6658      -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
  6649   6659      -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
  6650   6660      -e 's:$: $lt_compiler_flag:'`
  6651         -   (eval echo "\"\$as_me:6651: $lt_compile\"" >&5)
         6661  +   (eval echo "\"\$as_me:6661: $lt_compile\"" >&5)
  6652   6662      (eval "$lt_compile" 2>conftest.err)
  6653   6663      ac_status=$?
  6654   6664      cat conftest.err >&5
  6655         -   echo "$as_me:6655: \$? = $ac_status" >&5
         6665  +   echo "$as_me:6665: \$? = $ac_status" >&5
  6656   6666      if (exit $ac_status) && test -s "$ac_outfile"; then
  6657   6667        # The compiler can only warn and ignore the option if not recognized
  6658   6668        # So say no if there are warnings other than the usual output.
  6659   6669        $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
  6660   6670        $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
  6661   6671        if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
  6662   6672          lt_cv_prog_compiler_rtti_exceptions=yes
................................................................................
  6983   6993      # Note that $ac_compile itself does not contain backslashes and begins
  6984   6994      # with a dollar sign (not a hyphen), so the echo should work correctly.
  6985   6995      # The option is referenced via a variable to avoid confusing sed.
  6986   6996      lt_compile=`echo "$ac_compile" | $SED \
  6987   6997      -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
  6988   6998      -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
  6989   6999      -e 's:$: $lt_compiler_flag:'`
  6990         -   (eval echo "\"\$as_me:6990: $lt_compile\"" >&5)
         7000  +   (eval echo "\"\$as_me:7000: $lt_compile\"" >&5)
  6991   7001      (eval "$lt_compile" 2>conftest.err)
  6992   7002      ac_status=$?
  6993   7003      cat conftest.err >&5
  6994         -   echo "$as_me:6994: \$? = $ac_status" >&5
         7004  +   echo "$as_me:7004: \$? = $ac_status" >&5
  6995   7005      if (exit $ac_status) && test -s "$ac_outfile"; then
  6996   7006        # The compiler can only warn and ignore the option if not recognized
  6997   7007        # So say no if there are warnings other than the usual output.
  6998   7008        $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
  6999   7009        $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
  7000   7010        if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
  7001   7011          lt_cv_prog_compiler_pic_works=yes
................................................................................
  7088   7098      # (2) before a word containing "conftest.", or (3) at the end.
  7089   7099      # Note that $ac_compile itself does not contain backslashes and begins
  7090   7100      # with a dollar sign (not a hyphen), so the echo should work correctly.
  7091   7101      lt_compile=`echo "$ac_compile" | $SED \
  7092   7102      -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
  7093   7103      -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
  7094   7104      -e 's:$: $lt_compiler_flag:'`
  7095         -   (eval echo "\"\$as_me:7095: $lt_compile\"" >&5)
         7105  +   (eval echo "\"\$as_me:7105: $lt_compile\"" >&5)
  7096   7106      (eval "$lt_compile" 2>out/conftest.err)
  7097   7107      ac_status=$?
  7098   7108      cat out/conftest.err >&5
  7099         -   echo "$as_me:7099: \$? = $ac_status" >&5
         7109  +   echo "$as_me:7109: \$? = $ac_status" >&5
  7100   7110      if (exit $ac_status) && test -s out/conftest2.$ac_objext
  7101   7111      then
  7102   7112        # The compiler can only warn and ignore the option if not recognized
  7103   7113        # So say no if there are warnings
  7104   7114        $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
  7105   7115        $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
  7106   7116        if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
................................................................................
  7143   7153      # (2) before a word containing "conftest.", or (3) at the end.
  7144   7154      # Note that $ac_compile itself does not contain backslashes and begins
  7145   7155      # with a dollar sign (not a hyphen), so the echo should work correctly.
  7146   7156      lt_compile=`echo "$ac_compile" | $SED \
  7147   7157      -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
  7148   7158      -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
  7149   7159      -e 's:$: $lt_compiler_flag:'`
  7150         -   (eval echo "\"\$as_me:7150: $lt_compile\"" >&5)
         7160  +   (eval echo "\"\$as_me:7160: $lt_compile\"" >&5)
  7151   7161      (eval "$lt_compile" 2>out/conftest.err)
  7152   7162      ac_status=$?
  7153   7163      cat out/conftest.err >&5
  7154         -   echo "$as_me:7154: \$? = $ac_status" >&5
         7164  +   echo "$as_me:7164: \$? = $ac_status" >&5
  7155   7165      if (exit $ac_status) && test -s out/conftest2.$ac_objext
  7156   7166      then
  7157   7167        # The compiler can only warn and ignore the option if not recognized
  7158   7168        # So say no if there are warnings
  7159   7169        $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
  7160   7170        $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
  7161   7171        if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
................................................................................
  9523   9533   else
  9524   9534     	  if test "$cross_compiling" = yes; then :
  9525   9535     lt_cv_dlopen_self=cross
  9526   9536   else
  9527   9537     lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
  9528   9538     lt_status=$lt_dlunknown
  9529   9539     cat > conftest.$ac_ext <<_LT_EOF
  9530         -#line 9530 "configure"
         9540  +#line 9540 "configure"
  9531   9541   #include "confdefs.h"
  9532   9542   
  9533   9543   #if HAVE_DLFCN_H
  9534   9544   #include <dlfcn.h>
  9535   9545   #endif
  9536   9546   
  9537   9547   #include <stdio.h>
................................................................................
  9619   9629   else
  9620   9630     	  if test "$cross_compiling" = yes; then :
  9621   9631     lt_cv_dlopen_self_static=cross
  9622   9632   else
  9623   9633     lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
  9624   9634     lt_status=$lt_dlunknown
  9625   9635     cat > conftest.$ac_ext <<_LT_EOF
  9626         -#line 9626 "configure"
         9636  +#line 9636 "configure"
  9627   9637   #include "confdefs.h"
  9628   9638   
  9629   9639   #if HAVE_DLFCN_H
  9630   9640   #include <dlfcn.h>
  9631   9641   #endif
  9632   9642   
  9633   9643   #include <stdio.h>
................................................................................
 11218  11228     test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
 11219  11229   
 11220  11230   fi
 11221  11231   
 11222  11232   else
 11223  11233     OPT_FEATURE_FLAGS="-DSQLITE_OMIT_LOAD_EXTENSION=1"
 11224  11234   fi
        11235  +
        11236  +#########
        11237  +# See whether we should enable Full Text Search extensions
        11238  +# Check whether --enable-fts3 was given.
        11239  +if test "${enable_fts3+set}" = set; then :
        11240  +  enableval=$enable_fts3; enable_fts3=yes
        11241  +else
        11242  +  enable_fts3=no
        11243  +fi
        11244  +
        11245  +if test "${enable_fts3}" = "yes" ; then
        11246  +  OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS3"
        11247  +fi
        11248  +# Check whether --enable-fts4 was given.
        11249  +if test "${enable_fts4+set}" = set; then :
        11250  +  enableval=$enable_fts4; enable_fts4=yes
        11251  +else
        11252  +  enable_fts4=no
        11253  +fi
        11254  +
        11255  +if test "${enable_fts4}" = "yes" ; then
        11256  +  OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS4"
        11257  +  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
        11258  +$as_echo_n "checking for library containing log... " >&6; }
        11259  +if ${ac_cv_search_log+:} false; then :
        11260  +  $as_echo_n "(cached) " >&6
        11261  +else
        11262  +  ac_func_search_save_LIBS=$LIBS
        11263  +cat confdefs.h - <<_ACEOF >conftest.$ac_ext
        11264  +/* end confdefs.h.  */
        11265  +
        11266  +/* Override any GCC internal prototype to avoid an error.
        11267  +   Use char because int might match the return type of a GCC
        11268  +   builtin and then its argument prototype would still apply.  */
        11269  +#ifdef __cplusplus
        11270  +extern "C"
        11271  +#endif
        11272  +char log ();
        11273  +int
        11274  +main ()
        11275  +{
        11276  +return log ();
        11277  +  ;
        11278  +  return 0;
        11279  +}
        11280  +_ACEOF
        11281  +for ac_lib in '' m; do
        11282  +  if test -z "$ac_lib"; then
        11283  +    ac_res="none required"
        11284  +  else
        11285  +    ac_res=-l$ac_lib
        11286  +    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
        11287  +  fi
        11288  +  if ac_fn_c_try_link "$LINENO"; then :
        11289  +  ac_cv_search_log=$ac_res
        11290  +fi
        11291  +rm -f core conftest.err conftest.$ac_objext \
        11292  +    conftest$ac_exeext
        11293  +  if ${ac_cv_search_log+:} false; then :
        11294  +  break
        11295  +fi
        11296  +done
        11297  +if ${ac_cv_search_log+:} false; then :
        11298  +
        11299  +else
        11300  +  ac_cv_search_log=no
        11301  +fi
        11302  +rm conftest.$ac_ext
        11303  +LIBS=$ac_func_search_save_LIBS
        11304  +fi
        11305  +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_log" >&5
        11306  +$as_echo "$ac_cv_search_log" >&6; }
        11307  +ac_res=$ac_cv_search_log
        11308  +if test "$ac_res" != no; then :
        11309  +  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
        11310  +
        11311  +fi
        11312  +
        11313  +fi
        11314  +# Check whether --enable-fts5 was given.
        11315  +if test "${enable_fts5+set}" = set; then :
        11316  +  enableval=$enable_fts5; enable_fts5=yes
        11317  +else
        11318  +  enable_fts5=no
        11319  +fi
        11320  +
        11321  +if test "${enable_fts5}" = "yes" ; then
        11322  +  OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS5"
        11323  +  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
        11324  +$as_echo_n "checking for library containing log... " >&6; }
        11325  +if ${ac_cv_search_log+:} false; then :
        11326  +  $as_echo_n "(cached) " >&6
        11327  +else
        11328  +  ac_func_search_save_LIBS=$LIBS
        11329  +cat confdefs.h - <<_ACEOF >conftest.$ac_ext
        11330  +/* end confdefs.h.  */
        11331  +
        11332  +/* Override any GCC internal prototype to avoid an error.
        11333  +   Use char because int might match the return type of a GCC
        11334  +   builtin and then its argument prototype would still apply.  */
        11335  +#ifdef __cplusplus
        11336  +extern "C"
        11337  +#endif
        11338  +char log ();
        11339  +int
        11340  +main ()
        11341  +{
        11342  +return log ();
        11343  +  ;
        11344  +  return 0;
        11345  +}
        11346  +_ACEOF
        11347  +for ac_lib in '' m; do
        11348  +  if test -z "$ac_lib"; then
        11349  +    ac_res="none required"
        11350  +  else
        11351  +    ac_res=-l$ac_lib
        11352  +    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
        11353  +  fi
        11354  +  if ac_fn_c_try_link "$LINENO"; then :
        11355  +  ac_cv_search_log=$ac_res
        11356  +fi
        11357  +rm -f core conftest.err conftest.$ac_objext \
        11358  +    conftest$ac_exeext
        11359  +  if ${ac_cv_search_log+:} false; then :
        11360  +  break
        11361  +fi
        11362  +done
        11363  +if ${ac_cv_search_log+:} false; then :
        11364  +
        11365  +else
        11366  +  ac_cv_search_log=no
        11367  +fi
        11368  +rm conftest.$ac_ext
        11369  +LIBS=$ac_func_search_save_LIBS
        11370  +fi
        11371  +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_log" >&5
        11372  +$as_echo "$ac_cv_search_log" >&6; }
        11373  +ac_res=$ac_cv_search_log
        11374  +if test "$ac_res" != no; then :
        11375  +  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
        11376  +
        11377  +fi
        11378  +
        11379  +fi
        11380  +
        11381  +#########
        11382  +# See whether we should enable JSON1
        11383  +# Check whether --enable-json1 was given.
        11384  +if test "${enable_json1+set}" = set; then :
        11385  +  enableval=$enable_json1; enable_json1=yes
        11386  +else
        11387  +  enable_json1=no
        11388  +fi
        11389  +
        11390  +if test "${enable_json1}" = "yes" ; then
        11391  +  OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_JSON1"
        11392  +fi
        11393  +
        11394  +#########
        11395  +# See whether we should enable RTREE
        11396  +# Check whether --enable-rtree was given.
        11397  +if test "${enable_rtree+set}" = set; then :
        11398  +  enableval=$enable_rtree; enable_rtree=yes
        11399  +else
        11400  +  enable_rtree=no
        11401  +fi
        11402  +
        11403  +if test "${enable_rtree}" = "yes" ; then
        11404  +  OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_RTREE"
        11405  +fi
 11225  11406   
 11226  11407   #########
 11227  11408   # attempt to duplicate any OMITS and ENABLES into the $(OPT_FEATURE_FLAGS) parameter
 11228  11409   for option in $CFLAGS $CPPFLAGS
 11229  11410   do
 11230  11411     case $option in
 11231  11412       -DSQLITE_OMIT*) OPT_FEATURE_FLAGS="$OPT_FEATURE_FLAGS $option";;
................................................................................
 11804  11985   test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
 11805  11986   
 11806  11987   cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 11807  11988   # Save the log message, to keep $0 and so on meaningful, and to
 11808  11989   # report actual input values of CONFIG_FILES etc. instead of their
 11809  11990   # values after options handling.
 11810  11991   ac_log="
 11811         -This file was extended by sqlite $as_me 3.8.12, which was
        11992  +This file was extended by sqlite $as_me 3.9.0, which was
 11812  11993   generated by GNU Autoconf 2.69.  Invocation command line was
 11813  11994   
 11814  11995     CONFIG_FILES    = $CONFIG_FILES
 11815  11996     CONFIG_HEADERS  = $CONFIG_HEADERS
 11816  11997     CONFIG_LINKS    = $CONFIG_LINKS
 11817  11998     CONFIG_COMMANDS = $CONFIG_COMMANDS
 11818  11999     $ $0 $@
................................................................................
 11870  12051   
 11871  12052   Report bugs to the package provider."
 11872  12053   
 11873  12054   _ACEOF
 11874  12055   cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 11875  12056   ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 11876  12057   ac_cs_version="\\
 11877         -sqlite config.status 3.8.12
        12058  +sqlite config.status 3.9.0
 11878  12059   configured by $0, generated by GNU Autoconf 2.69,
 11879  12060     with options \\"\$ac_cs_config\\"
 11880  12061   
 11881  12062   Copyright (C) 2012 Free Software Foundation, Inc.
 11882  12063   This config.status script is free software; the Free Software Foundation
 11883  12064   gives unlimited permission to copy, distribute and modify it."
 11884  12065   

Changes to configure.ac.

   555    555         [use_loadextension=$enableval],[use_loadextension=yes])
   556    556   if test "${use_loadextension}" = "yes" ; then
   557    557     OPT_FEATURE_FLAGS=""
   558    558     AC_SEARCH_LIBS(dlopen, dl)
   559    559   else
   560    560     OPT_FEATURE_FLAGS="-DSQLITE_OMIT_LOAD_EXTENSION=1"
   561    561   fi
          562  +
          563  +#########
          564  +# See whether we should enable Full Text Search extensions
          565  +AC_ARG_ENABLE(fts3, AC_HELP_STRING([--enable-fts3],
          566  +      [Enable the FTS3 extension]),
          567  +      [enable_fts3=yes],[enable_fts3=no])
          568  +if test "${enable_fts3}" = "yes" ; then
          569  +  OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS3"
          570  +fi
          571  +AC_ARG_ENABLE(fts4, AC_HELP_STRING([--enable-fts4],
          572  +      [Enable the FTS4 extension]),
          573  +      [enable_fts4=yes],[enable_fts4=no])
          574  +if test "${enable_fts4}" = "yes" ; then
          575  +  OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS4"
          576  +  AC_SEARCH_LIBS([log],[m])
          577  +fi
          578  +AC_ARG_ENABLE(fts5, AC_HELP_STRING([--enable-fts5],
          579  +      [Enable the FTS5 extension]),
          580  +      [enable_fts5=yes],[enable_fts5=no])
          581  +if test "${enable_fts5}" = "yes" ; then
          582  +  OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS5"
          583  +  AC_SEARCH_LIBS([log],[m])
          584  +fi
          585  +
          586  +#########
          587  +# See whether we should enable JSON1
          588  +AC_ARG_ENABLE(json1, AC_HELP_STRING([--enable-json1],
          589  +      [Enable the JSON1 extension]),
          590  +      [enable_json1=yes],[enable_json1=no])
          591  +if test "${enable_json1}" = "yes" ; then
          592  +  OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_JSON1"
          593  +fi
          594  +
          595  +#########
          596  +# See whether we should enable RTREE
          597  +AC_ARG_ENABLE(rtree, AC_HELP_STRING([--enable-rtree],
          598  +      [Enable the RTREE extension]),
          599  +      [enable_rtree=yes],[enable_rtree=no])
          600  +if test "${enable_rtree}" = "yes" ; then
          601  +  OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_RTREE"
          602  +fi
   562    603   
   563    604   #########
   564    605   # attempt to duplicate any OMITS and ENABLES into the $(OPT_FEATURE_FLAGS) parameter
   565    606   for option in $CFLAGS $CPPFLAGS
   566    607   do
   567    608     case $option in
   568    609       -DSQLITE_OMIT*) OPT_FEATURE_FLAGS="$OPT_FEATURE_FLAGS $option";;

Changes to ext/fts3/fts3.c.

  1512   1512   static void fts3SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){
  1513   1513   #if SQLITE_VERSION_NUMBER>=3008002
  1514   1514     if( sqlite3_libversion_number()>=3008002 ){
  1515   1515       pIdxInfo->estimatedRows = nRow;
  1516   1516     }
  1517   1517   #endif
  1518   1518   }
         1519  +
         1520  +/*
         1521  +** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this
         1522  +** extension is currently being used by a version of SQLite too old to
         1523  +** support index-info flags. In that case this function is a no-op.
         1524  +*/
         1525  +static void fts3SetUniqueFlag(sqlite3_index_info *pIdxInfo){
         1526  +#if SQLITE_VERSION_NUMBER>=3008012
         1527  +  if( sqlite3_libversion_number()>=3008012 ){
         1528  +    pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE;
         1529  +  }
         1530  +#endif
         1531  +}
  1519   1532   
  1520   1533   /* 
  1521   1534   ** Implementation of the xBestIndex method for FTS3 tables. There
  1522   1535   ** are three possible strategies, in order of preference:
  1523   1536   **
  1524   1537   **   1. Direct lookup by rowid or docid. 
  1525   1538   **   2. Full-text search using a MATCH operator on a non-docid column.
................................................................................
  1602   1615           case SQLITE_INDEX_CONSTRAINT_LE:
  1603   1616           case SQLITE_INDEX_CONSTRAINT_LT:
  1604   1617             iDocidLe = i;
  1605   1618             break;
  1606   1619         }
  1607   1620       }
  1608   1621     }
         1622  +
         1623  +  /* If using a docid=? or rowid=? strategy, set the UNIQUE flag. */
         1624  +  if( pInfo->idxNum==FTS3_DOCID_SEARCH ) fts3SetUniqueFlag(pInfo);
  1609   1625   
  1610   1626     iIdx = 1;
  1611   1627     if( iCons>=0 ){
  1612   1628       pInfo->aConstraintUsage[iCons].argvIndex = iIdx++;
  1613   1629       pInfo->aConstraintUsage[iCons].omit = 1;
  1614   1630     } 
  1615   1631     if( iLangidCons>=0 ){

Changes to ext/fts3/fts3Int.h.

   260    260       int nPrefix;                  /* Prefix length (0 for main terms index) */
   261    261       Fts3Hash hPending;            /* Pending terms table for this index */
   262    262     } *aIndex;
   263    263     int nMaxPendingData;            /* Max pending data before flush to disk */
   264    264     int nPendingData;               /* Current bytes of pending data */
   265    265     sqlite_int64 iPrevDocid;        /* Docid of most recently inserted document */
   266    266     int iPrevLangid;                /* Langid of recently inserted document */
          267  +  int bPrevDelete;                /* True if last operation was a delete */
   267    268   
   268    269   #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
   269    270     /* State variables used for validating that the transaction control
   270    271     ** methods of the virtual table are called at appropriate times.  These
   271    272     ** values do not contribute to FTS functionality; they are used for
   272    273     ** verifying the operation of the SQLite core.
   273    274     */

Changes to ext/fts3/fts3_expr.c.

   789    789     Fts3Expr *pFree = 0;            /* List of free nodes. Linked by pParent. */
   790    790     int eType = pRoot->eType;       /* Type of node in this tree */
   791    791   
   792    792     if( nMaxDepth==0 ){
   793    793       rc = SQLITE_ERROR;
   794    794     }
   795    795   
   796         -  if( rc==SQLITE_OK && (eType==FTSQUERY_AND || eType==FTSQUERY_OR) ){
   797         -    Fts3Expr **apLeaf;
   798         -    apLeaf = (Fts3Expr **)sqlite3_malloc(sizeof(Fts3Expr *) * nMaxDepth);
   799         -    if( 0==apLeaf ){
   800         -      rc = SQLITE_NOMEM;
   801         -    }else{
   802         -      memset(apLeaf, 0, sizeof(Fts3Expr *) * nMaxDepth);
   803         -    }
   804         -
   805         -    if( rc==SQLITE_OK ){
   806         -      int i;
   807         -      Fts3Expr *p;
   808         -
   809         -      /* Set $p to point to the left-most leaf in the tree of eType nodes. */
   810         -      for(p=pRoot; p->eType==eType; p=p->pLeft){
   811         -        assert( p->pParent==0 || p->pParent->pLeft==p );
   812         -        assert( p->pLeft && p->pRight );
   813         -      }
   814         -
   815         -      /* This loop runs once for each leaf in the tree of eType nodes. */
   816         -      while( 1 ){
   817         -        int iLvl;
   818         -        Fts3Expr *pParent = p->pParent;     /* Current parent of p */
   819         -
   820         -        assert( pParent==0 || pParent->pLeft==p );
   821         -        p->pParent = 0;
   822         -        if( pParent ){
   823         -          pParent->pLeft = 0;
   824         -        }else{
   825         -          pRoot = 0;
   826         -        }
   827         -        rc = fts3ExprBalance(&p, nMaxDepth-1);
   828         -        if( rc!=SQLITE_OK ) break;
   829         -
   830         -        for(iLvl=0; p && iLvl<nMaxDepth; iLvl++){
   831         -          if( apLeaf[iLvl]==0 ){
   832         -            apLeaf[iLvl] = p;
   833         -            p = 0;
   834         -          }else{
   835         -            assert( pFree );
   836         -            pFree->pLeft = apLeaf[iLvl];
   837         -            pFree->pRight = p;
   838         -            pFree->pLeft->pParent = pFree;
   839         -            pFree->pRight->pParent = pFree;
   840         -
   841         -            p = pFree;
   842         -            pFree = pFree->pParent;
   843         -            p->pParent = 0;
   844         -            apLeaf[iLvl] = 0;
   845         -          }
   846         -        }
   847         -        if( p ){
   848         -          sqlite3Fts3ExprFree(p);
   849         -          rc = SQLITE_TOOBIG;
   850         -          break;
   851         -        }
   852         -
   853         -        /* If that was the last leaf node, break out of the loop */
   854         -        if( pParent==0 ) break;
   855         -
   856         -        /* Set $p to point to the next leaf in the tree of eType nodes */
   857         -        for(p=pParent->pRight; p->eType==eType; p=p->pLeft);
   858         -
   859         -        /* Remove pParent from the original tree. */
   860         -        assert( pParent->pParent==0 || pParent->pParent->pLeft==pParent );
   861         -        pParent->pRight->pParent = pParent->pParent;
   862         -        if( pParent->pParent ){
   863         -          pParent->pParent->pLeft = pParent->pRight;
   864         -        }else{
   865         -          assert( pParent==pRoot );
   866         -          pRoot = pParent->pRight;
   867         -        }
   868         -
   869         -        /* Link pParent into the free node list. It will be used as an
   870         -        ** internal node of the new tree.  */
   871         -        pParent->pParent = pFree;
   872         -        pFree = pParent;
          796  +  if( rc==SQLITE_OK ){
          797  +    if( (eType==FTSQUERY_AND || eType==FTSQUERY_OR) ){
          798  +      Fts3Expr **apLeaf;
          799  +      apLeaf = (Fts3Expr **)sqlite3_malloc(sizeof(Fts3Expr *) * nMaxDepth);
          800  +      if( 0==apLeaf ){
          801  +        rc = SQLITE_NOMEM;
          802  +      }else{
          803  +        memset(apLeaf, 0, sizeof(Fts3Expr *) * nMaxDepth);
   873    804         }
   874    805   
   875    806         if( rc==SQLITE_OK ){
   876         -        p = 0;
   877         -        for(i=0; i<nMaxDepth; i++){
   878         -          if( apLeaf[i] ){
   879         -            if( p==0 ){
   880         -              p = apLeaf[i];
   881         -              p->pParent = 0;
          807  +        int i;
          808  +        Fts3Expr *p;
          809  +
          810  +        /* Set $p to point to the left-most leaf in the tree of eType nodes. */
          811  +        for(p=pRoot; p->eType==eType; p=p->pLeft){
          812  +          assert( p->pParent==0 || p->pParent->pLeft==p );
          813  +          assert( p->pLeft && p->pRight );
          814  +        }
          815  +
          816  +        /* This loop runs once for each leaf in the tree of eType nodes. */
          817  +        while( 1 ){
          818  +          int iLvl;
          819  +          Fts3Expr *pParent = p->pParent;     /* Current parent of p */
          820  +
          821  +          assert( pParent==0 || pParent->pLeft==p );
          822  +          p->pParent = 0;
          823  +          if( pParent ){
          824  +            pParent->pLeft = 0;
          825  +          }else{
          826  +            pRoot = 0;
          827  +          }
          828  +          rc = fts3ExprBalance(&p, nMaxDepth-1);
          829  +          if( rc!=SQLITE_OK ) break;
          830  +
          831  +          for(iLvl=0; p && iLvl<nMaxDepth; iLvl++){
          832  +            if( apLeaf[iLvl]==0 ){
          833  +              apLeaf[iLvl] = p;
          834  +              p = 0;
   882    835               }else{
   883         -              assert( pFree!=0 );
          836  +              assert( pFree );
          837  +              pFree->pLeft = apLeaf[iLvl];
   884    838                 pFree->pRight = p;
   885         -              pFree->pLeft = apLeaf[i];
   886    839                 pFree->pLeft->pParent = pFree;
   887    840                 pFree->pRight->pParent = pFree;
   888    841   
   889    842                 p = pFree;
   890    843                 pFree = pFree->pParent;
   891    844                 p->pParent = 0;
          845  +              apLeaf[iLvl] = 0;
          846  +            }
          847  +          }
          848  +          if( p ){
          849  +            sqlite3Fts3ExprFree(p);
          850  +            rc = SQLITE_TOOBIG;
          851  +            break;
          852  +          }
          853  +
          854  +          /* If that was the last leaf node, break out of the loop */
          855  +          if( pParent==0 ) break;
          856  +
          857  +          /* Set $p to point to the next leaf in the tree of eType nodes */
          858  +          for(p=pParent->pRight; p->eType==eType; p=p->pLeft);
          859  +
          860  +          /* Remove pParent from the original tree. */
          861  +          assert( pParent->pParent==0 || pParent->pParent->pLeft==pParent );
          862  +          pParent->pRight->pParent = pParent->pParent;
          863  +          if( pParent->pParent ){
          864  +            pParent->pParent->pLeft = pParent->pRight;
          865  +          }else{
          866  +            assert( pParent==pRoot );
          867  +            pRoot = pParent->pRight;
          868  +          }
          869  +
          870  +          /* Link pParent into the free node list. It will be used as an
          871  +          ** internal node of the new tree.  */
          872  +          pParent->pParent = pFree;
          873  +          pFree = pParent;
          874  +        }
          875  +
          876  +        if( rc==SQLITE_OK ){
          877  +          p = 0;
          878  +          for(i=0; i<nMaxDepth; i++){
          879  +            if( apLeaf[i] ){
          880  +              if( p==0 ){
          881  +                p = apLeaf[i];
          882  +                p->pParent = 0;
          883  +              }else{
          884  +                assert( pFree!=0 );
          885  +                pFree->pRight = p;
          886  +                pFree->pLeft = apLeaf[i];
          887  +                pFree->pLeft->pParent = pFree;
          888  +                pFree->pRight->pParent = pFree;
          889  +
          890  +                p = pFree;
          891  +                pFree = pFree->pParent;
          892  +                p->pParent = 0;
          893  +              }
   892    894               }
   893    895             }
   894         -        }
   895         -        pRoot = p;
   896         -      }else{
   897         -        /* An error occurred. Delete the contents of the apLeaf[] array 
   898         -        ** and pFree list. Everything else is cleaned up by the call to
   899         -        ** sqlite3Fts3ExprFree(pRoot) below.  */
   900         -        Fts3Expr *pDel;
   901         -        for(i=0; i<nMaxDepth; i++){
   902         -          sqlite3Fts3ExprFree(apLeaf[i]);
          896  +          pRoot = p;
          897  +        }else{
          898  +          /* An error occurred. Delete the contents of the apLeaf[] array 
          899  +          ** and pFree list. Everything else is cleaned up by the call to
          900  +          ** sqlite3Fts3ExprFree(pRoot) below.  */
          901  +          Fts3Expr *pDel;
          902  +          for(i=0; i<nMaxDepth; i++){
          903  +            sqlite3Fts3ExprFree(apLeaf[i]);
          904  +          }
          905  +          while( (pDel=pFree)!=0 ){
          906  +            pFree = pDel->pParent;
          907  +            sqlite3_free(pDel);
          908  +          }
   903    909           }
   904         -        while( (pDel=pFree)!=0 ){
   905         -          pFree = pDel->pParent;
   906         -          sqlite3_free(pDel);
   907         -        }
          910  +
          911  +        assert( pFree==0 );
          912  +        sqlite3_free( apLeaf );
          913  +      }
          914  +    }else if( eType==FTSQUERY_NOT ){
          915  +      Fts3Expr *pLeft = pRoot->pLeft;
          916  +      Fts3Expr *pRight = pRoot->pRight;
          917  +
          918  +      pRoot->pLeft = 0;
          919  +      pRoot->pRight = 0;
          920  +      pLeft->pParent = 0;
          921  +      pRight->pParent = 0;
          922  +
          923  +      rc = fts3ExprBalance(&pLeft, nMaxDepth-1);
          924  +      if( rc==SQLITE_OK ){
          925  +        rc = fts3ExprBalance(&pRight, nMaxDepth-1);
   908    926         }
   909    927   
   910         -      assert( pFree==0 );
   911         -      sqlite3_free( apLeaf );
          928  +      if( rc!=SQLITE_OK ){
          929  +        sqlite3Fts3ExprFree(pRight);
          930  +        sqlite3Fts3ExprFree(pLeft);
          931  +      }else{
          932  +        assert( pLeft && pRight );
          933  +        pRoot->pLeft = pLeft;
          934  +        pLeft->pParent = pRoot;
          935  +        pRoot->pRight = pRight;
          936  +        pRight->pParent = pRoot;
          937  +      }
   912    938       }
   913    939     }
   914         -
          940  +  
   915    941     if( rc!=SQLITE_OK ){
   916    942       sqlite3Fts3ExprFree(pRoot);
   917    943       pRoot = 0;
   918    944     }
   919    945     *pp = pRoot;
   920    946     return rc;
   921    947   }

Changes to ext/fts3/fts3_write.c.

   856    856   /* 
   857    857   ** Calling this function indicates that subsequent calls to 
   858    858   ** fts3PendingTermsAdd() are to add term/position-list pairs for the
   859    859   ** contents of the document with docid iDocid.
   860    860   */
   861    861   static int fts3PendingTermsDocid(
   862    862     Fts3Table *p,                   /* Full-text table handle */
          863  +  int bDelete,                    /* True if this op is a delete */
   863    864     int iLangid,                    /* Language id of row being written */
   864    865     sqlite_int64 iDocid             /* Docid of row being written */
   865    866   ){
   866    867     assert( iLangid>=0 );
          868  +  assert( bDelete==1 || bDelete==0 );
   867    869   
   868    870     /* TODO(shess) Explore whether partially flushing the buffer on
   869    871     ** forced-flush would provide better performance.  I suspect that if
   870    872     ** we ordered the doclists by size and flushed the largest until the
   871    873     ** buffer was half empty, that would let the less frequent terms
   872    874     ** generate longer doclists.
   873    875     */
   874         -  if( iDocid<=p->iPrevDocid 
          876  +  if( iDocid<p->iPrevDocid 
          877  +   || (iDocid==p->iPrevDocid && p->bPrevDelete==0)
   875    878      || p->iPrevLangid!=iLangid
   876    879      || p->nPendingData>p->nMaxPendingData 
   877    880     ){
   878    881       int rc = sqlite3Fts3PendingTermsFlush(p);
   879    882       if( rc!=SQLITE_OK ) return rc;
   880    883     }
   881    884     p->iPrevDocid = iDocid;
   882    885     p->iPrevLangid = iLangid;
          886  +  p->bPrevDelete = bDelete;
   883    887     return SQLITE_OK;
   884    888   }
   885    889   
   886    890   /*
   887    891   ** Discard the contents of the pending-terms hash tables. 
   888    892   */
   889    893   void sqlite3Fts3PendingTermsClear(Fts3Table *p){
................................................................................
  1065   1069     assert( *pbFound==0 );
  1066   1070     if( *pRC ) return;
  1067   1071     rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid);
  1068   1072     if( rc==SQLITE_OK ){
  1069   1073       if( SQLITE_ROW==sqlite3_step(pSelect) ){
  1070   1074         int i;
  1071   1075         int iLangid = langidFromSelect(p, pSelect);
  1072         -      rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0));
         1076  +      i64 iDocid = sqlite3_column_int64(pSelect, 0);
         1077  +      rc = fts3PendingTermsDocid(p, 1, iLangid, iDocid);
  1073   1078         for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){
  1074   1079           int iCol = i-1;
  1075   1080           if( p->abNotindexed[iCol]==0 ){
  1076   1081             const char *zText = (const char *)sqlite3_column_text(pSelect, i);
  1077   1082             rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[iCol]);
  1078   1083             aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i);
  1079   1084           }
................................................................................
  1313   1318       pNext = &pReader->aDoclist[pReader->nDoclist];
  1314   1319     }
  1315   1320   
  1316   1321     if( !pNext || pNext>=&pReader->aNode[pReader->nNode] ){
  1317   1322   
  1318   1323       if( fts3SegReaderIsPending(pReader) ){
  1319   1324         Fts3HashElem *pElem = *(pReader->ppNextElem);
  1320         -      if( pElem==0 ){
  1321         -        pReader->aNode = 0;
  1322         -      }else{
         1325  +      sqlite3_free(pReader->aNode);
         1326  +      pReader->aNode = 0;
         1327  +      if( pElem ){
         1328  +        char *aCopy;
  1323   1329           PendingList *pList = (PendingList *)fts3HashData(pElem);
         1330  +        int nCopy = pList->nData+1;
  1324   1331           pReader->zTerm = (char *)fts3HashKey(pElem);
  1325   1332           pReader->nTerm = fts3HashKeysize(pElem);
  1326         -        pReader->nNode = pReader->nDoclist = pList->nData + 1;
  1327         -        pReader->aNode = pReader->aDoclist = pList->aData;
         1333  +        aCopy = (char*)sqlite3_malloc(nCopy);
         1334  +        if( !aCopy ) return SQLITE_NOMEM;
         1335  +        memcpy(aCopy, pList->aData, nCopy);
         1336  +        pReader->nNode = pReader->nDoclist = nCopy;
         1337  +        pReader->aNode = pReader->aDoclist = aCopy;
  1328   1338           pReader->ppNextElem++;
  1329   1339           assert( pReader->aNode );
  1330   1340         }
  1331   1341         return SQLITE_OK;
  1332   1342       }
  1333   1343   
  1334   1344       fts3SegReaderSetEof(pReader);
................................................................................
  1560   1570   }
  1561   1571   
  1562   1572   /*
  1563   1573   ** Free all allocations associated with the iterator passed as the 
  1564   1574   ** second argument.
  1565   1575   */
  1566   1576   void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){
  1567         -  if( pReader && !fts3SegReaderIsPending(pReader) ){
  1568         -    sqlite3_free(pReader->zTerm);
         1577  +  if( pReader ){
         1578  +    if( !fts3SegReaderIsPending(pReader) ){
         1579  +      sqlite3_free(pReader->zTerm);
         1580  +    }
  1569   1581       if( !fts3SegReaderIsRootOnly(pReader) ){
  1570   1582         sqlite3_free(pReader->aNode);
  1571         -      sqlite3_blob_close(pReader->pBlob);
  1572   1583       }
         1584  +    sqlite3_blob_close(pReader->pBlob);
  1573   1585     }
  1574   1586     sqlite3_free(pReader);
  1575   1587   }
  1576   1588   
  1577   1589   /*
  1578   1590   ** Allocate a new SegReader object.
  1579   1591   */
................................................................................
  3508   3520           aSzDel = &aSzIns[p->nColumn+1];
  3509   3521         }
  3510   3522       }
  3511   3523   
  3512   3524       while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
  3513   3525         int iCol;
  3514   3526         int iLangid = langidFromSelect(p, pStmt);
  3515         -      rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0));
         3527  +      rc = fts3PendingTermsDocid(p, 0, iLangid, sqlite3_column_int64(pStmt, 0));
  3516   3528         memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1));
  3517   3529         for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
  3518   3530           if( p->abNotindexed[iCol]==0 ){
  3519   3531             const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
  3520   3532             rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]);
  3521   3533             aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1);
  3522   3534           }
................................................................................
  5613   5625       if( bInsertDone==0 ){
  5614   5626         rc = fts3InsertData(p, apVal, pRowid);
  5615   5627         if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){
  5616   5628           rc = FTS_CORRUPT_VTAB;
  5617   5629         }
  5618   5630       }
  5619   5631       if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){
  5620         -      rc = fts3PendingTermsDocid(p, iLangid, *pRowid);
         5632  +      rc = fts3PendingTermsDocid(p, 0, iLangid, *pRowid);
  5621   5633       }
  5622   5634       if( rc==SQLITE_OK ){
  5623   5635         assert( p->iPrevDocid==*pRowid );
  5624   5636         rc = fts3InsertTerms(p, iLangid, apVal, aSzIns);
  5625   5637       }
  5626   5638       if( p->bHasDocsize ){
  5627   5639         fts3InsertDocsize(&rc, p, aSzIns);

Changes to ext/fts5/fts5Int.h.

    77     77   extern int sqlite3_fts5_may_be_corrupt;
    78     78   # define assert_nc(x) assert(sqlite3_fts5_may_be_corrupt || (x))
    79     79   #else
    80     80   # define assert_nc(x) assert(x)
    81     81   #endif
    82     82   
    83     83   typedef struct Fts5Global Fts5Global;
           84  +typedef struct Fts5Colset Fts5Colset;
           85  +
           86  +/* If a NEAR() clump or phrase may only match a specific set of columns, 
           87  +** then an object of the following type is used to record the set of columns.
           88  +** Each entry in the aiCol[] array is a column that may be matched.
           89  +**
           90  +** This object is used by fts5_expr.c and fts5_index.c.
           91  +*/
           92  +struct Fts5Colset {
           93  +  int nCol;
           94  +  int aiCol[1];
           95  +};
           96  +
           97  +
    84     98   
    85     99   /**************************************************************************
    86    100   ** Interface to code in fts5_config.c. fts5_config.c contains contains code
    87    101   ** to parse the arguments passed to the CREATE VIRTUAL TABLE statement.
    88    102   */
    89    103   
    90    104   typedef struct Fts5Config Fts5Config;
................................................................................
   301    315   ** Create/destroy an Fts5Index object.
   302    316   */
   303    317   int sqlite3Fts5IndexOpen(Fts5Config *pConfig, int bCreate, Fts5Index**, char**);
   304    318   int sqlite3Fts5IndexClose(Fts5Index *p);
   305    319   
   306    320   /*
   307    321   ** for(
   308         -**   pIter = sqlite3Fts5IndexQuery(p, "token", 5, 0);
          322  +**   sqlite3Fts5IndexQuery(p, "token", 5, 0, 0, &pIter);
   309    323   **   0==sqlite3Fts5IterEof(pIter);
   310    324   **   sqlite3Fts5IterNext(pIter)
   311    325   ** ){
   312    326   **   i64 iRowid = sqlite3Fts5IterRowid(pIter);
   313    327   ** }
   314    328   */
   315    329   
................................................................................
   317    331   ** Open a new iterator to iterate though all rowids that match the 
   318    332   ** specified token or token prefix.
   319    333   */
   320    334   int sqlite3Fts5IndexQuery(
   321    335     Fts5Index *p,                   /* FTS index to query */
   322    336     const char *pToken, int nToken, /* Token (or prefix) to query for */
   323    337     int flags,                      /* Mask of FTS5INDEX_QUERY_X flags */
   324         -  Fts5IndexIter **ppIter
          338  +  Fts5Colset *pColset,            /* Match these columns only */
          339  +  Fts5IndexIter **ppIter          /* OUT: New iterator object */
   325    340   );
   326    341   
   327    342   /*
   328    343   ** The various operations on open token or token prefix iterators opened
   329    344   ** using sqlite3Fts5IndexQuery().
   330    345   */
   331    346   int sqlite3Fts5IterEof(Fts5IndexIter*);
................................................................................
   366    381   
   367    382   /*
   368    383   ** Indicate that subsequent calls to sqlite3Fts5IndexWrite() pertain to
   369    384   ** document iDocid.
   370    385   */
   371    386   int sqlite3Fts5IndexBeginWrite(
   372    387     Fts5Index *p,                   /* Index to write to */
          388  +  int bDelete,                    /* True if current operation is a delete */
   373    389     i64 iDocid                      /* Docid to add or remove data from */
   374    390   );
   375    391   
   376    392   /*
   377    393   ** Flush any data stored in the in-memory hash tables to the database.
   378    394   ** If the bCommit flag is true, also close any open blob handles.
   379    395   */
................................................................................
   429    445   int sqlite3Fts5GetVarint32(const unsigned char *p, u32 *v);
   430    446   int sqlite3Fts5GetVarintLen(u32 iVal);
   431    447   u8 sqlite3Fts5GetVarint(const unsigned char*, u64*);
   432    448   int sqlite3Fts5PutVarint(unsigned char *p, u64 v);
   433    449   
   434    450   #define fts5GetVarint32(a,b) sqlite3Fts5GetVarint32(a,(u32*)&b)
   435    451   #define fts5GetVarint    sqlite3Fts5GetVarint
          452  +
          453  +#define fts5FastGetVarint32(a, iOff, nVal) {      \
          454  +  nVal = (a)[iOff++];                             \
          455  +  if( nVal & 0x80 ){                              \
          456  +    iOff--;                                       \
          457  +    iOff += fts5GetVarint32(&(a)[iOff], nVal);    \
          458  +  }                                               \
          459  +}
          460  +
   436    461   
   437    462   /*
   438    463   ** End of interface to code in fts5_varint.c.
   439    464   **************************************************************************/
   440    465   
   441    466   
   442    467   /**************************************************************************
................................................................................
   522    547   int sqlite3Fts5StorageClose(Fts5Storage *p);
   523    548   int sqlite3Fts5StorageRename(Fts5Storage*, const char *zName);
   524    549   
   525    550   int sqlite3Fts5DropAll(Fts5Config*);
   526    551   int sqlite3Fts5CreateTable(Fts5Config*, const char*, const char*, int, char **);
   527    552   
   528    553   int sqlite3Fts5StorageDelete(Fts5Storage *p, i64);
   529         -int sqlite3Fts5StorageInsert(Fts5Storage *p, sqlite3_value **apVal, int, i64*);
          554  +int sqlite3Fts5StorageContentInsert(Fts5Storage *p, sqlite3_value**, i64*);
          555  +int sqlite3Fts5StorageIndexInsert(Fts5Storage *p, sqlite3_value**, i64);
   530    556   
   531    557   int sqlite3Fts5StorageIntegrity(Fts5Storage *p);
   532    558   
   533    559   int sqlite3Fts5StorageStmt(Fts5Storage *p, int eStmt, sqlite3_stmt**, char**);
   534    560   void sqlite3Fts5StorageStmtRelease(Fts5Storage *p, int eStmt, sqlite3_stmt*);
   535    561   
   536    562   int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol);
................................................................................
   561    587   */
   562    588   typedef struct Fts5Expr Fts5Expr;
   563    589   typedef struct Fts5ExprNode Fts5ExprNode;
   564    590   typedef struct Fts5Parse Fts5Parse;
   565    591   typedef struct Fts5Token Fts5Token;
   566    592   typedef struct Fts5ExprPhrase Fts5ExprPhrase;
   567    593   typedef struct Fts5ExprNearset Fts5ExprNearset;
   568         -typedef struct Fts5ExprColset Fts5ExprColset;
   569    594   
   570    595   struct Fts5Token {
   571    596     const char *p;                  /* Token text (not NULL terminated) */
   572    597     int n;                          /* Size of buffer p in bytes */
   573    598   };
   574    599   
   575    600   /* Parse a MATCH expression. */
................................................................................
   629    654   
   630    655   Fts5ExprNearset *sqlite3Fts5ParseNearset(
   631    656     Fts5Parse*, 
   632    657     Fts5ExprNearset*,
   633    658     Fts5ExprPhrase* 
   634    659   );
   635    660   
   636         -Fts5ExprColset *sqlite3Fts5ParseColset(
          661  +Fts5Colset *sqlite3Fts5ParseColset(
   637    662     Fts5Parse*, 
   638         -  Fts5ExprColset*, 
          663  +  Fts5Colset*, 
   639    664     Fts5Token *
   640    665   );
   641    666   
   642    667   void sqlite3Fts5ParsePhraseFree(Fts5ExprPhrase*);
   643    668   void sqlite3Fts5ParseNearsetFree(Fts5ExprNearset*);
   644    669   void sqlite3Fts5ParseNodeFree(Fts5ExprNode*);
   645    670   
   646    671   void sqlite3Fts5ParseSetDistance(Fts5Parse*, Fts5ExprNearset*, Fts5Token*);
   647         -void sqlite3Fts5ParseSetColset(Fts5Parse*, Fts5ExprNearset*, Fts5ExprColset*);
          672  +void sqlite3Fts5ParseSetColset(Fts5Parse*, Fts5ExprNearset*, Fts5Colset*);
   648    673   void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p);
   649    674   void sqlite3Fts5ParseNear(Fts5Parse *pParse, Fts5Token*);
   650    675   
   651    676   /*
   652    677   ** End of interface to code in fts5_expr.c.
   653    678   **************************************************************************/
   654    679   

Changes to ext/fts5/fts5_aux.c.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   ******************************************************************************
    12     12   */
    13     13   
    14     14   
    15     15   #include "fts5Int.h"
    16         -#include <math.h>
           16  +#include <math.h>                 /* amalgamator: keep */
    17     17   
    18     18   /*
    19     19   ** Object used to iterate through all "coalesced phrase instances" in 
    20     20   ** a single column of the current row. If the phrase instances in the
    21     21   ** column being considered do not overlap, this object simply iterates
    22     22   ** through them. Or, if they do overlap (share one or more tokens in
    23     23   ** common), each set of overlapping instances is treated as a single

Changes to ext/fts5/fts5_buffer.c.

   181    181     if( i>=n ){
   182    182       /* EOF */
   183    183       *piOff = -1;
   184    184       return 1;  
   185    185     }else{
   186    186       i64 iOff = *piOff;
   187    187       int iVal;
   188         -    i += fts5GetVarint32(&a[i], iVal);
          188  +    fts5FastGetVarint32(a, i, iVal);
   189    189       if( iVal==1 ){
   190         -      i += fts5GetVarint32(&a[i], iVal);
          190  +      fts5FastGetVarint32(a, i, iVal);
   191    191         iOff = ((i64)iVal) << 32;
   192         -      i += fts5GetVarint32(&a[i], iVal);
          192  +      fts5FastGetVarint32(a, i, iVal);
   193    193       }
   194    194       *piOff = iOff + (iVal-2);
   195    195       *pi = i;
   196    196       return 0;
   197    197     }
   198    198   }
   199    199   
................................................................................
   229    229   int sqlite3Fts5PoslistWriterAppend(
   230    230     Fts5Buffer *pBuf, 
   231    231     Fts5PoslistWriter *pWriter,
   232    232     i64 iPos
   233    233   ){
   234    234     static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32;
   235    235     int rc = SQLITE_OK;
   236         -  if( (iPos & colmask) != (pWriter->iPrev & colmask) ){
   237         -    fts5BufferAppendVarint(&rc, pBuf, 1);
   238         -    fts5BufferAppendVarint(&rc, pBuf, (iPos >> 32));
   239         -    pWriter->iPrev = (iPos & colmask);
          236  +  if( 0==sqlite3Fts5BufferGrow(&rc, pBuf, 5+5+5) ){
          237  +    if( (iPos & colmask) != (pWriter->iPrev & colmask) ){
          238  +      pBuf->p[pBuf->n++] = 1;
          239  +      pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32));
          240  +      pWriter->iPrev = (iPos & colmask);
          241  +    }
          242  +    pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-pWriter->iPrev)+2);
          243  +    pWriter->iPrev = iPos;
   240    244     }
   241         -  fts5BufferAppendVarint(&rc, pBuf, (iPos - pWriter->iPrev) + 2);
   242         -  pWriter->iPrev = iPos;
   243    245     return rc;
   244    246   }
   245    247   
   246    248   void *sqlite3Fts5MallocZero(int *pRc, int nByte){
   247    249     void *pRet = 0;
   248    250     if( *pRc==SQLITE_OK ){
   249    251       pRet = sqlite3_malloc(nByte);
................................................................................
   286    288   ** Return true if character 't' may be part of an FTS5 bareword, or false
   287    289   ** otherwise. Characters that may be part of barewords:
   288    290   **
   289    291   **   * All non-ASCII characters,
   290    292   **   * The 52 upper and lower case ASCII characters, and
   291    293   **   * The 10 integer ASCII characters.
   292    294   **   * The underscore character "_" (0x5F).
          295  +**   * The unicode "subsitute" character (0x1A).
   293    296   */
   294    297   int sqlite3Fts5IsBareword(char t){
   295    298     u8 aBareword[128] = {
   296    299       0, 0, 0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0, 0, 0,   /* 0x00 .. 0x0F */
   297         -    0, 0, 0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0, 0, 0,   /* 0x10 .. 0x1F */
          300  +    0, 0, 0, 0, 0, 0, 0, 0,    0, 0, 1, 0, 0, 0, 0, 0,   /* 0x10 .. 0x1F */
   298    301       0, 0, 0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0, 0, 0,   /* 0x20 .. 0x2F */
   299    302       1, 1, 1, 1, 1, 1, 1, 1,    1, 1, 0, 0, 0, 0, 0, 0,   /* 0x30 .. 0x3F */
   300    303       0, 1, 1, 1, 1, 1, 1, 1,    1, 1, 1, 1, 1, 1, 1, 1,   /* 0x40 .. 0x4F */
   301    304       1, 1, 1, 1, 1, 1, 1, 1,    1, 1, 1, 0, 0, 0, 0, 1,   /* 0x50 .. 0x5F */
   302    305       0, 1, 1, 1, 1, 1, 1, 1,    1, 1, 1, 1, 1, 1, 1, 1,   /* 0x60 .. 0x6F */
   303    306       1, 1, 1, 1, 1, 1, 1, 1,    1, 1, 1, 0, 0, 0, 0, 0    /* 0x70 .. 0x7F */
   304    307     };
   305    308   
   306    309     return (t & 0x80) || aBareword[(int)t];
   307    310   }
   308    311   
   309    312   

Changes to ext/fts5/fts5_expr.c.

    28     28   
    29     29   /*
    30     30   ** Functions generated by lemon from fts5parse.y.
    31     31   */
    32     32   void *sqlite3Fts5ParserAlloc(void *(*mallocProc)(u64));
    33     33   void sqlite3Fts5ParserFree(void*, void (*freeProc)(void*));
    34     34   void sqlite3Fts5Parser(void*, int, Fts5Token, Fts5Parse*);
           35  +#ifndef NDEBUG
           36  +#include <stdio.h>
           37  +void sqlite3Fts5ParserTrace(FILE*, char*);
           38  +#endif
           39  +
    35     40   
    36     41   struct Fts5Expr {
    37     42     Fts5Index *pIndex;
    38     43     Fts5ExprNode *pRoot;
    39     44     int bDesc;                      /* Iterate in descending rowid order */
    40     45     int nPhrase;                    /* Number of phrases in expression */
    41     46     Fts5ExprPhrase **apExprPhrase;  /* Pointers to phrase objects */
................................................................................
    85     90   struct Fts5ExprPhrase {
    86     91     Fts5ExprNode *pNode;            /* FTS5_STRING node this phrase is part of */
    87     92     Fts5Buffer poslist;             /* Current position list */
    88     93     int nTerm;                      /* Number of entries in aTerm[] */
    89     94     Fts5ExprTerm aTerm[1];          /* Terms that make up this phrase */
    90     95   };
    91     96   
    92         -/*
    93         -** If a NEAR() clump may only match a specific set of columns, then
    94         -** Fts5ExprNearset.pColset points to an object of the following type.
    95         -** Each entry in the aiCol[] array
    96         -*/
    97         -struct Fts5ExprColset {
    98         -  int nCol;
    99         -  int aiCol[1];
   100         -};
   101         -
   102     97   /*
   103     98   ** One or more phrases that must appear within a certain token distance of
   104     99   ** each other within each matching document.
   105    100   */
   106    101   struct Fts5ExprNearset {
   107    102     int nNear;                      /* NEAR parameter */
   108         -  Fts5ExprColset *pColset;        /* Columns to search (NULL -> all columns) */
          103  +  Fts5Colset *pColset;            /* Columns to search (NULL -> all columns) */
   109    104     int nPhrase;                    /* Number of entries in aPhrase[] array */
   110    105     Fts5ExprPhrase *apPhrase[1];    /* Array of phrase pointers */
   111    106   };
   112    107   
   113    108   
   114    109   /*
   115    110   ** Parse context.
................................................................................
   272    267     if( p ){
   273    268       sqlite3Fts5ParseNodeFree(p->pRoot);
   274    269       sqlite3_free(p->apExprPhrase);
   275    270       sqlite3_free(p);
   276    271     }
   277    272   }
   278    273   
   279         -static int fts5ExprColsetTest(Fts5ExprColset *pColset, int iCol){
          274  +static int fts5ExprColsetTest(Fts5Colset *pColset, int iCol){
   280    275     int i;
   281    276     for(i=0; i<pColset->nCol; i++){
   282    277       if( pColset->aiCol[i]==iCol ) return 1;
   283    278     }
   284    279     return 0;
   285    280   }
   286    281   
................................................................................
   401    396   **
   402    397   ** SQLITE_OK is returned if an error occurs, or an SQLite error code 
   403    398   ** otherwise. It is not considered an error code if the current rowid is 
   404    399   ** not a match.
   405    400   */
   406    401   static int fts5ExprPhraseIsMatch(
   407    402     Fts5ExprNode *pNode,            /* Node pPhrase belongs to */
   408         -  Fts5ExprColset *pColset,        /* Restrict matches to these columns */
          403  +  Fts5Colset *pColset,            /* Restrict matches to these columns */
   409    404     Fts5ExprPhrase *pPhrase,        /* Phrase object to initialize */
   410    405     int *pbMatch                    /* OUT: Set to true if really a match */
   411    406   ){
   412    407     Fts5PoslistWriter writer = {0};
   413    408     Fts5PoslistReader aStatic[4];
   414    409     Fts5PoslistReader *aIter = aStatic;
   415    410     int i;
................................................................................
   801    796     while( p<pEnd && ((prev & 0x80) || *p!=0x01) ){
   802    797       prev = *p++;
   803    798     }
   804    799     return p - (*pa);
   805    800   }
   806    801   
   807    802   static int fts5ExprExtractColset (
   808         -  Fts5ExprColset *pColset,        /* Colset to filter on */
          803  +  Fts5Colset *pColset,            /* Colset to filter on */
   809    804     const u8 *pPos, int nPos,       /* Position list */
   810    805     Fts5Buffer *pBuf                /* Output buffer */
   811    806   ){
   812    807     int rc = SQLITE_OK;
   813    808     int i;
   814    809   
   815    810     fts5BufferZero(pBuf);
................................................................................
   864    859     ** of a single term only, grab pointers into the poslist managed by the
   865    860     ** fts5_index.c iterator object. This is much faster than synthesizing 
   866    861     ** a new poslist the way we have to for more complicated phrase or NEAR
   867    862     ** expressions.  */
   868    863     Fts5ExprNearset *pNear = pNode->pNear;
   869    864     Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
   870    865     Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter;
   871         -  Fts5ExprColset *pColset = pNear->pColset;
          866  +  Fts5Colset *pColset = pNear->pColset;
   872    867     const u8 *pPos;
   873    868     int nPos;
   874    869     int rc;
   875    870   
   876    871     assert( pNode->eType==FTS5_TERM );
   877    872     assert( pNear->nPhrase==1 && pPhrase->nTerm==1 );
   878    873     assert( pPhrase->aTerm[0].pSynonym==0 );
................................................................................
   998    993             sqlite3Fts5IterClose(p->pIter);
   999    994             p->pIter = 0;
  1000    995           }
  1001    996           rc = sqlite3Fts5IndexQuery(
  1002    997               pExpr->pIndex, p->zTerm, strlen(p->zTerm),
  1003    998               (pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) |
  1004    999               (pExpr->bDesc ? FTS5INDEX_QUERY_DESC : 0),
         1000  +            pNear->pColset,
  1005   1001               &p->pIter
  1006   1002           );
  1007   1003           assert( rc==SQLITE_OK || p->pIter==0 );
  1008   1004           if( p->pIter && 0==sqlite3Fts5IterEof(p->pIter) ){
  1009   1005             bEof = 0;
  1010   1006           }
  1011   1007         }
................................................................................
  1750   1746       nNear = FTS5_DEFAULT_NEARDIST;
  1751   1747     }
  1752   1748     pNear->nNear = nNear;
  1753   1749   }
  1754   1750   
  1755   1751   /*
  1756   1752   ** The second argument passed to this function may be NULL, or it may be
  1757         -** an existing Fts5ExprColset object. This function returns a pointer to
         1753  +** an existing Fts5Colset object. This function returns a pointer to
  1758   1754   ** a new colset object containing the contents of (p) with new value column
  1759   1755   ** number iCol appended. 
  1760   1756   **
  1761   1757   ** If an OOM error occurs, store an error code in pParse and return NULL.
  1762   1758   ** The old colset object (if any) is not freed in this case.
  1763   1759   */
  1764         -static Fts5ExprColset *fts5ParseColset(
         1760  +static Fts5Colset *fts5ParseColset(
  1765   1761     Fts5Parse *pParse,              /* Store SQLITE_NOMEM here if required */
  1766         -  Fts5ExprColset *p,              /* Existing colset object */
         1762  +  Fts5Colset *p,                  /* Existing colset object */
  1767   1763     int iCol                        /* New column to add to colset object */
  1768   1764   ){
  1769   1765     int nCol = p ? p->nCol : 0;     /* Num. columns already in colset object */
  1770         -  Fts5ExprColset *pNew;           /* New colset object to return */
         1766  +  Fts5Colset *pNew;               /* New colset object to return */
  1771   1767   
  1772   1768     assert( pParse->rc==SQLITE_OK );
  1773   1769     assert( iCol>=0 && iCol<pParse->pConfig->nCol );
  1774   1770   
  1775         -  pNew = sqlite3_realloc(p, sizeof(Fts5ExprColset) + sizeof(int)*nCol);
         1771  +  pNew = sqlite3_realloc(p, sizeof(Fts5Colset) + sizeof(int)*nCol);
  1776   1772     if( pNew==0 ){
  1777   1773       pParse->rc = SQLITE_NOMEM;
  1778   1774     }else{
  1779   1775       int *aiCol = pNew->aiCol;
  1780   1776       int i, j;
  1781   1777       for(i=0; i<nCol; i++){
  1782   1778         if( aiCol[i]==iCol ) return pNew;
................................................................................
  1793   1789       for(i=1; i<pNew->nCol; i++) assert( pNew->aiCol[i]>pNew->aiCol[i-1] );
  1794   1790   #endif
  1795   1791     }
  1796   1792   
  1797   1793     return pNew;
  1798   1794   }
  1799   1795   
  1800         -Fts5ExprColset *sqlite3Fts5ParseColset(
         1796  +Fts5Colset *sqlite3Fts5ParseColset(
  1801   1797     Fts5Parse *pParse,              /* Store SQLITE_NOMEM here if required */
  1802         -  Fts5ExprColset *pColset,        /* Existing colset object */
         1798  +  Fts5Colset *pColset,            /* Existing colset object */
  1803   1799     Fts5Token *p
  1804   1800   ){
  1805         -  Fts5ExprColset *pRet = 0;
         1801  +  Fts5Colset *pRet = 0;
  1806   1802     int iCol;
  1807   1803     char *z;                        /* Dequoted copy of token p */
  1808   1804   
  1809   1805     z = sqlite3Fts5Strndup(&pParse->rc, p->p, p->n);
  1810   1806     if( pParse->rc==SQLITE_OK ){
  1811   1807       Fts5Config *pConfig = pParse->pConfig;
  1812   1808       sqlite3Fts5Dequote(z);
................................................................................
  1828   1824   
  1829   1825     return pRet;
  1830   1826   }
  1831   1827   
  1832   1828   void sqlite3Fts5ParseSetColset(
  1833   1829     Fts5Parse *pParse, 
  1834   1830     Fts5ExprNearset *pNear, 
  1835         -  Fts5ExprColset *pColset 
         1831  +  Fts5Colset *pColset 
  1836   1832   ){
  1837   1833     if( pNear ){
  1838   1834       pNear->pColset = pColset;
  1839   1835     }else{
  1840   1836       sqlite3_free(pColset);
  1841   1837     }
  1842   1838   }
................................................................................
  2280   2276     int rc = SQLITE_OK;
  2281   2277     void *pCtx = (void*)pGlobal;
  2282   2278   
  2283   2279     for(i=0; rc==SQLITE_OK && i<(sizeof(aFunc) / sizeof(aFunc[0])); i++){
  2284   2280       struct Fts5ExprFunc *p = &aFunc[i];
  2285   2281       rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0);
  2286   2282     }
         2283  +
         2284  +  /* Avoid a warning indicating that sqlite3Fts5ParserTrace() is unused */
         2285  +#ifndef NDEBUG
         2286  +  (void)sqlite3Fts5ParserTrace;
         2287  +#endif
  2287   2288   
  2288   2289     return rc;
  2289   2290   }
  2290   2291   
  2291   2292   /*
  2292   2293   ** Return the number of phrases in expression pExpr.
  2293   2294   */

Changes to ext/fts5/fts5_index.c.

   287    287     ** Variables related to the accumulation of tokens and doclists within the
   288    288     ** in-memory hash tables before they are flushed to disk.
   289    289     */
   290    290     Fts5Hash *pHash;                /* Hash table for in-memory data */
   291    291     int nMaxPendingData;            /* Max pending data before flush to disk */
   292    292     int nPendingData;               /* Current bytes of pending data */
   293    293     i64 iWriteRowid;                /* Rowid for current doc being written */
   294         -  Fts5Buffer scratch;
          294  +  int bDelete;                    /* Current write is a delete */
   295    295   
   296    296     /* Error state. */
   297    297     int rc;                         /* Current error code */
   298    298   
   299    299     /* State used by the fts5DataXXX() functions. */
   300    300     sqlite3_blob *pReader;          /* RO incr-blob open on %_data table */
   301    301     sqlite3_stmt *pWriter;          /* "INSERT ... %_data VALUES(?,?)" */
................................................................................
   303    303     sqlite3_stmt *pIdxWriter;       /* "INSERT ... %_idx VALUES(?,?,?,?)" */
   304    304     sqlite3_stmt *pIdxDeleter;      /* "DELETE FROM %_idx WHERE segid=? */
   305    305     sqlite3_stmt *pIdxSelect;
   306    306     int nRead;                      /* Total number of blocks read */
   307    307   };
   308    308   
   309    309   struct Fts5DoclistIter {
   310         -  u8 *a;
   311         -  int n;
   312         -  int i;
          310  +  u8 *aEof;                       /* Pointer to 1 byte past end of doclist */
   313    311   
   314    312     /* Output variables. aPoslist==0 at EOF */
   315    313     i64 iRowid;
   316    314     u8 *aPoslist;
   317    315     int nPoslist;
          316  +  int nSize;
   318    317   };
   319    318   
   320    319   /*
   321    320   ** The contents of the "structure" record for each index are represented
   322    321   ** using an Fts5Structure record in memory. Which uses instances of the 
   323    322   ** other Fts5StructureXXX types as components.
   324    323   */
................................................................................
  1776   1775           }else{
  1777   1776             pIter->pLeaf->p = (u8*)pList;
  1778   1777             pIter->pLeaf->nn = nList;
  1779   1778             pIter->pLeaf->szLeaf = nList;
  1780   1779             pIter->iEndofDoclist = nList+1;
  1781   1780             sqlite3Fts5BufferSet(&p->rc, &pIter->term, strlen(zTerm), (u8*)zTerm);
  1782   1781             pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid);
         1782  +          if( pbNewTerm ) *pbNewTerm = 1;
  1783   1783           }
  1784   1784         }else{
  1785   1785           iOff = 0;
  1786   1786           /* Next entry is not on the current page */
  1787   1787           while( iOff==0 ){
  1788   1788             fts5SegIterNextPage(p, pIter);
  1789   1789             pLeaf = pIter->pLeaf;
................................................................................
  1936   1936     ){
  1937   1937       return;
  1938   1938     }
  1939   1939   
  1940   1940     pIter->pDlidx = fts5DlidxIterInit(p, bRev, iSeg, pIter->iTermLeafPgno);
  1941   1941   }
  1942   1942   
  1943         -#define fts5IndexGetVarint32(a, iOff, nVal) {     \
  1944         -  nVal = (a)[iOff++];                             \
  1945         -  if( nVal & 0x80 ){                              \
  1946         -    iOff--;                                       \
  1947         -    iOff += fts5GetVarint32(&(a)[iOff], nVal);    \
  1948         -  }                                               \
  1949         -}
  1950         -
  1951   1943   #define fts5IndexSkipVarint(a, iOff) {            \
  1952   1944     int iEnd = iOff+9;                              \
  1953   1945     while( (a[iOff++] & 0x80) && iOff<iEnd );       \
  1954   1946   }
  1955   1947   
  1956   1948   /*
  1957   1949   ** The iterator object passed as the second argument currently contains
................................................................................
  1990   1982     iPgidx = szLeaf;
  1991   1983     iPgidx += fts5GetVarint32(&a[iPgidx], iTermOff);
  1992   1984     iOff = iTermOff;
  1993   1985   
  1994   1986     while( 1 ){
  1995   1987   
  1996   1988       /* Figure out how many new bytes are in this term */
  1997         -    fts5IndexGetVarint32(a, iOff, nNew);
         1989  +    fts5FastGetVarint32(a, iOff, nNew);
  1998   1990       if( nKeep<nMatch ){
  1999   1991         goto search_failed;
  2000   1992       }
  2001   1993   
  2002   1994       assert( nKeep>=nMatch );
  2003   1995       if( nKeep==nMatch ){
  2004   1996         int nCmp;
................................................................................
  2026   2018       }
  2027   2019   
  2028   2020       iPgidx += fts5GetVarint32(&a[iPgidx], nKeep);
  2029   2021       iTermOff += nKeep;
  2030   2022       iOff = iTermOff;
  2031   2023   
  2032   2024       /* Read the nKeep field of the next term. */
  2033         -    fts5IndexGetVarint32(a, iOff, nKeep);
         2025  +    fts5FastGetVarint32(a, iOff, nKeep);
  2034   2026     }
  2035   2027   
  2036   2028    search_failed:
  2037   2029     if( bGe==0 ){
  2038   2030       fts5DataRelease(pIter->pLeaf);
  2039   2031       pIter->pLeaf = 0;
  2040   2032       return;
................................................................................
  3701   3693         if( (ret + i) > nMax ) break;
  3702   3694         ret += i;
  3703   3695       }
  3704   3696     }
  3705   3697     return ret;
  3706   3698   }
  3707   3699   
  3708         -#define fts5BufferSafeAppendBlob(pBuf, pBlob, nBlob) { \
  3709         -  assert( pBuf->nSpace>=(pBuf->n+nBlob) );             \
  3710         -  memcpy(&pBuf->p[pBuf->n], pBlob, nBlob);             \
  3711         -  pBuf->n += nBlob;                                    \
         3700  +#define fts5BufferSafeAppendBlob(pBuf, pBlob, nBlob) {     \
         3701  +  assert( (pBuf)->nSpace>=((pBuf)->n+nBlob) );             \
         3702  +  memcpy(&(pBuf)->p[(pBuf)->n], pBlob, nBlob);             \
         3703  +  (pBuf)->n += nBlob;                                      \
         3704  +}
         3705  +
         3706  +#define fts5BufferSafeAppendVarint(pBuf, iVal) {                \
         3707  +  (pBuf)->n += sqlite3Fts5PutVarint(&(pBuf)->p[(pBuf)->n], (iVal));  \
         3708  +  assert( (pBuf)->nSpace>=(pBuf)->n );                          \
  3712   3709   }
  3713   3710   
  3714   3711   /*
  3715   3712   ** Flush the contents of in-memory hash table iHash to a new level-0 
  3716   3713   ** segment on disk. Also update the corresponding structure record.
  3717   3714   **
  3718   3715   ** If an error occurs, set the Fts5Index.rc error code. If an error has 
................................................................................
  3934   3931     fts5StructureRelease(pStruct);
  3935   3932   
  3936   3933     return fts5IndexReturn(p);
  3937   3934   }
  3938   3935   
  3939   3936   static void fts5PoslistCallback(
  3940   3937     Fts5Index *p, 
  3941         -  void *pCtx, 
         3938  +  void *pContext, 
         3939  +  const u8 *pChunk, int nChunk
         3940  +){
         3941  +  assert_nc( nChunk>=0 );
         3942  +  if( nChunk>0 ){
         3943  +    fts5BufferAppendBlob(&p->rc, (Fts5Buffer*)pContext, nChunk, pChunk);
         3944  +  }
         3945  +}
         3946  +
         3947  +typedef struct PoslistCallbackCtx PoslistCallbackCtx;
         3948  +struct PoslistCallbackCtx {
         3949  +  Fts5Buffer *pBuf;               /* Append to this buffer */
         3950  +  Fts5Colset *pColset;            /* Restrict matches to this column */
         3951  +  int eState;                     /* See above */
         3952  +};
         3953  +
         3954  +/*
         3955  +** TODO: Make this more efficient!
         3956  +*/
         3957  +static int fts5IndexColsetTest(Fts5Colset *pColset, int iCol){
         3958  +  int i;
         3959  +  for(i=0; i<pColset->nCol; i++){
         3960  +    if( pColset->aiCol[i]==iCol ) return 1;
         3961  +  }
         3962  +  return 0;
         3963  +}
         3964  +
         3965  +static void fts5PoslistFilterCallback(
         3966  +  Fts5Index *p, 
         3967  +  void *pContext, 
  3942   3968     const u8 *pChunk, int nChunk
  3943   3969   ){
         3970  +  PoslistCallbackCtx *pCtx = (PoslistCallbackCtx*)pContext;
  3944   3971     assert_nc( nChunk>=0 );
  3945   3972     if( nChunk>0 ){
  3946         -    fts5BufferAppendBlob(&p->rc, (Fts5Buffer*)pCtx, nChunk, pChunk);
         3973  +    /* Search through to find the first varint with value 1. This is the
         3974  +    ** start of the next columns hits. */
         3975  +    int i = 0;
         3976  +    int iStart = 0;
         3977  +
         3978  +    if( pCtx->eState==2 ){
         3979  +      int iCol;
         3980  +      fts5FastGetVarint32(pChunk, i, iCol);
         3981  +      if( fts5IndexColsetTest(pCtx->pColset, iCol) ){
         3982  +        pCtx->eState = 1;
         3983  +        fts5BufferAppendVarint(&p->rc, pCtx->pBuf, 1);
         3984  +      }else{
         3985  +        pCtx->eState = 0;
         3986  +      }
         3987  +    }
         3988  +
         3989  +    do {
         3990  +      while( i<nChunk && pChunk[i]!=0x01 ){
         3991  +        while( pChunk[i] & 0x80 ) i++;
         3992  +        i++;
         3993  +      }
         3994  +      if( pCtx->eState ){
         3995  +        fts5BufferAppendBlob(&p->rc, pCtx->pBuf, i-iStart, &pChunk[iStart]);
         3996  +      }
         3997  +      if( i<nChunk ){
         3998  +        int iCol;
         3999  +        iStart = i;
         4000  +        i++;
         4001  +        if( i>=nChunk ){
         4002  +          pCtx->eState = 2;
         4003  +        }else{
         4004  +          fts5FastGetVarint32(pChunk, i, iCol);
         4005  +          pCtx->eState = fts5IndexColsetTest(pCtx->pColset, iCol);
         4006  +          if( pCtx->eState ){
         4007  +            fts5BufferAppendBlob(&p->rc, pCtx->pBuf, i-iStart, &pChunk[iStart]);
         4008  +            iStart = i;
         4009  +          }
         4010  +        }
         4011  +      }
         4012  +    }while( i<nChunk );
  3947   4013     }
  3948   4014   }
  3949   4015   
  3950   4016   /*
  3951   4017   ** Iterator pIter currently points to a valid entry (not EOF). This
  3952   4018   ** function appends the position list data for the current entry to
  3953   4019   ** buffer pBuf. It does not make a copy of the position-list size
  3954   4020   ** field.
  3955   4021   */
  3956   4022   static void fts5SegiterPoslist(
  3957   4023     Fts5Index *p,
  3958   4024     Fts5SegIter *pSeg,
         4025  +  Fts5Colset *pColset,
  3959   4026     Fts5Buffer *pBuf
  3960   4027   ){
  3961         -  fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
         4028  +  if( pColset==0 ){
         4029  +    fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
         4030  +  }else{
         4031  +    PoslistCallbackCtx sCtx;
         4032  +    sCtx.pBuf = pBuf;
         4033  +    sCtx.pColset = pColset;
         4034  +    sCtx.eState = pColset ? fts5IndexColsetTest(pColset, 0) : 1;
         4035  +    assert( sCtx.eState==0 || sCtx.eState==1 );
         4036  +    fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback);
         4037  +  }
  3962   4038   }
  3963   4039   
  3964   4040   /*
  3965   4041   ** Iterator pMulti currently points to a valid entry (not EOF). This
  3966   4042   ** function appends a copy of the position-list of the entry pMulti 
  3967   4043   ** currently points to to buffer pBuf.
  3968   4044   **
  3969   4045   ** If an error occurs, an error code is left in p->rc. It is assumed
  3970   4046   ** no error has already occurred when this function is called.
  3971   4047   */
  3972         -static void fts5MultiIterPoslist(
         4048  +static int fts5MultiIterPoslist(
  3973   4049     Fts5Index *p,
  3974   4050     Fts5IndexIter *pMulti,
  3975         -  int bSz,                        /* Append a size field before the data */
         4051  +  Fts5Colset *pColset,
  3976   4052     Fts5Buffer *pBuf
  3977   4053   ){
  3978   4054     if( p->rc==SQLITE_OK ){
         4055  +    int iSz;
         4056  +    int iData;
         4057  +
  3979   4058       Fts5SegIter *pSeg = &pMulti->aSeg[ pMulti->aFirst[1].iFirst ];
  3980   4059       assert( fts5MultiIterEof(p, pMulti)==0 );
  3981   4060   
  3982         -    if( bSz ){
  3983         -      /* WRITEPOSLISTSIZE */
  3984         -      fts5BufferAppendVarint(&p->rc, pBuf, pSeg->nPos*2);
         4061  +    /* WRITEPOSLISTSIZE */
         4062  +    iSz = pBuf->n;
         4063  +    fts5BufferSafeAppendVarint(pBuf, pSeg->nPos*2);
         4064  +    iData = pBuf->n;
         4065  +
         4066  +    fts5SegiterPoslist(p, pSeg, pColset, pBuf);
         4067  +
         4068  +    if( pColset ){
         4069  +      int nActual = pBuf->n - iData;
         4070  +      if( nActual!=pSeg->nPos ){
         4071  +        /* WRITEPOSLISTSIZE */
         4072  +        if( nActual==0 ){
         4073  +          return 1;
         4074  +        }else{
         4075  +          int nReq = sqlite3Fts5GetVarintLen((u32)(nActual*2));
         4076  +          while( iSz<(iData-nReq) ){ pBuf->p[iSz++] = 0x80; }
         4077  +          sqlite3Fts5PutVarint(&pBuf->p[iSz], nActual*2);
         4078  +        }
         4079  +      }
  3985   4080       }
  3986         -    fts5SegiterPoslist(p, pSeg, pBuf);
  3987   4081     }
         4082  +
         4083  +  return 0;
  3988   4084   }
  3989   4085   
  3990   4086   static void fts5DoclistIterNext(Fts5DoclistIter *pIter){
  3991         -  if( pIter->i<pIter->n ){
  3992         -    int bDummy;
  3993         -    if( pIter->i ){
  3994         -      i64 iDelta;
  3995         -      pIter->i += fts5GetVarint(&pIter->a[pIter->i], (u64*)&iDelta);
  3996         -      pIter->iRowid += iDelta;
         4087  +  u8 *p = pIter->aPoslist + pIter->nSize + pIter->nPoslist;
         4088  +
         4089  +  assert( pIter->aPoslist );
         4090  +  if( p>=pIter->aEof ){
         4091  +    pIter->aPoslist = 0;
         4092  +  }else{
         4093  +    i64 iDelta;
         4094  +
         4095  +    p += fts5GetVarint(p, (u64*)&iDelta);
         4096  +    pIter->iRowid += iDelta;
         4097  +
         4098  +    /* Read position list size */
         4099  +    if( p[0] & 0x80 ){
         4100  +      int nPos;
         4101  +      pIter->nSize = fts5GetVarint32(p, nPos);
         4102  +      pIter->nPoslist = (nPos>>1);
  3997   4103       }else{
  3998         -      pIter->i += fts5GetVarint(&pIter->a[pIter->i], (u64*)&pIter->iRowid);
         4104  +      pIter->nPoslist = ((int)(p[0])) >> 1;
         4105  +      pIter->nSize = 1;
  3999   4106       }
  4000         -    pIter->i += fts5GetPoslistSize(
  4001         -        &pIter->a[pIter->i], &pIter->nPoslist, &bDummy
  4002         -    );
  4003         -    pIter->aPoslist = &pIter->a[pIter->i];
  4004         -    pIter->i += pIter->nPoslist;
  4005         -  }else{
  4006         -    pIter->aPoslist = 0;
         4107  +
         4108  +    pIter->aPoslist = p;
  4007   4109     }
  4008   4110   }
  4009   4111   
  4010   4112   static void fts5DoclistIterInit(
  4011   4113     Fts5Buffer *pBuf, 
  4012   4114     Fts5DoclistIter *pIter
  4013   4115   ){
  4014   4116     memset(pIter, 0, sizeof(*pIter));
  4015         -  pIter->a = pBuf->p;
  4016         -  pIter->n = pBuf->n;
         4117  +  pIter->aPoslist = pBuf->p;
         4118  +  pIter->aEof = &pBuf->p[pBuf->n];
  4017   4119     fts5DoclistIterNext(pIter);
  4018   4120   }
  4019   4121   
         4122  +#if 0
  4020   4123   /*
  4021   4124   ** Append a doclist to buffer pBuf.
         4125  +**
         4126  +** This function assumes that space within the buffer has already been
         4127  +** allocated.
  4022   4128   */
  4023   4129   static void fts5MergeAppendDocid(
  4024         -  int *pRc,                       /* IN/OUT: Error code */
  4025   4130     Fts5Buffer *pBuf,               /* Buffer to write to */
  4026   4131     i64 *piLastRowid,               /* IN/OUT: Previous rowid written (if any) */
  4027   4132     i64 iRowid                      /* Rowid to append */
  4028   4133   ){
  4029         -  if( pBuf->n==0 ){
  4030         -    fts5BufferAppendVarint(pRc, pBuf, iRowid);
  4031         -  }else{
  4032         -    fts5BufferAppendVarint(pRc, pBuf, iRowid - *piLastRowid);
  4033         -  }
         4134  +  assert( pBuf->n!=0 || (*piLastRowid)==0 );
         4135  +  fts5BufferSafeAppendVarint(pBuf, iRowid - *piLastRowid);
  4034   4136     *piLastRowid = iRowid;
  4035   4137   }
         4138  +#endif
         4139  +
         4140  +#define fts5MergeAppendDocid(pBuf, iLastRowid, iRowid) {       \
         4141  +  assert( (pBuf)->n!=0 || (iLastRowid)==0 );                   \
         4142  +  fts5BufferSafeAppendVarint((pBuf), (iRowid) - (iLastRowid)); \
         4143  +  (iLastRowid) = (iRowid);                                     \
         4144  +}
  4036   4145   
  4037   4146   /*
  4038   4147   ** Buffers p1 and p2 contain doclists. This function merges the content
  4039   4148   ** of the two doclists together and sets buffer p1 to the result before
  4040   4149   ** returning.
  4041   4150   **
  4042   4151   ** If an error occurs, an error code is left in p->rc. If an error has
................................................................................
  4052   4161       Fts5DoclistIter i1;
  4053   4162       Fts5DoclistIter i2;
  4054   4163       Fts5Buffer out;
  4055   4164       Fts5Buffer tmp;
  4056   4165       memset(&out, 0, sizeof(out));
  4057   4166       memset(&tmp, 0, sizeof(tmp));
  4058   4167   
         4168  +    sqlite3Fts5BufferGrow(&p->rc, &out, p1->n + p2->n);
  4059   4169       fts5DoclistIterInit(p1, &i1);
  4060   4170       fts5DoclistIterInit(p2, &i2);
  4061   4171       while( p->rc==SQLITE_OK && (i1.aPoslist!=0 || i2.aPoslist!=0) ){
  4062   4172         if( i2.aPoslist==0 || (i1.aPoslist && i1.iRowid<i2.iRowid) ){
  4063   4173           /* Copy entry from i1 */
  4064         -        fts5MergeAppendDocid(&p->rc, &out, &iLastRowid, i1.iRowid);
  4065         -        /* WRITEPOSLISTSIZE */
  4066         -        fts5BufferAppendVarint(&p->rc, &out, i1.nPoslist * 2);
  4067         -        fts5BufferAppendBlob(&p->rc, &out, i1.nPoslist, i1.aPoslist);
         4174  +        fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid);
         4175  +        fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.nPoslist+i1.nSize);
  4068   4176           fts5DoclistIterNext(&i1);
  4069   4177         }
  4070   4178         else if( i1.aPoslist==0 || i2.iRowid!=i1.iRowid ){
  4071   4179           /* Copy entry from i2 */
  4072         -        fts5MergeAppendDocid(&p->rc, &out, &iLastRowid, i2.iRowid);
  4073         -        /* WRITEPOSLISTSIZE */
  4074         -        fts5BufferAppendVarint(&p->rc, &out, i2.nPoslist * 2);
  4075         -        fts5BufferAppendBlob(&p->rc, &out, i2.nPoslist, i2.aPoslist);
         4180  +        fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
         4181  +        fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.nPoslist+i2.nSize);
  4076   4182           fts5DoclistIterNext(&i2);
  4077   4183         }
  4078   4184         else{
  4079         -        Fts5PoslistReader r1;
  4080         -        Fts5PoslistReader r2;
         4185  +        i64 iPos1 = 0;
         4186  +        i64 iPos2 = 0;
         4187  +        int iOff1 = 0;
         4188  +        int iOff2 = 0;
         4189  +        u8 *a1 = &i1.aPoslist[i1.nSize];
         4190  +        u8 *a2 = &i2.aPoslist[i2.nSize];
         4191  +
  4081   4192           Fts5PoslistWriter writer;
  4082         -
  4083   4193           memset(&writer, 0, sizeof(writer));
  4084   4194   
  4085   4195           /* Merge the two position lists. */ 
  4086         -        fts5MergeAppendDocid(&p->rc, &out, &iLastRowid, i2.iRowid);
         4196  +        fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
  4087   4197           fts5BufferZero(&tmp);
  4088         -        sqlite3Fts5PoslistReaderInit(-1, i1.aPoslist, i1.nPoslist, &r1);
  4089         -        sqlite3Fts5PoslistReaderInit(-1, i2.aPoslist, i2.nPoslist, &r2);
  4090         -        while( p->rc==SQLITE_OK && (r1.bEof==0 || r2.bEof==0) ){
         4198  +
         4199  +        sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
         4200  +        sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
         4201  +
         4202  +        while( p->rc==SQLITE_OK && (iPos1>=0 || iPos2>=0) ){
  4091   4203             i64 iNew;
  4092         -          if( r2.bEof || (r1.bEof==0 && r1.iPos<r2.iPos) ){
  4093         -            iNew = r1.iPos;
  4094         -            sqlite3Fts5PoslistReaderNext(&r1);
         4204  +          if( iPos2<0 || (iPos1>=0 && iPos1<iPos2) ){
         4205  +            iNew = iPos1;
         4206  +            sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
  4095   4207             }else{
  4096         -            iNew = r2.iPos;
  4097         -            sqlite3Fts5PoslistReaderNext(&r2);
  4098         -            if( r1.iPos==r2.iPos ) sqlite3Fts5PoslistReaderNext(&r1);
         4208  +            iNew = iPos2;
         4209  +            sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
         4210  +            if( iPos1==iPos2 ){
         4211  +              sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1,&iPos1);
         4212  +            }
  4099   4213             }
  4100   4214             p->rc = sqlite3Fts5PoslistWriterAppend(&tmp, &writer, iNew);
  4101   4215           }
  4102   4216   
  4103   4217           /* WRITEPOSLISTSIZE */
  4104         -        fts5BufferAppendVarint(&p->rc, &out, tmp.n * 2);
  4105         -        fts5BufferAppendBlob(&p->rc, &out, tmp.n, tmp.p);
         4218  +        fts5BufferSafeAppendVarint(&out, tmp.n * 2);
         4219  +        fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
  4106   4220           fts5DoclistIterNext(&i1);
  4107   4221           fts5DoclistIterNext(&i2);
  4108   4222         }
  4109   4223       }
  4110   4224   
  4111   4225       fts5BufferSet(&p->rc, p1, out.n, out.p);
  4112   4226       fts5BufferFree(&tmp);
................................................................................
  4121   4235   }
  4122   4236   
  4123   4237   static void fts5SetupPrefixIter(
  4124   4238     Fts5Index *p,                   /* Index to read from */
  4125   4239     int bDesc,                      /* True for "ORDER BY rowid DESC" */
  4126   4240     const u8 *pToken,               /* Buffer containing prefix to match */
  4127   4241     int nToken,                     /* Size of buffer pToken in bytes */
  4128         -  Fts5IndexIter **ppIter       /* OUT: New iterator */
         4242  +  Fts5Colset *pColset,            /* Restrict matches to these columns */
         4243  +  Fts5IndexIter **ppIter          /* OUT: New iterator */
  4129   4244   ){
  4130   4245     Fts5Structure *pStruct;
  4131   4246     Fts5Buffer *aBuf;
  4132   4247     const int nBuf = 32;
  4133   4248   
  4134   4249     aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*nBuf);
  4135   4250     pStruct = fts5StructureRead(p);
................................................................................
  4160   4275               fts5BufferSwap(&doclist, &aBuf[i]);
  4161   4276               fts5BufferZero(&doclist);
  4162   4277             }else{
  4163   4278               fts5MergePrefixLists(p, &doclist, &aBuf[i]);
  4164   4279               fts5BufferZero(&aBuf[i]);
  4165   4280             }
  4166   4281           }
         4282  +        iLastRowid = 0;
  4167   4283         }
  4168   4284   
  4169         -      fts5MergeAppendDocid(&p->rc, &doclist, &iLastRowid, iRowid);
  4170         -      fts5MultiIterPoslist(p, p1, 1, &doclist);
         4285  +      if( 0==sqlite3Fts5BufferGrow(&p->rc, &doclist, 9) ){
         4286  +        int iSave = doclist.n;
         4287  +        assert( doclist.n!=0 || iLastRowid==0 );
         4288  +        fts5BufferSafeAppendVarint(&doclist, iRowid - iLastRowid);
         4289  +        if( fts5MultiIterPoslist(p, p1, pColset, &doclist) ){
         4290  +          doclist.n = iSave;
         4291  +        }else{
         4292  +          iLastRowid = iRowid;
         4293  +        }
         4294  +      }
  4171   4295       }
  4172   4296   
  4173   4297       for(i=0; i<nBuf; i++){
  4174         -      fts5MergePrefixLists(p, &doclist, &aBuf[i]);
         4298  +      if( p->rc==SQLITE_OK ){
         4299  +        fts5MergePrefixLists(p, &doclist, &aBuf[i]);
         4300  +      }
  4175   4301         fts5BufferFree(&aBuf[i]);
  4176   4302       }
  4177   4303       fts5MultiIterFree(p, p1);
  4178   4304   
  4179   4305       pData = fts5IdxMalloc(p, sizeof(Fts5Data) + doclist.n);
  4180   4306       if( pData ){
  4181   4307         pData->p = (u8*)&pData[1];
................................................................................
  4191   4317   }
  4192   4318   
  4193   4319   
  4194   4320   /*
  4195   4321   ** Indicate that all subsequent calls to sqlite3Fts5IndexWrite() pertain
  4196   4322   ** to the document with rowid iRowid.
  4197   4323   */
  4198         -int sqlite3Fts5IndexBeginWrite(Fts5Index *p, i64 iRowid){
         4324  +int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){
  4199   4325     assert( p->rc==SQLITE_OK );
  4200   4326   
  4201   4327     /* Allocate the hash table if it has not already been allocated */
  4202   4328     if( p->pHash==0 ){
  4203   4329       p->rc = sqlite3Fts5HashNew(&p->pHash, &p->nPendingData);
  4204   4330     }
  4205   4331   
  4206   4332     /* Flush the hash table to disk if required */
  4207         -  if( iRowid<=p->iWriteRowid || (p->nPendingData > p->nMaxPendingData) ){
         4333  +  if( iRowid<p->iWriteRowid 
         4334  +   || (iRowid==p->iWriteRowid && p->bDelete==0)
         4335  +   || (p->nPendingData > p->nMaxPendingData) 
         4336  +  ){
  4208   4337       fts5IndexFlush(p);
  4209   4338     }
         4339  +
  4210   4340     p->iWriteRowid = iRowid;
         4341  +  p->bDelete = bDelete;
  4211   4342     return fts5IndexReturn(p);
  4212   4343   }
  4213   4344   
  4214   4345   /*
  4215   4346   ** Commit data to disk.
  4216   4347   */
  4217   4348   int sqlite3Fts5IndexSync(Fts5Index *p, int bCommit){
................................................................................
  4302   4433       assert( p->pReader==0 );
  4303   4434       sqlite3_finalize(p->pWriter);
  4304   4435       sqlite3_finalize(p->pDeleter);
  4305   4436       sqlite3_finalize(p->pIdxWriter);
  4306   4437       sqlite3_finalize(p->pIdxDeleter);
  4307   4438       sqlite3_finalize(p->pIdxSelect);
  4308   4439       sqlite3Fts5HashFree(p->pHash);
  4309         -    sqlite3Fts5BufferFree(&p->scratch);
  4310   4440       sqlite3_free(p->zDataTbl);
  4311   4441       sqlite3_free(p);
  4312   4442     }
  4313   4443     return rc;
  4314   4444   }
  4315   4445   
  4316   4446   /*
................................................................................
  4363   4493     const char *pToken, int nToken  /* Token to add or remove to or from index */
  4364   4494   ){
  4365   4495     int i;                          /* Used to iterate through indexes */
  4366   4496     int rc = SQLITE_OK;             /* Return code */
  4367   4497     Fts5Config *pConfig = p->pConfig;
  4368   4498   
  4369   4499     assert( p->rc==SQLITE_OK );
         4500  +  assert( (iCol<0)==p->bDelete );
  4370   4501   
  4371   4502     /* Add the entry to the main terms index. */
  4372   4503     rc = sqlite3Fts5HashWrite(
  4373   4504         p->pHash, p->iWriteRowid, iCol, iPos, FTS5_MAIN_PREFIX, pToken, nToken
  4374   4505     );
  4375   4506   
  4376   4507     for(i=0; i<pConfig->nPrefix && rc==SQLITE_OK; i++){
................................................................................
  4389   4520   ** Open a new iterator to iterate though all rowid that match the 
  4390   4521   ** specified token or token prefix.
  4391   4522   */
  4392   4523   int sqlite3Fts5IndexQuery(
  4393   4524     Fts5Index *p,                   /* FTS index to query */
  4394   4525     const char *pToken, int nToken, /* Token (or prefix) to query for */
  4395   4526     int flags,                      /* Mask of FTS5INDEX_QUERY_X flags */
         4527  +  Fts5Colset *pColset,            /* Match these columns only */
  4396   4528     Fts5IndexIter **ppIter          /* OUT: New iterator object */
  4397   4529   ){
  4398   4530     Fts5Config *pConfig = p->pConfig;
  4399   4531     Fts5IndexIter *pRet = 0;
  4400   4532     int iIdx = 0;
  4401   4533     Fts5Buffer buf = {0, 0, 0};
  4402   4534   
................................................................................
  4432   4564         if( pStruct ){
  4433   4565           fts5MultiIterNew(p, pStruct, 1, flags, buf.p, nToken+1, -1, 0, &pRet);
  4434   4566           fts5StructureRelease(pStruct);
  4435   4567         }
  4436   4568       }else{
  4437   4569         int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0;
  4438   4570         buf.p[0] = FTS5_MAIN_PREFIX;
  4439         -      fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, &pRet);
         4571  +      fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet);
  4440   4572       }
  4441   4573   
  4442   4574       if( p->rc ){
  4443   4575         sqlite3Fts5IterClose(pRet);
  4444   4576         pRet = 0;
  4445   4577         fts5CloseReader(p);
  4446   4578       }
................................................................................
  4534   4666     assert( pIter->pIndex->rc==SQLITE_OK );
  4535   4667     *piRowid = pSeg->iRowid;
  4536   4668     *pn = pSeg->nPos;
  4537   4669     if( pSeg->iLeafOffset+pSeg->nPos <= pSeg->pLeaf->szLeaf ){
  4538   4670       *pp = &pSeg->pLeaf->p[pSeg->iLeafOffset];
  4539   4671     }else{
  4540   4672       fts5BufferZero(&pIter->poslist);
  4541         -    fts5SegiterPoslist(pIter->pIndex, pSeg, &pIter->poslist);
         4673  +    fts5SegiterPoslist(pIter->pIndex, pSeg, 0, &pIter->poslist);
  4542   4674       *pp = pIter->poslist.p;
  4543   4675     }
  4544   4676     return fts5IndexReturn(pIter->pIndex);
  4545   4677   }
  4546   4678   
  4547   4679   /*
  4548   4680   ** This function is similar to sqlite3Fts5IterPoslist(), except that it
  4549   4681   ** copies the position list into the buffer supplied as the second 
  4550   4682   ** argument.
  4551   4683   */
  4552   4684   int sqlite3Fts5IterPoslistBuffer(Fts5IndexIter *pIter, Fts5Buffer *pBuf){
  4553   4685     Fts5Index *p = pIter->pIndex;
  4554         -
         4686  +  Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
  4555   4687     assert( p->rc==SQLITE_OK );
  4556   4688     fts5BufferZero(pBuf);
  4557         -  fts5MultiIterPoslist(p, pIter, 0, pBuf);
         4689  +  fts5SegiterPoslist(p, pSeg, 0, pBuf);
  4558   4690     return fts5IndexReturn(p);
  4559   4691   }
  4560   4692   
  4561   4693   /*
  4562   4694   ** Close an iterator opened by an earlier call to sqlite3Fts5IndexQuery().
  4563   4695   */
  4564   4696   void sqlite3Fts5IterClose(Fts5IndexIter *pIter){
................................................................................
  4725   4857     const char *z,                  /* Index key to query for */
  4726   4858     int n,                          /* Size of index key in bytes */
  4727   4859     int flags,                      /* Flags for Fts5IndexQuery */
  4728   4860     u64 *pCksum                     /* IN/OUT: Checksum value */
  4729   4861   ){
  4730   4862     u64 cksum = *pCksum;
  4731   4863     Fts5IndexIter *pIdxIter = 0;
  4732         -  int rc = sqlite3Fts5IndexQuery(p, z, n, flags, &pIdxIter);
         4864  +  int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIdxIter);
  4733   4865   
  4734   4866     while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIdxIter) ){
  4735   4867       i64 dummy;
  4736   4868       const u8 *pPos;
  4737   4869       int nPos;
  4738   4870       i64 rowid = sqlite3Fts5IterRowid(pIdxIter);
  4739   4871       rc = sqlite3Fts5IterPoslist(pIdxIter, &pPos, &nPos, &dummy);
................................................................................
  5099   5231       i64 iRowid = fts5MultiIterRowid(pIter);
  5100   5232       char *z = (char*)fts5MultiIterTerm(pIter, &n);
  5101   5233   
  5102   5234       /* If this is a new term, query for it. Update cksum3 with the results. */
  5103   5235       fts5TestTerm(p, &term, z, n, cksum2, &cksum3);
  5104   5236   
  5105   5237       poslist.n = 0;
  5106         -    fts5MultiIterPoslist(p, pIter, 0, &poslist);
         5238  +    fts5SegiterPoslist(p, &pIter->aSeg[pIter->aFirst[1].iFirst] , 0, &poslist);
  5107   5239       while( 0==sqlite3Fts5PoslistNext64(poslist.p, poslist.n, &iOff, &iPos) ){
  5108   5240         int iCol = FTS5_POS2COLUMN(iPos);
  5109   5241         int iTokOff = FTS5_POS2OFFSET(iPos);
  5110   5242         cksum2 ^= fts5IndexEntryCksum(iRowid, iCol, iTokOff, -1, z, n);
  5111   5243       }
  5112   5244     }
  5113   5245     fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3);
................................................................................
  5238   5370       *pRc = rc;
  5239   5371       return;
  5240   5372     }
  5241   5373   
  5242   5374     fts5DebugStructure(pRc, pBuf, p);
  5243   5375     fts5StructureRelease(p);
  5244   5376   }
         5377  +
         5378  +/*
         5379  +** This is part of the fts5_decode() debugging aid.
         5380  +**
         5381  +** Arguments pBlob/nBlob contain an "averages" record. This function 
         5382  +** appends a human-readable representation of record to the buffer passed 
         5383  +** as the second argument. 
         5384  +*/
         5385  +static void fts5DecodeAverages(
         5386  +  int *pRc,                       /* IN/OUT: error code */
         5387  +  Fts5Buffer *pBuf,
         5388  +  const u8 *pBlob, int nBlob
         5389  +){
         5390  +  int i = 0;
         5391  +  const char *zSpace = "";
         5392  +
         5393  +  while( i<nBlob ){
         5394  +    u64 iVal;
         5395  +    i += sqlite3Fts5GetVarint(&pBlob[i], &iVal);
         5396  +    sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "%s%d", zSpace, (int)iVal);
         5397  +    zSpace = " ";
         5398  +  }
         5399  +}
  5245   5400   
  5246   5401   /*
  5247   5402   ** Buffer (a/n) is assumed to contain a list of serialized varints. Read
  5248   5403   ** each varint and append its string representation to buffer pBuf. Return
  5249   5404   ** after either the input buffer is exhausted or a 0 value is read.
  5250   5405   **
  5251   5406   ** The return value is the number of bytes read from the input buffer.
................................................................................
  5340   5495       for(fts5DlidxLvlNext(&lvl); lvl.bEof==0; fts5DlidxLvlNext(&lvl)){
  5341   5496         sqlite3Fts5BufferAppendPrintf(&rc, &s, 
  5342   5497             " %d(%lld)", lvl.iLeafPgno, lvl.iRowid
  5343   5498         );
  5344   5499       }
  5345   5500     }else if( iSegid==0 ){
  5346   5501       if( iRowid==FTS5_AVERAGES_ROWID ){
  5347         -      /* todo */
         5502  +      fts5DecodeAverages(&rc, &s, a, n);
  5348   5503       }else{
  5349   5504         fts5DecodeStructure(&rc, &s, a, n);
  5350   5505       }
  5351   5506     }else{
  5352   5507       Fts5Buffer term;              /* Current term read from page */
  5353   5508       int szLeaf;                   /* Offset of pgidx in a[] */
  5354   5509       int iPgidxOff;
................................................................................
  5357   5512       int iRowidOff = 0;
  5358   5513       int iOff;
  5359   5514       int nDoclist;
  5360   5515   
  5361   5516       memset(&term, 0, sizeof(Fts5Buffer));
  5362   5517   
  5363   5518       if( n<4 ){
  5364         -      sqlite3Fts5BufferSet(&rc, &s, 8, (const u8*)"corrupt");
         5519  +      sqlite3Fts5BufferSet(&rc, &s, 7, (const u8*)"corrupt");
  5365   5520         goto decode_out;
  5366   5521       }else{
  5367   5522         iRowidOff = fts5GetU16(&a[0]);
  5368   5523         iPgidxOff = szLeaf = fts5GetU16(&a[2]);
  5369   5524         if( iPgidxOff<n ){
  5370   5525           fts5GetVarint32(&a[iPgidxOff], iTermOff);
  5371   5526         }

Changes to ext/fts5/fts5_main.c.

   435    435   */
   436    436   #define FTS5_PLAN_MATCH          1       /* (<tbl> MATCH ?) */
   437    437   #define FTS5_PLAN_SOURCE         2       /* A source cursor for SORTED_MATCH */
   438    438   #define FTS5_PLAN_SPECIAL        3       /* An internal query */
   439    439   #define FTS5_PLAN_SORTED_MATCH   4       /* (<tbl> MATCH ? ORDER BY rank) */
   440    440   #define FTS5_PLAN_SCAN           5       /* No usable constraint */
   441    441   #define FTS5_PLAN_ROWID          6       /* (rowid = ?) */
          442  +
          443  +/*
          444  +** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this
          445  +** extension is currently being used by a version of SQLite too old to
          446  +** support index-info flags. In that case this function is a no-op.
          447  +*/
          448  +static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){
          449  +#if SQLITE_VERSION_NUMBER>=3008012
          450  +  if( sqlite3_libversion_number()>=3008012 ){
          451  +    pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE;
          452  +  }
          453  +#endif
          454  +}
   442    455   
   443    456   /*
   444    457   ** Implementation of the xBestIndex method for FTS5 tables. Within the 
   445    458   ** WHERE constraint, it searches for the following:
   446    459   **
   447    460   **   1. A MATCH constraint against the special column.
   448    461   **   2. A MATCH constraint against the "rank" column.
................................................................................
   488    501     struct Constraint {
   489    502       int op;                       /* Mask against sqlite3_index_constraint.op */
   490    503       int fts5op;                   /* FTS5 mask for idxFlags */
   491    504       int iCol;                     /* 0==rowid, 1==tbl, 2==rank */
   492    505       int omit;                     /* True to omit this if found */
   493    506       int iConsIndex;               /* Index in pInfo->aConstraint[] */
   494    507     } aConstraint[] = {
   495         -    {SQLITE_INDEX_CONSTRAINT_MATCH, FTS5_BI_MATCH,    1, 1, -1},
   496         -    {SQLITE_INDEX_CONSTRAINT_MATCH, FTS5_BI_RANK,     2, 1, -1},
          508  +    {SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ, 
          509  +                                    FTS5_BI_MATCH,    1, 1, -1},
          510  +    {SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ, 
          511  +                                    FTS5_BI_RANK,     2, 1, -1},
   497    512       {SQLITE_INDEX_CONSTRAINT_EQ,    FTS5_BI_ROWID_EQ, 0, 0, -1},
   498    513       {SQLITE_INDEX_CONSTRAINT_LT|SQLITE_INDEX_CONSTRAINT_LE, 
   499    514                                       FTS5_BI_ROWID_LE, 0, 0, -1},
   500    515       {SQLITE_INDEX_CONSTRAINT_GT|SQLITE_INDEX_CONSTRAINT_GE, 
   501    516                                       FTS5_BI_ROWID_GE, 0, 0, -1},
   502    517     };
   503    518   
................................................................................
   542    557       }
   543    558     }
   544    559   
   545    560     /* Calculate the estimated cost based on the flags set in idxFlags. */
   546    561     bHasMatch = BitFlagTest(idxFlags, FTS5_BI_MATCH);
   547    562     if( BitFlagTest(idxFlags, FTS5_BI_ROWID_EQ) ){
   548    563       pInfo->estimatedCost = bHasMatch ? 100.0 : 10.0;
          564  +    if( bHasMatch==0 ) fts5SetUniqueFlag(pInfo);
   549    565     }else if( BitFlagAllTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){
   550    566       pInfo->estimatedCost = bHasMatch ? 500.0 : 250000.0;
   551    567     }else if( BitFlagTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){
   552    568       pInfo->estimatedCost = bHasMatch ? 750.0 : 750000.0;
   553    569     }else{
   554    570       pInfo->estimatedCost = bHasMatch ? 1000.0 : 1000000.0;
   555    571     }
................................................................................
  1280   1296   **
  1281   1297   ** The commands implemented by this function are documented in the "Special
  1282   1298   ** INSERT Directives" section of the documentation. It should be updated if
  1283   1299   ** more commands are added to this function.
  1284   1300   */
  1285   1301   static int fts5SpecialInsert(
  1286   1302     Fts5Table *pTab,                /* Fts5 table object */
  1287         -  sqlite3_value *pCmd,            /* Value inserted into special column */
         1303  +  const char *zCmd,               /* Text inserted into table-name column */
  1288   1304     sqlite3_value *pVal             /* Value inserted into rank column */
  1289   1305   ){
  1290   1306     Fts5Config *pConfig = pTab->pConfig;
  1291         -  const char *z = (const char*)sqlite3_value_text(pCmd);
  1292   1307     int rc = SQLITE_OK;
  1293   1308     int bError = 0;
  1294   1309   
  1295         -  if( 0==sqlite3_stricmp("delete-all", z) ){
         1310  +  if( 0==sqlite3_stricmp("delete-all", zCmd) ){
  1296   1311       if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
  1297   1312         fts5SetVtabError(pTab, 
  1298   1313             "'delete-all' may only be used with a "
  1299   1314             "contentless or external content fts5 table"
  1300   1315         );
  1301   1316         rc = SQLITE_ERROR;
  1302   1317       }else{
  1303   1318         rc = sqlite3Fts5StorageDeleteAll(pTab->pStorage);
  1304   1319       }
  1305         -  }else if( 0==sqlite3_stricmp("rebuild", z) ){
         1320  +  }else if( 0==sqlite3_stricmp("rebuild", zCmd) ){
  1306   1321       if( pConfig->eContent==FTS5_CONTENT_NONE ){
  1307   1322         fts5SetVtabError(pTab, 
  1308   1323             "'rebuild' may not be used with a contentless fts5 table"
  1309   1324         );
  1310   1325         rc = SQLITE_ERROR;
  1311   1326       }else{
  1312   1327         rc = sqlite3Fts5StorageRebuild(pTab->pStorage);
  1313   1328       }
  1314         -  }else if( 0==sqlite3_stricmp("optimize", z) ){
         1329  +  }else if( 0==sqlite3_stricmp("optimize", zCmd) ){
  1315   1330       rc = sqlite3Fts5StorageOptimize(pTab->pStorage);
  1316         -  }else if( 0==sqlite3_stricmp("merge", z) ){
         1331  +  }else if( 0==sqlite3_stricmp("merge", zCmd) ){
  1317   1332       int nMerge = sqlite3_value_int(pVal);
  1318   1333       rc = sqlite3Fts5StorageMerge(pTab->pStorage, nMerge);
  1319         -  }else if( 0==sqlite3_stricmp("integrity-check", z) ){
         1334  +  }else if( 0==sqlite3_stricmp("integrity-check", zCmd) ){
  1320   1335       rc = sqlite3Fts5StorageIntegrity(pTab->pStorage);
  1321   1336   #ifdef SQLITE_DEBUG
  1322         -  }else if( 0==sqlite3_stricmp("prefix-index", z) ){
         1337  +  }else if( 0==sqlite3_stricmp("prefix-index", zCmd) ){
  1323   1338       pConfig->bPrefixIndex = sqlite3_value_int(pVal);
  1324   1339   #endif
  1325   1340     }else{
  1326   1341       rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex);
  1327   1342       if( rc==SQLITE_OK ){
  1328         -      rc = sqlite3Fts5ConfigSetValue(pTab->pConfig, z, pVal, &bError);
         1343  +      rc = sqlite3Fts5ConfigSetValue(pTab->pConfig, zCmd, pVal, &bError);
  1329   1344       }
  1330   1345       if( rc==SQLITE_OK ){
  1331   1346         if( bError ){
  1332   1347           rc = SQLITE_ERROR;
  1333   1348         }else{
  1334         -        rc = sqlite3Fts5StorageConfigValue(pTab->pStorage, z, pVal, 0);
         1349  +        rc = sqlite3Fts5StorageConfigValue(pTab->pStorage, zCmd, pVal, 0);
  1335   1350         }
  1336   1351       }
  1337   1352     }
  1338   1353     return rc;
  1339   1354   }
  1340   1355   
  1341   1356   static int fts5SpecialDelete(
................................................................................
  1347   1362     int eType1 = sqlite3_value_type(apVal[1]);
  1348   1363     if( eType1==SQLITE_INTEGER ){
  1349   1364       sqlite3_int64 iDel = sqlite3_value_int64(apVal[1]);
  1350   1365       rc = sqlite3Fts5StorageSpecialDelete(pTab->pStorage, iDel, &apVal[2]);
  1351   1366     }
  1352   1367     return rc;
  1353   1368   }
         1369  +
         1370  +static void fts5StorageInsert(
         1371  +  int *pRc, 
         1372  +  Fts5Table *pTab, 
         1373  +  sqlite3_value **apVal, 
         1374  +  i64 *piRowid
         1375  +){
         1376  +  int rc = *pRc;
         1377  +  if( rc==SQLITE_OK ){
         1378  +    rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, piRowid);
         1379  +  }
         1380  +  if( rc==SQLITE_OK ){
         1381  +    rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *piRowid);
         1382  +  }
         1383  +  *pRc = rc;
         1384  +}
  1354   1385   
  1355   1386   /* 
  1356   1387   ** This function is the implementation of the xUpdate callback used by 
  1357   1388   ** FTS3 virtual tables. It is invoked by SQLite each time a row is to be
  1358   1389   ** inserted, updated or deleted.
         1390  +**
         1391  +** A delete specifies a single argument - the rowid of the row to remove.
         1392  +** 
         1393  +** Update and insert operations pass:
         1394  +**
         1395  +**   1. The "old" rowid, or NULL.
         1396  +**   2. The "new" rowid.
         1397  +**   3. Values for each of the nCol matchable columns.
         1398  +**   4. Values for the two hidden columns (<tablename> and "rank").
  1359   1399   */
  1360   1400   static int fts5UpdateMethod(
  1361   1401     sqlite3_vtab *pVtab,            /* Virtual table handle */
  1362   1402     int nArg,                       /* Size of argument array */
  1363   1403     sqlite3_value **apVal,          /* Array of arguments */
  1364   1404     sqlite_int64 *pRowid            /* OUT: The affected (or effected) rowid */
  1365   1405   ){
  1366   1406     Fts5Table *pTab = (Fts5Table*)pVtab;
  1367   1407     Fts5Config *pConfig = pTab->pConfig;
  1368   1408     int eType0;                     /* value_type() of apVal[0] */
  1369         -  int eConflict;                  /* ON CONFLICT for this DML */
  1370   1409     int rc = SQLITE_OK;             /* Return code */
  1371   1410   
  1372   1411     /* A transaction must be open when this is called. */
  1373   1412     assert( pTab->ts.eState==1 );
  1374   1413   
         1414  +  assert( pVtab->zErrMsg==0 );
         1415  +  assert( nArg==1 || nArg==(2+pConfig->nCol+2) );
         1416  +  assert( nArg==1 
         1417  +      || sqlite3_value_type(apVal[1])==SQLITE_INTEGER 
         1418  +      || sqlite3_value_type(apVal[1])==SQLITE_NULL 
         1419  +  );
  1375   1420     assert( pTab->pConfig->pzErrmsg==0 );
  1376   1421     pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
  1377   1422   
  1378         -  /* A delete specifies a single argument - the rowid of the row to remove.
  1379         -  ** Update and insert operations pass:
  1380         -  **
  1381         -  **   1. The "old" rowid, or NULL.
  1382         -  **   2. The "new" rowid.
  1383         -  **   3. Values for each of the nCol matchable columns.
  1384         -  **   4. Values for the two hidden columns (<tablename> and "rank").
  1385         -  */
         1423  +  /* Put any active cursors into REQUIRE_SEEK state. */
         1424  +  fts5TripCursors(pTab);
  1386   1425   
  1387   1426     eType0 = sqlite3_value_type(apVal[0]);
  1388         -  eConflict = sqlite3_vtab_on_conflict(pConfig->db);
         1427  +  if( eType0==SQLITE_NULL 
         1428  +   && sqlite3_value_type(apVal[2+pConfig->nCol])!=SQLITE_NULL 
         1429  +  ){
         1430  +    /* A "special" INSERT op. These are handled separately. */
         1431  +    const char *z = (const char*)sqlite3_value_text(apVal[2+pConfig->nCol]);
         1432  +    if( pConfig->eContent!=FTS5_CONTENT_NORMAL 
         1433  +      && 0==sqlite3_stricmp("delete", z) 
         1434  +    ){
         1435  +      rc = fts5SpecialDelete(pTab, apVal, pRowid);
         1436  +    }else{
         1437  +      rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]);
         1438  +    }
         1439  +  }else{
         1440  +    /* A regular INSERT, UPDATE or DELETE statement. The trick here is that
         1441  +    ** any conflict on the rowid value must be detected before any 
         1442  +    ** modifications are made to the database file. There are 4 cases:
         1443  +    **
         1444  +    **   1) DELETE
         1445  +    **   2) UPDATE (rowid not modified)
         1446  +    **   3) UPDATE (rowid modified)
         1447  +    **   4) INSERT
         1448  +    **
         1449  +    ** Cases 3 and 4 may violate the rowid constraint.
         1450  +    */
         1451  +    int eConflict = sqlite3_vtab_on_conflict(pConfig->db);
  1389   1452   
  1390         -  assert( eType0==SQLITE_INTEGER || eType0==SQLITE_NULL );
  1391         -  assert( pVtab->zErrMsg==0 );
  1392         -  assert( (nArg==1 && eType0==SQLITE_INTEGER) || nArg==(2+pConfig->nCol+2) );
         1453  +    assert( eType0==SQLITE_INTEGER || eType0==SQLITE_NULL );
         1454  +    assert( nArg!=1 || eType0==SQLITE_INTEGER );
  1393   1455   
  1394         -  fts5TripCursors(pTab);
  1395         -  if( eType0==SQLITE_INTEGER ){
  1396         -    if( fts5IsContentless(pTab) ){
         1456  +    /* Filter out attempts to run UPDATE or DELETE on contentless tables.
         1457  +    ** This is not suported.  */
         1458  +    if( eType0==SQLITE_INTEGER && fts5IsContentless(pTab) ){
  1397   1459         pTab->base.zErrMsg = sqlite3_mprintf(
  1398   1460             "cannot %s contentless fts5 table: %s", 
  1399   1461             (nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName
  1400   1462         );
  1401   1463         rc = SQLITE_ERROR;
  1402         -    }else{
         1464  +    }
         1465  +
         1466  +    /* Case 1: DELETE */
         1467  +    else if( nArg==1 ){
  1403   1468         i64 iDel = sqlite3_value_int64(apVal[0]);  /* Rowid to delete */
  1404   1469         rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel);
  1405   1470       }
  1406         -  }else{
  1407         -    sqlite3_value *pCmd = apVal[2 + pConfig->nCol];
  1408         -    assert( nArg>1 );
  1409         -    if( SQLITE_NULL!=sqlite3_value_type(pCmd) ){
  1410         -      const char *z = (const char*)sqlite3_value_text(pCmd);
  1411         -      if( pConfig->eContent!=FTS5_CONTENT_NORMAL 
  1412         -       && 0==sqlite3_stricmp("delete", z) 
         1471  +
         1472  +    /* Case 2: INSERT */
         1473  +    else if( eType0!=SQLITE_INTEGER ){     
         1474  +      /* If this is a REPLACE, first remove the current entry (if any) */
         1475  +      if( eConflict==SQLITE_REPLACE 
         1476  +       && sqlite3_value_type(apVal[1])==SQLITE_INTEGER 
  1413   1477         ){
  1414         -        rc = fts5SpecialDelete(pTab, apVal, pRowid);
         1478  +        i64 iNew = sqlite3_value_int64(apVal[1]);  /* Rowid to delete */
         1479  +        rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew);
         1480  +      }
         1481  +      fts5StorageInsert(&rc, pTab, apVal, pRowid);
         1482  +    }
         1483  +
         1484  +    /* Case 2: UPDATE */
         1485  +    else{
         1486  +      i64 iOld = sqlite3_value_int64(apVal[0]);  /* Old rowid */
         1487  +      i64 iNew = sqlite3_value_int64(apVal[1]);  /* New rowid */
         1488  +      if( iOld!=iNew ){
         1489  +        if( eConflict==SQLITE_REPLACE ){
         1490  +          rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld);
         1491  +          if( rc==SQLITE_OK ){
         1492  +            rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew);
         1493  +          }
         1494  +          fts5StorageInsert(&rc, pTab, apVal, pRowid);
         1495  +        }else{
         1496  +          rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid);
         1497  +          if( rc==SQLITE_OK ){
         1498  +            rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld);
         1499  +          }
         1500  +          if( rc==SQLITE_OK ){
         1501  +            rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *pRowid);
         1502  +          }
         1503  +        }
  1415   1504         }else{
  1416         -        rc = fts5SpecialInsert(pTab, pCmd, apVal[2 + pConfig->nCol + 1]);
         1505  +        rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld);
         1506  +        fts5StorageInsert(&rc, pTab, apVal, pRowid);
  1417   1507         }
  1418         -      goto update_method_out;
  1419   1508       }
  1420   1509     }
  1421   1510   
  1422         -
  1423         -  if( rc==SQLITE_OK && nArg>1 ){
  1424         -    rc = sqlite3Fts5StorageInsert(pTab->pStorage, apVal, eConflict, pRowid);
  1425         -  }
  1426         -
  1427         - update_method_out:
  1428   1511     pTab->pConfig->pzErrmsg = 0;
  1429   1512     return rc;
  1430   1513   }
  1431   1514   
  1432   1515   /*
  1433   1516   ** Implementation of xSync() method. 
  1434   1517   */
................................................................................
  2306   2389     int nArg,                       /* Number of args */
  2307   2390     sqlite3_value **apVal           /* Function arguments */
  2308   2391   ){
  2309   2392     assert( nArg==0 );
  2310   2393     sqlite3_result_text(pCtx, "--FTS5-SOURCE-ID--", -1, SQLITE_TRANSIENT);
  2311   2394   }
  2312   2395   
  2313         -#ifdef _WIN32
  2314         -__declspec(dllexport)
  2315         -#endif
  2316         -int sqlite3_fts5_init(
  2317         -  sqlite3 *db,
  2318         -  char **pzErrMsg,
  2319         -  const sqlite3_api_routines *pApi
  2320         -){
         2396  +static int fts5Init(sqlite3 *db){
  2321   2397     static const sqlite3_module fts5Mod = {
  2322   2398       /* iVersion      */ 2,
  2323   2399       /* xCreate       */ fts5CreateMethod,
  2324   2400       /* xConnect      */ fts5ConnectMethod,
  2325   2401       /* xBestIndex    */ fts5BestIndexMethod,
  2326   2402       /* xDisconnect   */ fts5DisconnectMethod,
  2327   2403       /* xDestroy      */ fts5DestroyMethod,
................................................................................
  2343   2419       /* xRelease      */ fts5ReleaseMethod,
  2344   2420       /* xRollbackTo   */ fts5RollbackToMethod,
  2345   2421     };
  2346   2422   
  2347   2423     int rc;
  2348   2424     Fts5Global *pGlobal = 0;
  2349   2425   
  2350         -  SQLITE_EXTENSION_INIT2(pApi);
  2351         -
  2352   2426     pGlobal = (Fts5Global*)sqlite3_malloc(sizeof(Fts5Global));
  2353   2427     if( pGlobal==0 ){
  2354   2428       rc = SQLITE_NOMEM;
  2355   2429     }else{
  2356   2430       void *p = (void*)pGlobal;
  2357   2431       memset(pGlobal, 0, sizeof(Fts5Global));
  2358   2432       pGlobal->db = db;
................................................................................
  2376   2450             db, "fts5_source_id", 0, SQLITE_UTF8, p, fts5SourceIdFunc, 0, 0
  2377   2451         );
  2378   2452       }
  2379   2453     }
  2380   2454     return rc;
  2381   2455   }
  2382   2456   
         2457  +/*
         2458  +** The following functions are used to register the module with SQLite. If
         2459  +** this module is being built as part of the SQLite core (SQLITE_CORE is
         2460  +** defined), then sqlite3_open() will call sqlite3Fts5Init() directly.
         2461  +**
         2462  +** Or, if this module is being built as a loadable extension, 
         2463  +** sqlite3Fts5Init() is omitted and the two standard entry points
         2464  +** sqlite3_fts_init() and sqlite3_fts5_init() defined instead.
         2465  +*/
         2466  +#ifndef SQLITE_CORE
  2383   2467   #ifdef _WIN32
  2384   2468   __declspec(dllexport)
  2385   2469   #endif
  2386   2470   int sqlite3_fts_init(
  2387   2471     sqlite3 *db,
  2388   2472     char **pzErrMsg,
  2389   2473     const sqlite3_api_routines *pApi
  2390   2474   ){
  2391         -  return sqlite3_fts5_init(db, pzErrMsg, pApi);
         2475  +  SQLITE_EXTENSION_INIT2(pApi);
         2476  +  (void)pzErrMsg;  /* Unused parameter */
         2477  +  return fts5Init(db);
  2392   2478   }
  2393   2479   
         2480  +#ifdef _WIN32
         2481  +__declspec(dllexport)
         2482  +#endif
         2483  +int sqlite3_fts5_init(
         2484  +  sqlite3 *db,
         2485  +  char **pzErrMsg,
         2486  +  const sqlite3_api_routines *pApi
         2487  +){
         2488  +  SQLITE_EXTENSION_INIT2(pApi);
         2489  +  (void)pzErrMsg;  /* Unused parameter */
         2490  +  return fts5Init(db);
         2491  +}
         2492  +#else
         2493  +int sqlite3Fts5Init(sqlite3 *db){
         2494  +  return fts5Init(db);
         2495  +}
         2496  +#endif
  2394   2497   

Changes to ext/fts5/fts5_storage.c.

   388    388       int rc2;
   389    389       sqlite3_bind_int64(pSeek, 1, iDel);
   390    390       if( sqlite3_step(pSeek)==SQLITE_ROW ){
   391    391         int iCol;
   392    392         Fts5InsertCtx ctx;
   393    393         ctx.pStorage = p;
   394    394         ctx.iCol = -1;
   395         -      rc = sqlite3Fts5IndexBeginWrite(p->pIndex, iDel);
          395  +      rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 1, iDel);
   396    396         for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){
   397    397           if( pConfig->abUnindexed[iCol-1] ) continue;
   398    398           ctx.szCol = 0;
   399    399           rc = sqlite3Fts5Tokenize(pConfig, 
   400    400               FTS5_TOKENIZE_DOCUMENT,
   401    401               (const char*)sqlite3_column_text(pSeek, iCol),
   402    402               sqlite3_column_bytes(pSeek, iCol),
................................................................................
   545    545     /* Delete the index records */
   546    546     if( rc==SQLITE_OK ){
   547    547       int iCol;
   548    548       Fts5InsertCtx ctx;
   549    549       ctx.pStorage = p;
   550    550       ctx.iCol = -1;
   551    551   
   552         -    rc = sqlite3Fts5IndexBeginWrite(p->pIndex, iDel);
          552  +    rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 1, iDel);
   553    553       for(iCol=0; rc==SQLITE_OK && iCol<pConfig->nCol; iCol++){
   554    554         if( pConfig->abUnindexed[iCol] ) continue;
   555    555         ctx.szCol = 0;
   556    556         rc = sqlite3Fts5Tokenize(pConfig, 
   557    557           FTS5_TOKENIZE_DOCUMENT,
   558    558           (const char*)sqlite3_value_text(apVal[iCol]),
   559    559           sqlite3_value_bytes(apVal[iCol]),
................................................................................
   635    635       rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0);
   636    636     }
   637    637   
   638    638     while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pScan) ){
   639    639       i64 iRowid = sqlite3_column_int64(pScan, 0);
   640    640   
   641    641       sqlite3Fts5BufferZero(&buf);
   642         -    rc = sqlite3Fts5IndexBeginWrite(p->pIndex, iRowid);
          642  +    rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 0, iRowid);
   643    643       for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
   644    644         ctx.szCol = 0;
   645    645         if( pConfig->abUnindexed[ctx.iCol]==0 ){
   646    646           rc = sqlite3Fts5Tokenize(pConfig, 
   647    647               FTS5_TOKENIZE_DOCUMENT,
   648    648               (const char*)sqlite3_column_text(pScan, ctx.iCol+1),
   649    649               sqlite3_column_bytes(pScan, ctx.iCol+1),
................................................................................
   701    701         *piRowid = sqlite3_last_insert_rowid(p->pConfig->db);
   702    702       }
   703    703     }
   704    704     return rc;
   705    705   }
   706    706   
   707    707   /*
   708         -** Insert a new row into the FTS table.
          708  +** Insert a new row into the FTS content table.
          709  +*/
          710  +int sqlite3Fts5StorageContentInsert(
          711  +  Fts5Storage *p, 
          712  +  sqlite3_value **apVal, 
          713  +  i64 *piRowid
          714  +){
          715  +  Fts5Config *pConfig = p->pConfig;
          716  +  int rc = SQLITE_OK;
          717  +
          718  +  /* Insert the new row into the %_content table. */
          719  +  if( pConfig->eContent!=FTS5_CONTENT_NORMAL ){
          720  +    if( sqlite3_value_type(apVal[1])==SQLITE_INTEGER ){
          721  +      *piRowid = sqlite3_value_int64(apVal[1]);
          722  +    }else{
          723  +      rc = fts5StorageNewRowid(p, piRowid);
          724  +    }
          725  +  }else{
          726  +    sqlite3_stmt *pInsert = 0;    /* Statement to write %_content table */
          727  +    int i;                        /* Counter variable */
          728  +#if 0
          729  +    if( eConflict==SQLITE_REPLACE ){
          730  +      eStmt = FTS5_STMT_REPLACE_CONTENT;
          731  +      rc = fts5StorageDeleteFromIndex(p, sqlite3_value_int64(apVal[1]));
          732  +    }else{
          733  +      eStmt = FTS5_STMT_INSERT_CONTENT;
          734  +    }
          735  +#endif
          736  +    if( rc==SQLITE_OK ){
          737  +      rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT, &pInsert, 0);
          738  +    }
          739  +    for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
          740  +      rc = sqlite3_bind_value(pInsert, i, apVal[i]);
          741  +    }
          742  +    if( rc==SQLITE_OK ){
          743  +      sqlite3_step(pInsert);
          744  +      rc = sqlite3_reset(pInsert);
          745  +    }
          746  +    *piRowid = sqlite3_last_insert_rowid(pConfig->db);
          747  +  }
          748  +
          749  +  return rc;
          750  +}
          751  +
          752  +/*
          753  +** Insert new entries into the FTS index and %_docsize table.
   709    754   */
   710         -int sqlite3Fts5StorageInsert(
   711         -  Fts5Storage *p,                 /* Storage module to write to */
   712         -  sqlite3_value **apVal,          /* Array of values passed to xUpdate() */
   713         -  int eConflict,                  /* on conflict clause */
   714         -  i64 *piRowid                    /* OUT: rowid of new record */
          755  +int sqlite3Fts5StorageIndexInsert(
          756  +  Fts5Storage *p, 
          757  +  sqlite3_value **apVal, 
          758  +  i64 iRowid
   715    759   ){
   716    760     Fts5Config *pConfig = p->pConfig;
   717    761     int rc = SQLITE_OK;             /* Return code */
   718         -  sqlite3_stmt *pInsert = 0;      /* Statement used to write %_content table */
   719         -  int eStmt = 0;                  /* Type of statement used on %_content */
   720         -  int i;                          /* Counter variable */
   721    762     Fts5InsertCtx ctx;              /* Tokenization callback context object */
   722    763     Fts5Buffer buf;                 /* Buffer used to build up %_docsize blob */
   723    764   
   724    765     memset(&buf, 0, sizeof(Fts5Buffer));
          766  +  ctx.pStorage = p;
   725    767     rc = fts5StorageLoadTotals(p, 1);
   726    768   
   727         -  /* Insert the new row into the %_content table. */
   728    769     if( rc==SQLITE_OK ){
   729         -    if( pConfig->eContent!=FTS5_CONTENT_NORMAL ){
   730         -      if( sqlite3_value_type(apVal[1])==SQLITE_INTEGER ){
   731         -        *piRowid = sqlite3_value_int64(apVal[1]);
   732         -      }else{
   733         -        rc = fts5StorageNewRowid(p, piRowid);
   734         -      }
   735         -    }else{
   736         -      if( eConflict==SQLITE_REPLACE ){
   737         -        eStmt = FTS5_STMT_REPLACE_CONTENT;
   738         -        rc = fts5StorageDeleteFromIndex(p, sqlite3_value_int64(apVal[1]));
   739         -      }else{
   740         -        eStmt = FTS5_STMT_INSERT_CONTENT;
   741         -      }
   742         -      if( rc==SQLITE_OK ){
   743         -        rc = fts5StorageGetStmt(p, eStmt, &pInsert, 0);
   744         -      }
   745         -      for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
   746         -        rc = sqlite3_bind_value(pInsert, i, apVal[i]);
   747         -      }
   748         -      if( rc==SQLITE_OK ){
   749         -        sqlite3_step(pInsert);
   750         -        rc = sqlite3_reset(pInsert);
   751         -      }
   752         -      *piRowid = sqlite3_last_insert_rowid(pConfig->db);
   753         -    }
   754         -  }
   755         -
   756         -  /* Add new entries to the FTS index */
   757         -  if( rc==SQLITE_OK ){
   758         -    rc = sqlite3Fts5IndexBeginWrite(p->pIndex, *piRowid);
   759         -    ctx.pStorage = p;
          770  +    rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 0, iRowid);
   760    771     }
   761    772     for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
   762    773       ctx.szCol = 0;
   763    774       if( pConfig->abUnindexed[ctx.iCol]==0 ){
   764    775         rc = sqlite3Fts5Tokenize(pConfig, 
   765    776             FTS5_TOKENIZE_DOCUMENT,
   766    777             (const char*)sqlite3_value_text(apVal[ctx.iCol+2]),
................................................................................
   772    783       sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol);
   773    784       p->aTotalSize[ctx.iCol] += (i64)ctx.szCol;
   774    785     }
   775    786     p->nTotalRow++;
   776    787   
   777    788     /* Write the %_docsize record */
   778    789     if( rc==SQLITE_OK ){
   779         -    rc = fts5StorageInsertDocsize(p, *piRowid, &buf);
          790  +    rc = fts5StorageInsertDocsize(p, iRowid, &buf);
   780    791     }
   781    792     sqlite3_free(buf.p);
   782    793   
   783    794     /* Write the averages record */
   784    795     if( rc==SQLITE_OK ){
   785    796       rc = fts5StorageSaveTotals(p);
   786    797     }

Changes to ext/fts5/fts5_tcl.c.

   972    972   
   973    973   static int f5tTokenHash(
   974    974     void * clientData,
   975    975     Tcl_Interp *interp,
   976    976     int objc,
   977    977     Tcl_Obj *CONST objv[]
   978    978   ){
   979         -  int bOld = sqlite3_fts5_may_be_corrupt;
   980    979     char *z;
   981    980     int n;
   982    981     unsigned int iVal;
   983    982     int nSlot;
   984    983   
   985    984     if( objc!=3 ){
   986    985       Tcl_WrongNumArgs(interp, 1, objv, "NSLOT TOKEN");

Changes to ext/fts5/fts5_vocab.c.

   398    398     sqlite3_value **apVal           /* Arguments for the indexing scheme */
   399    399   ){
   400    400     Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
   401    401     int rc;
   402    402     const int flags = FTS5INDEX_QUERY_SCAN;
   403    403   
   404    404     fts5VocabResetCursor(pCsr);
   405         -  rc = sqlite3Fts5IndexQuery(pCsr->pIndex, 0, 0, flags, &pCsr->pIter);
          405  +  rc = sqlite3Fts5IndexQuery(pCsr->pIndex, 0, 0, flags, 0, &pCsr->pIter);
   406    406     if( rc==SQLITE_OK ){
   407    407       rc = fts5VocabNextMethod(pCursor);
   408    408     }
   409    409   
   410    410     return rc;
   411    411   }
   412    412   

Changes to ext/fts5/fts5parse.y.

    63     63   %left OR.
    64     64   %left AND.
    65     65   %left NOT.
    66     66   %left TERM.
    67     67   %left COLON.
    68     68   
    69     69   input ::= expr(X). { sqlite3Fts5ParseFinished(pParse, X); }
           70  +%destructor input { (void)pParse; }
    70     71   
    71     72   %type cnearset    {Fts5ExprNode*}
    72     73   %type expr        {Fts5ExprNode*}
    73     74   %type exprlist    {Fts5ExprNode*}
    74     75   %destructor cnearset { sqlite3Fts5ParseNodeFree($$); }
    75     76   %destructor expr     { sqlite3Fts5ParseNodeFree($$); }
    76     77   %destructor exprlist { sqlite3Fts5ParseNodeFree($$); }
................................................................................
    97     98     A = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, X); 
    98     99   }
    99    100   cnearset(A) ::= colset(X) COLON nearset(Y). { 
   100    101     sqlite3Fts5ParseSetColset(pParse, Y, X);
   101    102     A = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, Y); 
   102    103   }
   103    104   
   104         -%type colset {Fts5ExprColset*}
          105  +%type colset {Fts5Colset*}
   105    106   %destructor colset { sqlite3_free($$); }
   106         -%type colsetlist {Fts5ExprColset*}
          107  +%type colsetlist {Fts5Colset*}
   107    108   %destructor colsetlist { sqlite3_free($$); }
   108    109   
   109    110   colset(A) ::= LCP colsetlist(X) RCP. { A = X; }
   110    111   colset(A) ::= STRING(X). {
   111    112     A = sqlite3Fts5ParseColset(pParse, 0, &X);
   112    113   }
   113    114   

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

    13     13   if {![info exists testdir]} {
    14     14     set testdir [file join [file dirname [info script]] .. .. .. test]
    15     15   }
    16     16   source $testdir/tester.tcl
    17     17   
    18     18   catch { 
    19     19     sqlite3_fts5_may_be_corrupt 0 
    20         -  append G(perm:dbconfig) "; load_static_extension \$::dbhandle fts5"
    21     20     reset_db
    22     21   }
    23     22   
    24     23   proc fts5_test_poslist {cmd} {
    25     24     set res [list]
    26     25     for {set i 0} {$i < [$cmd xInstCount]} {incr i} {
    27     26       lappend res [string map {{ } .} [$cmd xInst $i]]

Changes to ext/fts5/test/fts5al.test.

   247    247     INSERT INTO t3 VALUES('a one');
   248    248     INSERT INTO t3 VALUES('a two');
   249    249     INSERT INTO t3 VALUES('a three');
   250    250     INSERT INTO t3 VALUES('a four');
   251    251     INSERT INTO t3 VALUES('a five');
   252    252     INSERT INTO t3(t3, rank) VALUES('rank', 'bm25()');
   253    253   }
   254         -breakpoint
   255    254   
   256    255   do_execsql_test 4.3.2 {
   257    256     SELECT * FROM t3
   258    257     WHERE t3 MATCH 'a' AND rank MATCH 'rowidmod(4)' 
   259    258     ORDER BY rank ASC
   260    259   } {
   261    260     {a four} {a one} {a five} {a two} {a three}
   262    261   }
          262  +
   263    263   do_execsql_test 4.3.3 {
   264    264     SELECT *, rank FROM t3
   265    265     WHERE t3 MATCH 'a' AND rank MATCH 'rowidmod(3)' 
   266    266     ORDER BY rank ASC
   267    267   } {
   268    268     {a three} 0 {a one} 1 {a four} 1 {a two} 2 {a five} 2 
   269    269   }
          270  +
          271  +do_execsql_test 4.3.4 {
          272  +  SELECT * FROM t3('a', 'rowidmod(4)') ORDER BY rank ASC;
          273  +} {
          274  +  {a four} {a one} {a five} {a two} {a three}
          275  +}
          276  +
          277  +do_execsql_test 4.3.5 {
          278  +  SELECT *, rank FROM t3('a', 'rowidmod(3)') ORDER BY rank ASC
          279  +} {
          280  +  {a three} 0 {a one} 1 {a four} 1 {a two} 2 {a five} 2 
          281  +}
   270    282   
   271    283   do_catchsql_test 4.4.3 {
   272    284     SELECT *, rank FROM t3 WHERE t3 MATCH 'a' AND rank MATCH 'xyz(3)' 
   273    285   } {1 {no such function: xyz}}
   274    286   do_catchsql_test 4.4.4 {
   275    287     SELECT *, rank FROM t3 WHERE t3 MATCH 'a' AND rank MATCH NULL
   276    288   } {1 {parse error in rank function: }}
   277    289   
   278    290   
   279    291   
   280    292   finish_test
   281    293   

Changes to ext/fts5/test/fts5fault6.test.

   280    280   
   281    281   #-------------------------------------------------------------------------
   282    282   catch { db close }
   283    283   breakpoint
   284    284   do_faultsim_test 6 -faults oom* -prep {
   285    285     sqlite_orig db test.db
   286    286     sqlite3_db_config_lookaside db 0 0 0
   287         -} -body {
   288         -  load_static_extension db fts5
   289    287   } -test {
   290    288     faultsim_test_result {0 {}} {1 {initialization of fts5 failed: }}
   291    289     if {$testrc==0} {
   292    290       db eval { CREATE VIRTUAL TABLE temp.t1 USING fts5(x) }
   293    291     }
   294    292     db close
   295    293   }
   296    294   finish_test
   297    295   

Added ext/fts5/test/fts5onepass.test.

            1  +# 2015 Sep 27
            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  +source [file join [file dirname [info script]] fts5_common.tcl]
           14  +set testprefix fts5onepass
           15  +
           16  +# If SQLITE_ENABLE_FTS3 is defined, omit this file.
           17  +ifcapable !fts5 {
           18  +  finish_test
           19  +  return
           20  +}
           21  +
           22  +do_execsql_test 1.0 {
           23  +  CREATE VIRTUAL TABLE ft USING fts5(content);
           24  +  INSERT INTO ft(rowid, content) VALUES(1, '1 2 3');
           25  +  INSERT INTO ft(rowid, content) VALUES(2, '4 5 6');
           26  +  INSERT INTO ft(rowid, content) VALUES(3, '7 8 9');
           27  +}
           28  +
           29  +#-------------------------------------------------------------------------
           30  +# Check that UPDATE and DELETE statements that feature "WHERE rowid=?" or 
           31  +# or "WHERE rowid=?" clauses do not use statement journals. But that other
           32  +# DELETE and UPDATE statements do.
           33  +#
           34  +# Note: "MATCH ? AND rowid=?" does use a statement journal.
           35  +#
           36  +foreach {tn sql uses} {
           37  +  1.1 { DELETE FROM ft } 1
           38  +  1.2 { DELETE FROM ft WHERE rowid=? } 0
           39  +  1.3 { DELETE FROM ft WHERE rowid=? } 0
           40  +  1.4 { DELETE FROM ft WHERE ft MATCH '1' } 1
           41  +  1.5 { DELETE FROM ft WHERE ft MATCH '1' AND rowid=? } 1
           42  +  1.6 { DELETE FROM ft WHERE ft MATCH '1' AND rowid=? } 1
           43  +
           44  +  2.1 { UPDATE ft SET content='a b c' } 1
           45  +  2.2 { UPDATE ft SET content='a b c' WHERE rowid=? } 0
           46  +  2.3 { UPDATE ft SET content='a b c' WHERE rowid=? } 0
           47  +  2.4 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' } 1
           48  +  2.5 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' AND rowid=? } 1
           49  +  2.6 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' AND rowid=? } 1
           50  +} {
           51  +  do_test 1.$tn { sql_uses_stmt db $sql } $uses
           52  +}
           53  +
           54  +#-------------------------------------------------------------------------
           55  +# Check that putting a "DELETE/UPDATE ... WHERE rowid=?" statement in a
           56  +# trigger program does not prevent the VM from using a statement 
           57  +# transaction. Even if the calling statement cannot hit a constraint.
           58  +#
           59  +do_execsql_test 2.0 {
           60  +  CREATE TABLE t1(x);
           61  +
           62  +  CREATE TRIGGER t1_ai AFTER INSERT ON t1 BEGIN
           63  +    DELETE FROM ft WHERE rowid=new.x;
           64  +  END;
           65  +
           66  +  CREATE TRIGGER t1_ad AFTER DELETE ON t1 BEGIN
           67  +    UPDATE ft SET content = 'a b c' WHERE rowid=old.x;
           68  +  END;
           69  +
           70  +  CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 BEGIN
           71  +    DELETE FROM ft WHERE rowid=old.x;
           72  +  END;
           73  +}
           74  +
           75  +foreach {tn sql uses} {
           76  +  1 { INSERT INTO t1 VALUES(1)      } 1
           77  +  2 { DELETE FROM t1 WHERE x=4      } 1
           78  +  3 { UPDATE t1 SET x=10 WHERE x=11 } 1
           79  +} {
           80  +  do_test 2.$tn { sql_uses_stmt db $sql } $uses
           81  +}
           82  +
           83  +#-------------------------------------------------------------------------
           84  +# Test that an "UPDATE ... WHERE rowid=?" works and does not corrupt the
           85  +# index when it strikes a constraint. Both inside and outside a 
           86  +# transaction.
           87  +#
           88  +foreach {tn tcl1 tcl2}  {
           89  +  1 {} {}
           90  +
           91  +  2 {
           92  +    execsql BEGIN
           93  +  } {
           94  +    if {[sqlite3_get_autocommit db]==1} { error "transaction rolled back!" }
           95  +    execsql COMMIT
           96  +  }
           97  +} {
           98  +
           99  +  do_execsql_test 3.$tn.0 {
          100  +    DROP TABLE IF EXISTS ft2;
          101  +    CREATE VIRTUAL TABLE ft2 USING fts5(content);
          102  +    INSERT INTO ft2(rowid, content) VALUES(1, 'a b c');
          103  +    INSERT INTO ft2(rowid, content) VALUES(2, 'a b d');
          104  +    INSERT INTO ft2(rowid, content) VALUES(3, 'a b e');
          105  +  }
          106  +
          107  +  eval $tcl1
          108  +  foreach {tn2 sql content} {
          109  +    1 { UPDATE ft2 SET rowid=2 WHERE rowid=1 }
          110  +      { 1 {a b c} 2 {a b d} 3 {a b e} }
          111  +
          112  +    2 { 
          113  +      INSERT INTO ft2(rowid, content) VALUES(4, 'a b f');
          114  +      UPDATE ft2 SET rowid=5 WHERE rowid=4;
          115  +      UPDATE ft2 SET rowid=3 WHERE rowid=5;
          116  +    } { 1 {a b c} 2 {a b d} 3 {a b e} 5 {a b f} }
          117  +
          118  +    3 {
          119  +      UPDATE ft2 SET rowid=3 WHERE rowid=4;           -- matches 0 rows
          120  +      UPDATE ft2 SET rowid=2 WHERE rowid=3;
          121  +    } { 1 {a b c} 2 {a b d} 3 {a b e} 5 {a b f} }
          122  +
          123  +    4 {
          124  +      INSERT INTO ft2(rowid, content) VALUES(4, 'a b g');
          125  +      UPDATE ft2 SET rowid=-1 WHERE rowid=4;
          126  +      UPDATE ft2 SET rowid=3 WHERE rowid=-1;
          127  +    } {-1 {a b g} 1 {a b c} 2 {a b d} 3 {a b e} 5 {a b f} }
          128  +
          129  +    5 {
          130  +      DELETE FROM ft2 WHERE rowid=451;
          131  +      DELETE FROM ft2 WHERE rowid=-1;
          132  +      UPDATE ft2 SET rowid = 2 WHERE rowid = 1;
          133  +    } {1 {a b c} 2 {a b d} 3 {a b e} 5 {a b f} }
          134  +  } {
          135  +    do_catchsql_test 3.$tn.$tn2.a $sql {1 {constraint failed}}
          136  +    do_execsql_test  3.$tn.$tn2.b { SELECT rowid, content FROM ft2 } $content
          137  +
          138  +    do_execsql_test  3.$tn.$tn2.c { 
          139  +      INSERT INTO ft2(ft2) VALUES('integrity-check');
          140  +    }
          141  +  }
          142  +  eval $tcl2
          143  +}
          144  +
          145  +#-------------------------------------------------------------------------
          146  +# Check that DELETE and UPDATE operations can be done without flushing
          147  +# the in-memory hash table to disk.
          148  +#
          149  +reset_db
          150  +do_execsql_test 4.1.1 {
          151  +  CREATE VIRTUAL TABLE ttt USING fts5(x);
          152  +  BEGIN;
          153  +    INSERT INTO ttt(rowid, x) VALUES(1, 'a b c');
          154  +    INSERT INTO ttt(rowid, x) VALUES(2, 'a b c');
          155  +    INSERT INTO ttt(rowid, x) VALUES(3, 'a b c');
          156  +  COMMIT
          157  +}
          158  +do_test 4.1.2 { fts5_level_segs ttt } {1}
          159  +
          160  +do_execsql_test 4.2.1 {
          161  +  BEGIN;
          162  +    DELETE FROM ttt WHERE rowid=1;
          163  +    DELETE FROM ttt WHERE rowid=3;
          164  +    INSERT INTO ttt(rowid, x) VALUES(4, 'd e f');
          165  +    INSERT INTO ttt(rowid, x) VALUES(5, 'd e f');
          166  +  COMMIT;
          167  +} {}
          168  +do_test 4.2.2 { fts5_level_segs ttt } {2}
          169  +
          170  +
          171  +do_execsql_test 4.3.1 {
          172  +  BEGIN;
          173  +    UPDATE ttt SET x = 'd e f' WHERE rowid = 2;
          174  +    UPDATE ttt SET x = 'A B C' WHERE rowid = 4;
          175  +    INSERT INTO ttt(rowid, x) VALUES(6, 'd e f');
          176  +  COMMIT;
          177  +} {}
          178  +do_test 4.2.2 { fts5_level_segs ttt } {3}
          179  +
          180  +finish_test
          181  +

Added ext/fts5/test/fts5phrase.test.

            1  +# 2014 Jan 08
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +#
           12  +# Tests focused on phrase queries.
           13  +#
           14  +
           15  +source [file join [file dirname [info script]] fts5_common.tcl]
           16  +set testprefix fts5phrase
           17  +
           18  +# If SQLITE_ENABLE_FTS5 is defined, omit this file.
           19  +ifcapable !fts5 {
           20  +  finish_test
           21  +  return
           22  +}
           23  +
           24  +do_execsql_test 1.0 {
           25  +  CREATE VIRTUAL TABLE t3 USING fts5(a, b, c);
           26  +  INSERT INTO t3 VALUES('d e a', 'd i j j f', 'i j i e b f h'); -- 1
           27  +  INSERT INTO t3 VALUES('g a e', 'f g i g a', 'h d g i g h c'); -- 2
           28  +  INSERT INTO t3 VALUES('e a d', 'e i h a f', 'c e h i f b i'); -- 3
           29  +  INSERT INTO t3 VALUES('a g c', 'd j d j c', 'c d f j i g j'); -- 4
           30  +  INSERT INTO t3 VALUES('b c b', 'j g c d f', 'j c j d g f b'); -- 5
           31  +  INSERT INTO t3 VALUES('j a d', 'e b i h h', 'c c f g d i d'); -- 6
           32  +  INSERT INTO t3 VALUES('a d f', 'h g i i i', 'e a g c i f b'); -- 7
           33  +  INSERT INTO t3 VALUES('g f d', 'f c g b j', 'b b h h h j j'); -- 8
           34  +  INSERT INTO t3 VALUES('f h g', 'c j f g j', 'd h d f e b h'); -- 9
           35  +  INSERT INTO t3 VALUES('f h d', 'c i a d b', 'g b j b a d e'); -- 10
           36  +  INSERT INTO t3 VALUES('j h h', 'j i h a g', 'd e i e a g j'); -- 11
           37  +  INSERT INTO t3 VALUES('a b e', 'h g a g c', 'h c a a d e g'); -- 12
           38  +  INSERT INTO t3 VALUES('a j g', 'i h i f i', 'a g h j g i b'); -- 13
           39  +  INSERT INTO t3 VALUES('j h e', 'f e d i e', 'i d c f e d c'); -- 14
           40  +  INSERT INTO t3 VALUES('d j d', 'd b i a c', 'g d h i d b e'); -- 15
           41  +  INSERT INTO t3 VALUES('h j e', 'e b b c f', 'j a f g h d j'); -- 16
           42  +  INSERT INTO t3 VALUES('c b j', 'c a b a i', 'h f i d a d c'); -- 17
           43  +  INSERT INTO t3 VALUES('e e d', 'i d f c c', 'g i d a f e a'); -- 18
           44  +  INSERT INTO t3 VALUES('e i g', 'e a b i h', 'i f d d a d f'); -- 19
           45  +  INSERT INTO t3 VALUES('h g f', 'b h h j d', 'i f d e g j a'); -- 20
           46  +  INSERT INTO t3 VALUES('e h f', 'j c b c f', 'j a j g h a c'); -- 21
           47  +  INSERT INTO t3 VALUES('d c h', 'b g i c e', 'i i c d e h i'); -- 22
           48  +  INSERT INTO t3 VALUES('a h i', 'a g d f f', 'e f i i b b h'); -- 23
           49  +  INSERT INTO t3 VALUES('d d g', 'c c b c g', 'g c h e b c e'); -- 24
           50  +  INSERT INTO t3 VALUES('a b b', 'b f a d i', 'd a h a b c i'); -- 25
           51  +  INSERT INTO t3 VALUES('a f d', 'a j e a h', 'j i h j a i f'); -- 26
           52  +  INSERT INTO t3 VALUES('d j d', 'h a d i a', 'h h f j h g a'); -- 27
           53  +  INSERT INTO t3 VALUES('g a e', 'd g f a g', 'i d b c g g j'); -- 28
           54  +  INSERT INTO t3 VALUES('j e h', 'g h j h g', 'd a e j a a h'); -- 29
           55  +  INSERT INTO t3 VALUES('e j e', 'g e j g c', 'f c e b e e a'); -- 30
           56  +  INSERT INTO t3 VALUES('h f f', 'i j g e c', 'j j f c a i j'); -- 31
           57  +  INSERT INTO t3 VALUES('a g c', 'c g d b i', 'g h c b a a f'); -- 32
           58  +  INSERT INTO t3 VALUES('c h i', 'j d h e e', 'a h i d c c j'); -- 33
           59  +  INSERT INTO t3 VALUES('d a c', 'e d d b j', 'c e b b h i h'); -- 34
           60  +  INSERT INTO t3 VALUES('d f h', 'c a f c c', 'j b b c c j f'); -- 35
           61  +  INSERT INTO t3 VALUES('b g h', 'g c c c f', 'c g c f h e e'); -- 36
           62  +  INSERT INTO t3 VALUES('f e a', 'b h f j h', 'j g h f d g f'); -- 37
           63  +  INSERT INTO t3 VALUES('h f a', 'a e i j g', 'f d a f d f c'); -- 38
           64  +  INSERT INTO t3 VALUES('f i c', 'f i i i i', 'e c f d h j f'); -- 39
           65  +  INSERT INTO t3 VALUES('h h d', 'd i e d i', 'd f e i a h a'); -- 40
           66  +  INSERT INTO t3 VALUES('f g c', 'd a f c h', 'b b g j c e g'); -- 41
           67  +  INSERT INTO t3 VALUES('h i h', 'h d j d e', 'e d b b i e g'); -- 42
           68  +  INSERT INTO t3 VALUES('b h i', 'j e i d a', 'j j h e e c a'); -- 43
           69  +  INSERT INTO t3 VALUES('g i g', 'f c c f d', 'a c i c a d a'); -- 44
           70  +  INSERT INTO t3 VALUES('c c f', 'a b j d b', 'c a e g f e c'); -- 45
           71  +  INSERT INTO t3 VALUES('d h j', 'g c b j d', 'e a h f h j g'); -- 46
           72  +  INSERT INTO t3 VALUES('a a d', 'j e j a i', 'i d c f f f b'); -- 47
           73  +  INSERT INTO t3 VALUES('b g j', 'e c i h f', 'd d h b g a d'); -- 48
           74  +  INSERT INTO t3 VALUES('c i a', 'a c c c c', 'e h i e h i e'); -- 49
           75  +  INSERT INTO t3 VALUES('f f c', 'f f b i i', 'f f a j e c i'); -- 50
           76  +}
           77  +
           78  +proc pmatch {col expr} {
           79  +  return [expr {[string first $expr $col]>=0}]
           80  +}
           81  +db func pmatch pmatch
           82  +
           83  +foreach {tn cols tokens} {
           84  +  1 a         "c c"
           85  +  2 b         "c c"
           86  +  3 c         "c c"
           87  +  4 {a b c}   "c c"
           88  +  5 {a b c}   "b h"
           89  +  6 {a b}     "b h"
           90  +  7 {a c}     "b h"
           91  +  8 {c a}     "b h"
           92  +  9 {c}       "i e"
           93  +  10 {b}      "i e"
           94  +  11 {a}      "i e"
           95  +} {
           96  +  set fts   "{$cols}:[join $tokens +]"
           97  +  set where [list]
           98  +  foreach c $cols { lappend where "pmatch($c, '$tokens')" }
           99  +  set where [join $where " OR "]
          100  +
          101  +  set res [db eval "SELECT rowid FROM t3 WHERE $where"]
          102  +  do_execsql_test "1.$tn.$fts->([llength $res] rows)" { 
          103  +    SELECT rowid FROM t3($fts) 
          104  +  } $res
          105  +}
          106  +
          107  +do_execsql_test 2.0 {
          108  +  SELECT rowid,
          109  +    highlight(t3, 0, '*', '*'),
          110  +    highlight(t3, 1, '*', '*'),
          111  +    highlight(t3, 2, '*', '*')
          112  +  FROM t3('a:f+f')
          113  +} {
          114  +  31 {h *f f*} {i j g e c} {j j f c a i j} 
          115  +  50 {*f f* c} {f f b i i} {f f a j e c i}
          116  +}
          117  +
          118  +finish_test
          119  +

Changes to ext/fts5/test/fts5prefix.test.

    58     58   foreach {tn q res} {
    59     59     1 "SELECT rowid FROM t1 WHERE t1 MATCH '\xCA\xCB*'" 1
    60     60     2 "SELECT rowid FROM t1 WHERE t1 MATCH '\u1234\u5678*'" 2
    61     61   } {
    62     62     do_execsql_test 2.3.$tn $q $res
    63     63   }
    64     64   
           65  +#-------------------------------------------------------------------------
           66  +# Check that prefix queries with:
           67  +#
           68  +#   * a column filter, and
           69  +#   * no prefix index.
           70  +#
           71  +# work Ok.
           72  +#
           73  +do_execsql_test 3.0 {
           74  +  CREATE VIRTUAL TABLE t3 USING fts5(a, b, c);
           75  +  INSERT INTO t3(t3, rank) VALUES('pgsz', 32);
           76  +  BEGIN;
           77  +    INSERT INTO t3 VALUES('acb ccc bba', 'cca bba bca', 'bbc ccc bca'); -- 1
           78  +    INSERT INTO t3 VALUES('cbb cac cab', 'abb aac bba', 'aab ccc cac'); -- 2
           79  +    INSERT INTO t3 VALUES('aac bcb aac', 'acb bcb caa', 'aca bab bca'); -- 3
           80  +    INSERT INTO t3 VALUES('aab ccb ccc', 'aca cba cca', 'aca aac cbb'); -- 4
           81  +    INSERT INTO t3 VALUES('bac aab bab', 'ccb bac cba', 'acb aba abb'); -- 5
           82  +    INSERT INTO t3 VALUES('bab abc ccb', 'acb cba abb', 'cbb aaa cab'); -- 6
           83  +    INSERT INTO t3 VALUES('cbb bbc baa', 'aab aca baa', 'bcc cca aca'); -- 7
           84  +    INSERT INTO t3 VALUES('abc bba abb', 'cac abc cba', 'acc aac cac'); -- 8
           85  +    INSERT INTO t3 VALUES('bbc bbc cab', 'bcb ccb cba', 'bcc cac acb'); -- 9
           86  +  COMMIT;
           87  +}
           88  +
           89  +foreach {tn match res} {
           90  +  1 "a : c*" {1 2 4 6 7 9}
           91  +  2 "b : c*" {1 3 4 5 6 8 9}
           92  +  3 "c : c*" {1 2 4 6 7 8 9}
           93  +  4 "a : b*" {1 3 5 6 7 8 9}
           94  +  5 "b : b*" {1 2 3 5 7 9}
           95  +  6 "c : b*" {1 3 7 9}
           96  +  7 "a : a*" {1 3 4 5 6 8}
           97  +  8 "b : a*" {2 3 4 6 7 8}
           98  +  9 "c : a*" {2 3 4 5 6 7 8 9}
           99  +} {
          100  +  do_execsql_test 3.1.$tn {
          101  +    SELECT rowid FROM t3($match)
          102  +  } $res
          103  +}
          104  +
          105  +do_test 3.2 {
          106  +  expr srand(0)
          107  +  execsql { DELETE FROM t3 }
          108  +  for {set i 0} {$i < 1000} {incr i} {
          109  +    set a [fts5_rnddoc 3]
          110  +    set b [fts5_rnddoc 8]
          111  +    set c [fts5_rnddoc 20]
          112  +    execsql { INSERT INTO t3 VALUES($a, $b, $c) }
          113  +  }
          114  +  execsql { INSERT INTO t3(t3) VALUES('integrity-check') }
          115  +} {}
          116  +
          117  +proc gmatch {col pattern} {
          118  +  expr {[lsearch -glob $col $pattern]>=0}
          119  +}
          120  +db func gmatch gmatch
          121  +
          122  +proc ghl {col pattern} {
          123  +  foreach t $col {
          124  +    if {[string match $pattern $t]} {
          125  +      lappend res "*$t*"
          126  +    } else {
          127  +      lappend res $t
          128  +    }
          129  +  }
          130  +  set res
          131  +}
          132  +db func ghl ghl
          133  +
          134  +set COLS(a) 0
          135  +set COLS(b) 1
          136  +set COLS(c) 2
          137  +
          138  +for {set x 0} {$x<2} {incr x} {
          139  +  foreach {tn pattern} {
          140  +    1  {xa*}
          141  +    2  {xb*}
          142  +    3  {xc*}
          143  +    4  {xd*}
          144  +    5  {xe*}
          145  +    6  {xf*}
          146  +    7  {xg*}
          147  +    8  {xh*}
          148  +    9  {xi*}
          149  +    10 {xj*}
          150  +  } {
          151  +    foreach col {a b c} {
          152  +
          153  +      # Check that the list of returned rowids is correct.
          154  +      #
          155  +      set res [db eval "SELECT rowid FROM t3 WHERE gmatch($col, '$pattern')"]
          156  +      set query "$col : $pattern"
          157  +      do_execsql_test 3.3.$x.$tn.$col.rowid {
          158  +        SELECT rowid FROM t3($query);
          159  +      } $res
          160  +
          161  +      # Check that the highlight() function works.
          162  +      #
          163  +      set res [db eval \
          164  +        "SELECT ghl($col, '$pattern') FROM t3 WHERE gmatch($col, '$pattern')"
          165  +      ]
          166  +      set idx $COLS($col)
          167  +      do_execsql_test 3.3.$x.$tn.$col.highlight {
          168  +        SELECT highlight(t3, $idx, '*', '*') FROM t3($query);
          169  +      } $res
          170  +    }
          171  +
          172  +    foreach colset {{a b} {b c} {c a} {a c} {b a}} {
          173  +      # Check that the list of returned rowids is correct.
          174  +      #
          175  +      foreach {col1 col2} $colset {}
          176  +      set expr "gmatch($col1, '$pattern') OR gmatch($col2, '$pattern')"
          177  +      set res [db eval "SELECT rowid FROM t3 WHERE $expr"]
          178  +      set query "{$colset} : $pattern"
          179  +      do_execsql_test 3.3.$x.$tn.{$colset}.rowid {
          180  +        SELECT rowid FROM t3($query);
          181  +      } $res
          182  +
          183  +      set resq    "SELECT ghl($col1, '$pattern'), ghl($col2, '$pattern')"
          184  +      append resq " FROM t3 WHERE $expr"
          185  +      set res [db eval $resq]
          186  +      set idx1 $COLS($col1)
          187  +      set idx2 $COLS($col2)
          188  +      do_execsql_test 3.3.$x.$tn.{$colset}.highlight {
          189  +        SELECT highlight(t3, $idx1, '*', '*'), highlight(t3, $idx2, '*', '*')
          190  +          FROM t3($query)
          191  +      } $res
          192  +    }
          193  +  }
          194  +  execsql { INSERT INTO t3(t3) VALUES('optimize') }
          195  +  execsql { INSERT INTO t3(t3) VALUES('integrity-check') }
          196  +}
          197  +
    65    198   
    66    199   finish_test
          200  +
    67    201   

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

    15     15   
    16     16   # If SQLITE_ENABLE_FTS5 is defined, omit this file.
    17     17   ifcapable !fts5 {
    18     18     finish_test
    19     19     return
    20     20   }
    21     21   
    22         -if 1 {
    23     22   #-------------------------------------------------------------------------
    24     23   #
    25     24   set doc "x x [string repeat {y } 50]z z"
    26     25   do_execsql_test 1.0 {
    27     26     CREATE VIRTUAL TABLE t1 USING fts5(x);
    28     27     INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
    29     28     BEGIN;
................................................................................
   133    132     COMMIT;
   134    133   } {}
   135    134   
   136    135   do_execsql_test 5.4 {
   137    136     SELECT rowid FROM tt WHERE tt MATCH 'a*';
   138    137   } {1 2}
   139    138   
   140         -}
   141         -
   142    139   do_execsql_test 5.5 {
   143    140     DELETE FROM tt;
   144    141     BEGIN;
   145    142       INSERT INTO tt VALUES('aa');
   146    143       INSERT INTO tt VALUES('ab');
   147    144       INSERT INTO tt VALUES('aa');
   148    145       INSERT INTO tt VALUES('ab');
................................................................................
   179    176   
   180    177   do_catchsql_test 6.2 { 
   181    178     SELECT * FROM xyz WHERE xyz MATCH '' 
   182    179   } {1 {fts5: syntax error near ""}}
   183    180   do_catchsql_test 6.3 { 
   184    181     SELECT * FROM xyz WHERE xyz MATCH NULL 
   185    182   } {1 {fts5: syntax error near ""}}
          183  +
          184  +#-------------------------------------------------------------------------
          185  +
          186  +do_execsql_test 7.1 {
          187  +  CREATE VIRTUAL TABLE ft2 USING fts5(content);
          188  +  INSERT INTO ft2(rowid, content) VALUES(1, 'a b c');
          189  +  INSERT INTO ft2(rowid, content) VALUES(2, 'a b d');
          190  +} 
          191  +
          192  +do_catchsql_test 7.2 {
          193  +  BEGIN;
          194  +    UPDATE ft2 SET rowid=2 WHERE rowid=1;
          195  +} {1 {constraint failed}} 
          196  +
          197  +do_execsql_test 7.3 {
          198  +  COMMIT;
          199  +  INSERT INTO ft2(ft2) VALUES('integrity-check');
          200  +} {}
          201  +
          202  +do_execsql_test 7.4 {
          203  +  SELECT * FROM ft2;
          204  +} {{a b c} {a b d}}
          205  +
          206  +#-------------------------------------------------------------------------
          207  +#
          208  +reset_db
          209  +do_execsql_test 8.1 {
          210  +  CREATE VIRTUAL TABLE ft2 USING fts5(content);
          211  +  INSERT INTO ft2(rowid, content) VALUES(1, 'a b');
          212  +}
          213  +
          214  +do_execsql_test 8.2 {
          215  +  BEGIN;
          216  +    INSERT INTO ft2(rowid, content) VALUES(4, 'a x');
          217  +}
          218  +
          219  +do_execsql_test 8.3 {
          220  +  INSERT INTO ft2(ft2) VALUES('integrity-check');
          221  +}
          222  +
          223  +#-------------------------------------------------------------------------
          224  +# Check that the "table function" syntax works.
          225  +#
          226  +reset_db
          227  +do_execsql_test 9.1 {
          228  +  CREATE VIRTUAL TABLE ft2 USING fts5(content);
          229  +  INSERT INTO ft2(rowid, content) VALUES(1, 'a b');
          230  +  INSERT INTO ft2(rowid, content) VALUES(2, 'a b c d');
          231  +  INSERT INTO ft2(rowid, content) VALUES(3, 'c d e f');
          232  +}
          233  +
          234  +do_execsql_test 9.2 {
          235  +  SELECT rowid FROM ft2('a');
          236  +} {1 2}
          237  +
          238  +do_execsql_test 9.3 {
          239  +  SELECT rowid FROM ft2('b AND c');
          240  +} {2}
          241  +
          242  +#-------------------------------------------------------------------------
          243  +#
          244  +do_execsql_test 10.0 {
          245  +  CREATE VIRTUAL TABLE t3 USING fts5(a, b, c);
          246  +  INSERT INTO t3 VALUES('bac aab bab', 'c bac c', 'acb aba abb'); -- 1
          247  +  INSERT INTO t3 VALUES('bab abc c', 'acb c abb', 'c aaa c');     -- 2
          248  +}
          249  +
          250  +do_execsql_test 10.1 {
          251  +  SELECT rowid FROM t3('c: c*');
          252  +} {2}
          253  +
          254  +#-------------------------------------------------------------------------
          255  +# Test that character 0x1A is allowed in fts5 barewords.
          256  +#
          257  +do_test 11.0 {
          258  +  execsql "CREATE VIRTUAL TABLE t4 USING fts5(x, tokenize=\"ascii tokenchars '\x1A'\")"
          259  +  execsql "
          260  +    INSERT INTO t4 VALUES('a b c \x1A');
          261  +    INSERT INTO t4 VALUES('a b c d\x1A');
          262  +    INSERT INTO t4 VALUES('a b c \x1Ad');
          263  +    INSERT INTO t4 VALUES('a b c d');
          264  +  "
          265  +} {}
          266  +
          267  +do_test 11.1 {
          268  +  execsql "SELECT rowid FROM t4('\x1A')"
          269  +} {1}
          270  +do_test 11.2 {
          271  +  execsql "SELECT rowid FROM t4('\x1A*')"
          272  +} {1 3}
          273  +do_test 11.3 {
          274  +  execsql "SELECT rowid FROM t4('d\x1A')"
          275  +} {2}
          276  +
          277  +do_test 11.4 {
          278  +  catchsql "SELECT rowid FROM t4('d\x1B')"
          279  +} {/fts5: syntax error/}
          280  +do_test 11.5 {
          281  +  catchsql "SELECT rowid FROM t4('d\x19')"
          282  +} {/fts5: syntax error/}
   186    283   
   187    284   
   188    285   finish_test
   189    286   

Added ext/fts5/tool/fts5txt2db.tcl.

            1  +
            2  +
            3  +proc usage {} {
            4  +  puts stderr "$::argv0 ?OPTIONS? DATABASE FILE1..."
            5  +  puts stderr ""
            6  +  puts stderr "Options are"
            7  +  puts stderr "  -fts5"
            8  +  puts stderr "  -fts4"
            9  +  puts stderr "  -colsize <list of column sizes>"
           10  +  puts stderr {
           11  +This script is designed to create fts4/5 tables with more than one column.
           12  +The -colsize option should be set to a Tcl list of integer values, one for
           13  +each column in the table. Each value is the number of tokens that will be
           14  +inserted into the column value for each row. For example, setting the -colsize
           15  +option to "5 10" creates an FTS table with 2 columns, with roughly 5 and 10
           16  +tokens per row in each, respectively.
           17  +
           18  +Each "FILE" argument should be a text file. The contents of these text files is
           19  +split on whitespace characters to form a list of tokens. The first N1 tokens
           20  +are used for the first column of the first row, where N1 is the first element
           21  +of the -colsize list. The next N2 are used for the second column of the first
           22  +row, and so on. Rows are added to the table until the entire list of tokens
           23  +is exhausted.
           24  +}
           25  +  exit -1
           26  +}
           27  +
           28  +set O(aColsize)       [list 10 10 10]
           29  +set O(tblname)        t1
           30  +set O(fts)            fts5
           31  +
           32  +
           33  +set options_with_values {-colsize}
           34  +
           35  +for {set i 0} {$i < [llength $argv]} {incr i} {
           36  +  set opt [lindex $argv $i]
           37  +  if {[string range $opt 0 0]!="-"} break
           38  +
           39  +  if {[lsearch $options_with_values $opt]>=0} {
           40  +    incr i
           41  +    if {$i==[llength $argv]} usage
           42  +    set val [lindex $argv $i]
           43  +  }
           44  +
           45  +  switch -- $opt {
           46  +    -colsize {
           47  +      set O(aColSize) $val
           48  +    }
           49  +
           50  +    -fts4 {
           51  +      set O(fts) fts4
           52  +    }
           53  +
           54  +    -fts5 {
           55  +      set O(fts) fts5
           56  +    }
           57  +  }
           58  +}
           59  +
           60  +if {$i > [llength $argv]-2} usage
           61  +set O(db) [lindex $argv $i]
           62  +set O(files) [lrange $argv [expr $i+1] end]
           63  +
           64  +foreach {k v} [lrange $argv 0 end-2] {
           65  +  switch -- $k {
           66  +    -colsize {
           67  +      set O(aColSize) $v
           68  +    }
           69  +
           70  +    -colsize {
           71  +      set O(aColSize) $v
           72  +    }
           73  +  }
           74  +
           75  +}
           76  +
           77  +sqlite3 db $O(db)
           78  +load_static_extension db fts5
           79  +
           80  +
           81  +# Create the FTS table in the db. Return a list of the table columns.
           82  +#
           83  +proc create_table {} {
           84  +  global O
           85  +  set cols [list a b c d e f g h i j k l m n o p q r s t u v w x y z]
           86  +
           87  +  set nCol [llength $O(aColsize)]
           88  +  set cols [lrange $cols 0 [expr $nCol-1]]
           89  +
           90  +  set sql    "CREATE VIRTUAL TABLE IF NOT EXISTS $O(tblname) USING $O(fts) ("
           91  +  append sql [join $cols ,]
           92  +  append sql ");"
           93  +
           94  +  db eval $sql
           95  +  return $cols
           96  +}
           97  +
           98  +# Return a list of tokens from the named file.
           99  +#
          100  +proc readfile {file} {
          101  +  set fd [open $file]
          102  +  set data [read $fd]
          103  +  close $fd
          104  +  split $data
          105  +}
          106  +
          107  +
          108  +# Load all the data into a big list of tokens.
          109  +#
          110  +set tokens [list]
          111  +foreach f $O(files) {
          112  +  set tokens [concat $tokens [readfile $f]]
          113  +}
          114  +
          115  +set N [llength $tokens]
          116  +set i 0
          117  +set cols [create_table]
          118  +set sql "INSERT INTO $O(tblname) VALUES(\$[lindex $cols 0]"
          119  +foreach c [lrange $cols 1 end] {
          120  +  append sql ", \$$c"
          121  +}
          122  +append sql ")"
          123  +
          124  +db eval BEGIN
          125  +  while {$i < $N} {
          126  +    foreach c $cols s $O(aColsize) {
          127  +      set $c [lrange $tokens $i [expr $i+$s-1]]
          128  +      incr i $s
          129  +    }
          130  +    db eval $sql
          131  +  }
          132  +db eval COMMIT
          133  +
          134  +
          135  +

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

     3      3   exec tclsh "$0" "$@"
     4      4   
     5      5   set srcdir [file dirname [file dirname [info script]]]
     6      6   set G(src) [string map [list %dir% $srcdir] {
     7      7     %dir%/fts5.h
     8      8     %dir%/fts5Int.h
     9      9     fts5parse.h
           10  +  fts5parse.c
    10     11     %dir%/fts5_aux.c
    11     12     %dir%/fts5_buffer.c
    12     13     %dir%/fts5_config.c
    13     14     %dir%/fts5_expr.c
    14     15     %dir%/fts5_hash.c
    15     16     %dir%/fts5_index.c
    16     17     %dir%/fts5_main.c
    17     18     %dir%/fts5_storage.c
    18     19     %dir%/fts5_tokenize.c
    19     20     %dir%/fts5_unicode2.c
    20     21     %dir%/fts5_varint.c
    21     22     %dir%/fts5_vocab.c
    22         -  fts5parse.c
    23     23   }]
    24     24   
    25     25   set G(hdr) {
    26     26   
    27         -#if !defined(SQLITE_TEST) || defined(SQLITE_ENABLE_FTS5) 
           27  +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5) 
    28     28   
    29     29   #if !defined(NDEBUG) && !defined(SQLITE_DEBUG) 
    30     30   # define NDEBUG 1
    31     31   #endif
    32     32   #if defined(NDEBUG) && defined(SQLITE_DEBUG)
    33     33   # undef NDEBUG
    34     34   #endif
    35     35   
    36     36   }
    37     37   
    38     38   set G(footer) {
    39     39       
    40         -#endif /* !defined(SQLITE_TEST) || defined(SQLITE_ENABLE_FTS5) */
           40  +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5) */
    41     41   }
    42     42   
    43     43   #-------------------------------------------------------------------------
    44     44   # Read and return the entire contents of text file $zFile from disk.
    45     45   #
    46     46   proc readfile {zFile} {
    47     47     set fd [open $zFile]
................................................................................
    83     83     set sub_map [list --FTS5-SOURCE-ID-- [fts5_source_id $::srcdir]]
    84     84     if {$zTail=="fts5parse.c"} {
    85     85       lappend sub_map yy fts5yy YY fts5YY TOKEN FTS5TOKEN
    86     86     }
    87     87   
    88     88     foreach line [split $data "\n"] {
    89     89       if {[regexp {^#include.*fts5} $line]} continue
    90         -    if {[regexp {^(const )?[a-zA-Z][a-zA-Z0-9]* [*]?sqlite3Fts5} $line]} {
           90  +    if { ![regexp { sqlite3Fts5Init\(} $line] 
           91  +       && [regexp {^(const )?[a-zA-Z][a-zA-Z0-9]* [*]?sqlite3Fts5} $line]
           92  +    } {
    91     93         set line "static $line"
    92     94       }
    93     95       set line [string map $sub_map $line]
    94     96       puts $G(fd) $line
    95     97     }
    96     98   }
    97     99   
................................................................................
   103    105     }
   104    106   }
   105    107   
   106    108   
   107    109   fts5c_init fts5.c
   108    110   foreach f $G(src) { fts5c_printfile $f }
   109    111   fts5c_close
   110         -
   111         -
   112         -
   113         -

Changes to ext/misc/json1.c.

    17     17   **
    18     18   ** For the time being, all JSON is stored as pure text.  (We might add
    19     19   ** a JSONB type in the future which stores a binary encoding of JSON in
    20     20   ** a BLOB, but there is no support for JSONB in the current implementation.
    21     21   ** This implementation parses JSON text at 250 MB/s, so it is hard to see
    22     22   ** how JSONB might improve on that.)
    23     23   */
           24  +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1)
    24     25   #if !defined(_SQLITEINT_H_)
    25     26   #include "sqlite3ext.h"
    26     27   #endif
    27     28   SQLITE_EXTENSION_INIT1
    28     29   #include <assert.h>
    29     30   #include <string.h>
    30     31   #include <ctype.h>
................................................................................
  1933   1934     0,                         /* xSavepoint */
  1934   1935     0,                         /* xRelease */
  1935   1936     0                          /* xRollbackTo */
  1936   1937   };
  1937   1938   #endif /* SQLITE_OMIT_VIRTUALTABLE */
  1938   1939   
  1939   1940   /****************************************************************************
  1940         -** The following routine is the only publically visible identifier in this
  1941         -** file.  Call the following routine in order to register the various SQL
         1941  +** The following routines are the only publically visible identifiers in this
         1942  +** file.  Call the following routines in order to register the various SQL
  1942   1943   ** functions and the virtual table implemented by this file.
  1943   1944   ****************************************************************************/
  1944   1945   
  1945         -#ifdef _WIN32
  1946         -__declspec(dllexport)
  1947         -#endif
  1948         -int sqlite3_json_init(
  1949         -  sqlite3 *db, 
  1950         -  char **pzErrMsg, 
  1951         -  const sqlite3_api_routines *pApi
  1952         -){
         1946  +int sqlite3Json1Init(sqlite3 *db){
  1953   1947     int rc = SQLITE_OK;
  1954   1948     unsigned int i;
  1955   1949     static const struct {
  1956   1950        const char *zName;
  1957   1951        int nArg;
  1958   1952        int flag;
  1959   1953        void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
................................................................................
  1983   1977        const char *zName;
  1984   1978        sqlite3_module *pModule;
  1985   1979     } aMod[] = {
  1986   1980       { "json_each",            &jsonEachModule               },
  1987   1981       { "json_tree",            &jsonTreeModule               },
  1988   1982     };
  1989   1983   #endif
  1990         -  SQLITE_EXTENSION_INIT2(pApi);
  1991         -  (void)pzErrMsg;  /* Unused parameter */
  1992   1984     for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
  1993   1985       rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
  1994   1986                                    SQLITE_UTF8 | SQLITE_DETERMINISTIC, 
  1995   1987                                    (void*)&aFunc[i].flag,
  1996   1988                                    aFunc[i].xFunc, 0, 0);
  1997   1989     }
  1998   1990   #ifndef SQLITE_OMIT_VIRTUALTABLE
  1999   1991     for(i=0; i<sizeof(aMod)/sizeof(aMod[0]) && rc==SQLITE_OK; i++){
  2000   1992       rc = sqlite3_create_module(db, aMod[i].zName, aMod[i].pModule, 0);
  2001   1993     }
  2002   1994   #endif
  2003   1995     return rc;
  2004   1996   }
         1997  +
         1998  +
         1999  +#ifdef _WIN32
         2000  +__declspec(dllexport)
         2001  +#endif
         2002  +int sqlite3_json_init(
         2003  +  sqlite3 *db, 
         2004  +  char **pzErrMsg, 
         2005  +  const sqlite3_api_routines *pApi
         2006  +){
         2007  +  SQLITE_EXTENSION_INIT2(pApi);
         2008  +  (void)pzErrMsg;  /* Unused parameter */
         2009  +  return sqlite3Json1Init(db);
         2010  +}
         2011  +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) */

Changes to ext/rbu/sqlite3rbu.c.

    84     84   #include <string.h>
    85     85   #include <stdio.h>
    86     86   
    87     87   #include "sqlite3.h"
    88     88   
    89     89   #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU)
    90     90   #include "sqlite3rbu.h"
           91  +
           92  +#if defined(_WIN32_WCE)
           93  +#include "windows.h"
           94  +#endif
    91     95   
    92     96   /* Maximum number of prepared UPDATE statements held by this module */
    93     97   #define SQLITE_RBU_UPDATE_CACHESIZE 16
    94     98   
    95     99   /*
    96    100   ** Swap two objects of type TYPE.
    97    101   */
................................................................................
  2378   2382     assert( p->rc==SQLITE_OK );
  2379   2383     p->rc = pReal->pMethods->xLock(pReal, SQLITE_LOCK_SHARED);
  2380   2384     if( p->rc==SQLITE_OK ){
  2381   2385       p->rc = pReal->pMethods->xLock(pReal, SQLITE_LOCK_EXCLUSIVE);
  2382   2386     }
  2383   2387   }
  2384   2388   
         2389  +#if defined(_WIN32_WCE)
         2390  +static LPWSTR rbuWinUtf8ToUnicode(const char *zFilename){
         2391  +  int nChar;
         2392  +  LPWSTR zWideFilename;
         2393  +
         2394  +  nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
         2395  +  if( nChar==0 ){
         2396  +    return 0;
         2397  +  }
         2398  +  zWideFilename = sqlite3_malloc( nChar*sizeof(zWideFilename[0]) );
         2399  +  if( zWideFilename==0 ){
         2400  +    return 0;
         2401  +  }
         2402  +  memset(zWideFilename, 0, nChar*sizeof(zWideFilename[0]));
         2403  +  nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename,
         2404  +                                nChar);
         2405  +  if( nChar==0 ){
         2406  +    sqlite3_free(zWideFilename);
         2407  +    zWideFilename = 0;
         2408  +  }
         2409  +  return zWideFilename;
         2410  +}
         2411  +#endif
         2412  +
  2385   2413   /*
  2386   2414   ** The RBU handle is currently in RBU_STAGE_OAL state, with a SHARED lock
  2387   2415   ** on the database file. This proc moves the *-oal file to the *-wal path,
  2388   2416   ** then reopens the database file (this time in vanilla, non-oal, WAL mode).
  2389   2417   ** If an error occurs, leave an error code and error message in the rbu 
  2390   2418   ** handle.
  2391   2419   */
................................................................................
  2412   2440         rbuFileSuffix3(zBase, zWal);
  2413   2441         rbuFileSuffix3(zBase, zOal);
  2414   2442   
  2415   2443         /* Re-open the databases. */
  2416   2444         rbuObjIterFinalize(&p->objiter);
  2417   2445         sqlite3_close(p->dbMain);
  2418   2446         sqlite3_close(p->dbRbu);
         2447  +      p->dbMain = 0;
         2448  +      p->dbRbu = 0;
         2449  +
         2450  +#if defined(_WIN32_WCE)
         2451  +      {
         2452  +        LPWSTR zWideOal;
         2453  +        LPWSTR zWideWal;
         2454  +
         2455  +        zWideOal = rbuWinUtf8ToUnicode(zOal);
         2456  +        if( zWideOal ){
         2457  +          zWideWal = rbuWinUtf8ToUnicode(zWal);
         2458  +          if( zWideWal ){
         2459  +            if( MoveFileW(zWideOal, zWideWal) ){
         2460  +              p->rc = SQLITE_OK;
         2461  +            }else{
         2462  +              p->rc = SQLITE_IOERR;
         2463  +            }
         2464  +            sqlite3_free(zWideWal);
         2465  +          }else{
         2466  +            p->rc = SQLITE_IOERR_NOMEM;
         2467  +          }
         2468  +          sqlite3_free(zWideOal);
         2469  +        }else{
         2470  +          p->rc = SQLITE_IOERR_NOMEM;
         2471  +        }
         2472  +      }
         2473  +#else
  2419   2474         p->rc = rename(zOal, zWal) ? SQLITE_IOERR : SQLITE_OK;
         2475  +#endif
         2476  +
  2420   2477         if( p->rc==SQLITE_OK ){
  2421         -        p->dbMain = 0;
  2422         -        p->dbRbu = 0;
  2423   2478           rbuOpenDatabase(p);
  2424   2479           rbuSetupCheckpoint(p, 0);
  2425   2480         }
  2426   2481       }
  2427   2482     }
  2428   2483   
  2429   2484     sqlite3_free(zWal);

Changes to ext/rtree/rtree1.test.

    30     30   #   rtree-5.*: Test DELETE
    31     31   #   rtree-6.*: Test UPDATE
    32     32   #   rtree-7.*: Test renaming an r-tree table.
    33     33   #   rtree-8.*: Test constrained scans of r-tree data.
    34     34   #
    35     35   #   rtree-12.*: Test that on-conflict clauses are supported.
    36     36   #   rtree-13.*: Test that bug [d2889096e7bdeac6d] has been fixed.
           37  +#   rtree-14.*: Test if a non-integer is inserted into the PK column of an
           38  +#               r-tree table, it is converted to an integer before being
           39  +#               inserted. Also that if a non-numeric is inserted into one
           40  +#               of the min/max dimension columns, it is converted to the
           41  +#               required type before being inserted.
    37     42   #
    38     43   
    39     44   ifcapable !rtree {
    40     45     finish_test
    41     46     return
    42     47   }
    43     48   
................................................................................
   530    535     WITH r(x) AS (
   531    536       SELECT 1 UNION ALL
   532    537       SELECT 2 UNION ALL
   533    538       SELECT 3
   534    539     )
   535    540     SELECT * FROM r CROSS JOIN t9 WHERE id=x;
   536    541   } {1 1 0.0 0.0 2 2 0.0 0.0}
          542  +
          543  +#-------------------------------------------------------------------------
          544  +# Test if a non-integer is inserted into the PK column of an r-tree
          545  +# table, it is converted to an integer before being inserted. Also
          546  +# that if a non-numeric is inserted into one of the min/max dimension
          547  +# columns, it is converted to the required type before being inserted.
          548  +#
          549  +do_execsql_test 14.1 {
          550  +  CREATE VIRTUAL TABLE t10 USING rtree(ii, x1, x2);
          551  +}
          552  +
          553  +do_execsql_test 14.2 {
          554  +  INSERT INTO t10 VALUES(NULL,   1, 2);
          555  +  INSERT INTO t10 VALUES(NULL,   2, 3);
          556  +  INSERT INTO t10 VALUES('4xxx', 3, 4);
          557  +  INSERT INTO t10 VALUES(5.0,    4, 5);
          558  +  INSERT INTO t10 VALUES(6.4,    5, 6);
          559  +}
          560  +do_execsql_test 14.3 {
          561  +  SELECT * FROM t10;
          562  +} {
          563  +  1 1.0 2.0   2 2.0 3.0   4 3.0 4.0   5 4.0 5.0   6 5.0 6.0
          564  +}
          565  +
          566  +do_execsql_test 14.4 {
          567  +  DELETE FROM t10;
          568  +  INSERT INTO t10 VALUES(1, 'one', 'two');
          569  +  INSERT INTO t10 VALUES(2, '52xyz', '81...');
          570  +}
          571  +do_execsql_test 14.5 {
          572  +  SELECT * FROM t10;
          573  +} {
          574  +  1 0.0 0.0
          575  +  2 52.0 81.0
          576  +}
          577  +
          578  +do_execsql_test 14.4 {
          579  +  DROP TABLE t10;
          580  +  CREATE VIRTUAL TABLE t10 USING rtree_i32(ii, x1, x2);
          581  +  INSERT INTO t10 VALUES(1, 'one', 'two');
          582  +  INSERT INTO t10 VALUES(2, '52xyz', '81...');
          583  +  INSERT INTO t10 VALUES(3, 42.3, 49.9);
          584  +}
          585  +do_execsql_test 14.5 {
          586  +  SELECT * FROM t10;
          587  +} {
          588  +  1 0 0
          589  +  2 52 81
          590  +  3 42 49
          591  +}
   537    592   
   538    593   finish_test

Changes to main.mk.

     7      7   #                  "configure.in" script.
     8      8   #
     9      9   # BCC              C Compiler and options for use in building executables that
    10     10   #                  will run on the platform that is doing the build.
    11     11   #
    12     12   # THREADLIB        Specify any extra linker options needed to make the library
    13     13   #                  thread safe
           14  +#
           15  +# LIBS             Extra libraries options
    14     16   #
    15     17   # OPTS             Extra compiler command-line options.
    16     18   #
    17     19   # EXE              The suffix to add to executable files.  ".exe" for windows
    18     20   #                  and "" for Unix.
    19     21   #
    20     22   # TCC              C Compiler and options for use in building executables that 
................................................................................
    44     46   
    45     47   # This is how we compile
    46     48   #
    47     49   TCCX =  $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP) 
    48     50   TCCX += -I$(TOP)/ext/rtree -I$(TOP)/ext/icu -I$(TOP)/ext/fts3
    49     51   TCCX += -I$(TOP)/ext/async -I$(TOP)/ext/userauth
    50     52   TCCX += -I$(TOP)/ext/fts5
           53  +THREADLIB += $(LIBS)
    51     54   
    52     55   # Object files for the SQLite library.
    53     56   #
    54     57   LIBOBJ+= vdbe.o parse.o \
    55     58            alter.o analyze.o attach.o auth.o \
    56     59            backup.o bitvec.o btmutex.o btree.o build.o \
    57         -         callback.o complete.o ctime.o date.o dbstat.o delete.o expr.o fault.o fkey.o \
           60  +         callback.o complete.o ctime.o date.o dbstat.o delete.o expr.o \
           61  +	 fault.o fkey.o \
    58     62            fts3.o fts3_aux.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \
    59     63            fts3_snippet.o fts3_tokenizer.o fts3_tokenizer1.o \
    60     64            fts3_tokenize_vtab.o \
    61     65   	 fts3_unicode.o fts3_unicode2.o \
    62         -         fts3_write.o func.o global.o hash.o \
    63         -         icu.o insert.o journal.o legacy.o loadext.o \
           66  +         fts3_write.o fts5.o func.o global.o hash.o \
           67  +         icu.o insert.o journal.o json1.o legacy.o loadext.o \
    64     68            main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
    65     69            memjournal.o \
    66     70            mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \
    67     71            notify.o opcodes.o os.o os_unix.o os_win.o \
    68     72            pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \
    69     73            random.o resolve.o rowset.o rtree.o select.o sqlite3rbu.o status.o \
    70     74            table.o threads.o tokenize.o treeview.o trigger.o \
................................................................................
   223    227     $(TOP)/ext/rtree/rtree.h \
   224    228     $(TOP)/ext/rtree/rtree.c
   225    229   SRC += \
   226    230     $(TOP)/ext/sqlrr/sqlrr.c
   227    231   SRC += \
   228    232     $(TOP)/ext/userauth/userauth.c \
   229    233     $(TOP)/ext/userauth/sqlite3userauth.h 
   230         -
   231    234   SRC += \
   232    235     $(TOP)/ext/rbu/sqlite3rbu.c \
   233    236     $(TOP)/ext/rbu/sqlite3rbu.h
          237  +SRC += \
          238  +  $(TOP)/ext/misc/json1.c
   234    239   
   235    240   
   236    241   # FTS5 things
   237    242   #
   238    243   FTS5_HDR = \
   239    244      $(TOP)/ext/fts5/fts5.h \
   240    245      $(TOP)/ext/fts5/fts5Int.h \
................................................................................
   319    324   TESTSRC += \
   320    325     $(TOP)/ext/misc/amatch.c \
   321    326     $(TOP)/ext/misc/closure.c \
   322    327     $(TOP)/ext/misc/eval.c \
   323    328     $(TOP)/ext/misc/fileio.c \
   324    329     $(TOP)/ext/misc/fuzzer.c \
   325    330     $(TOP)/ext/misc/ieee754.c \
   326         -  $(TOP)/ext/misc/json1.c \
   327    331     $(TOP)/ext/misc/nextchar.c \
   328    332     $(TOP)/ext/misc/percentile.c \
   329    333     $(TOP)/ext/misc/regexp.c \
   330    334     $(TOP)/ext/misc/series.c \
   331    335     $(TOP)/ext/misc/spellfix.c \
   332    336     $(TOP)/ext/misc/totype.c \
   333    337     $(TOP)/ext/misc/wholenumber.c \
   334    338     $(TOP)/ext/misc/vfslog.c \
   335    339     $(TOP)/ext/fts5/fts5_tcl.c \
   336         -  $(TOP)/ext/fts5/fts5_test_mi.c \
   337         -  fts5.c
          340  +  $(TOP)/ext/fts5/fts5_test_mi.c
   338    341   
   339    342   
   340    343   #TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c
   341    344   #TESTSRC += $(TOP)/ext/fts3/fts3_tokenizer.c
   342    345   
   343    346   TESTSRC2 = \
   344    347     $(TOP)/src/attach.c \
................................................................................
   377    380     $(TOP)/src/whereexpr.c \
   378    381     parse.c \
   379    382     $(TOP)/ext/fts3/fts3.c \
   380    383     $(TOP)/ext/fts3/fts3_aux.c \
   381    384     $(TOP)/ext/fts3/fts3_expr.c \
   382    385     $(TOP)/ext/fts3/fts3_tokenizer.c \
   383    386     $(TOP)/ext/fts3/fts3_write.c \
   384         -  $(TOP)/ext/async/sqlite3async.c 
          387  +  $(TOP)/ext/async/sqlite3async.c \
          388  +  $(FTS5_SRC)
   385    389   
   386    390   # Header files used by all library source files.
   387    391   #
   388    392   HDR = \
   389    393      $(TOP)/src/btree.h \
   390    394      $(TOP)/src/btreeInt.h \
   391    395      $(TOP)/src/hash.h \
................................................................................
   434    438   #
   435    439   FUZZDATA = \
   436    440     $(TOP)/test/fuzzdata1.db \
   437    441     $(TOP)/test/fuzzdata2.db \
   438    442     $(TOP)/test/fuzzdata3.db \
   439    443     $(TOP)/test/fuzzdata4.db
   440    444   
   441         -# Extra arguments for including json1 in the build of tools
   442         -#
   443         -JSON1_DEP = $(TOP)/ext/misc/json1.c sqlite3ext.h
   444         -JSON1_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_CORE
   445         -JSON1_SRC = $(TOP)/ext/misc/json1.c
   446         -
   447    445   # Standard options to testfixture
   448    446   #
   449    447   TESTOPTS = --verbose=file --output=test-out.txt
          448  +
          449  +# Extra compiler options for various shell tools
          450  +#
          451  +SHELL_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
          452  +FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
          453  +FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1
   450    454   
   451    455   # This is the default Makefile target.  The objects listed here
   452    456   # are what get build when you type just "make" with no arguments.
   453    457   #
   454    458   all:	sqlite3.h libsqlite3.a sqlite3$(EXE)
   455    459   
   456    460   libsqlite3.a:	$(LIBOBJ)
   457    461   	$(AR) libsqlite3.a $(LIBOBJ)
   458    462   	$(RANLIB) libsqlite3.a
   459    463   
   460         -sqlite3$(EXE):	$(TOP)/src/shell.c libsqlite3.a sqlite3.h $(JSON1_DEP)
   461         -	$(TCCX) $(READLINE_FLAGS) $(JSON1_OPT) -o sqlite3$(EXE)  \
   462         -		$(TOP)/src/shell.c $(JSON1_SRC) \
   463         -		libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB)
          464  +sqlite3$(EXE):	$(TOP)/src/shell.c libsqlite3.a sqlite3.h
          465  +	$(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE) $(SHELL_OPT) \
          466  +		$(TOP)/src/shell.c libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB)
   464    467   
   465    468   sqldiff$(EXE):	$(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
   466    469   	$(TCCX) -o sqldiff$(EXE) -DSQLITE_THREADSAFE=0 \
   467    470   		$(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) $(THREADLIB)
   468    471   
   469         -fuzzershell$(EXE):	$(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h $(JSON1_DEP)
          472  +fuzzershell$(EXE):	$(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
   470    473   	$(TCCX) -o fuzzershell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
   471         -	  $(JSON1_OPT)	$(TOP)/tool/fuzzershell.c $(JSON1_SRC) sqlite3.c \
          474  +	  $(FUZZERSHELL_OPT) $(TOP)/tool/fuzzershell.c sqlite3.c \
   472    475   	  $(TLIBS) $(THREADLIB)
   473    476   
   474         -fuzzcheck$(EXE):	$(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h $(JSON1_DEP)
          477  +fuzzcheck$(EXE):	$(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h
   475    478   	$(TCCX) -o fuzzcheck$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
   476         -		-DSQLITE_ENABLE_MEMSYS5 $(JSON1_OPT) \
   477         -		$(TOP)/test/fuzzcheck.c $(JSON1_SRC) sqlite3.c $(TLIBS) $(THREADLIB)
          479  +		-DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) \
          480  +		$(TOP)/test/fuzzcheck.c sqlite3.c $(TLIBS) $(THREADLIB)
   478    481   
   479    482   mptester$(EXE):	sqlite3.c $(TOP)/mptest/mptest.c
   480    483   	$(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
   481    484   		$(TLIBS) $(THREADLIB)
   482    485   
   483    486   MPTEST1=./mptester$(EXE) mptest.db $(TOP)/mptest/crash01.test --repeat 20
   484    487   MPTEST2=./mptester$(EXE) mptest.db $(TOP)/mptest/multiwrite01.test --repeat 20
................................................................................
   498    501   
   499    502   # This target creates a directory named "tsrc" and fills it with
   500    503   # copies of all of the C source code and header files needed to
   501    504   # build on the target system.  Some of the C source code and header
   502    505   # files are automatically generated.  This target takes care of
   503    506   # all that automatic generation.
   504    507   #
   505         -target_source:	$(SRC) $(EXTHDR) $(TOP)/tool/vdbe-compress.tcl
          508  +target_source:	$(SRC) $(EXTHDR) $(TOP)/tool/vdbe-compress.tcl fts5.c
   506    509   	rm -rf tsrc
   507    510   	mkdir tsrc
   508    511   	cp -f $(SRC) $(EXTHDR) tsrc
   509    512   	rm tsrc/sqlite.h.in tsrc/parse.y
   510    513   	tclsh $(TOP)/tool/vdbe-compress.tcl $(OPTS) <tsrc/vdbe.c >vdbe.new
   511    514   	mv vdbe.new tsrc/vdbe.c
          515  +	cp fts5.c fts5.h tsrc
   512    516   	touch target_source
   513    517   
   514    518   sqlite3.c:	target_source $(TOP)/tool/mksqlite3c.tcl
   515    519   	tclsh $(TOP)/tool/mksqlite3c.tcl
   516    520   	cp tsrc/shell.c tsrc/sqlite3ext.h .
   517    521   	echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c
   518    522   	cat sqlite3.c >>tclsqlite3.c
   519    523   	echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c
   520    524   	cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c
          525  +
          526  +sqlite3ext.h:	target_source
          527  +	cp tsrc/sqlite3ext.h .
   521    528   
   522    529   sqlite3.c-debug:	target_source $(TOP)/tool/mksqlite3c.tcl
   523    530   	tclsh $(TOP)/tool/mksqlite3c.tcl --linemacros
   524    531   	echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c
   525    532   	cat sqlite3.c >>tclsqlite3.c
   526    533   	echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c
   527    534   	echo '#line 1 "tclsqlite.c"' >>tclsqlite3.c
................................................................................
   648    655   
   649    656   fts3_unicode2.o:	$(TOP)/ext/fts3/fts3_unicode2.c $(HDR) $(EXTHDR)
   650    657   	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode2.c
   651    658   
   652    659   fts3_write.o:	$(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
   653    660   	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_write.c
   654    661   
          662  +fts5.o:	fts5.c
          663  +	$(TCCX) -DSQLITE_CORE -c fts5.c
          664  +
          665  +json1.o:	$(TOP)/ext/misc/json1.c
          666  +	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c
          667  +
   655    668   rtree.o:	$(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
   656    669   	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c
          670  +
          671  +
   657    672   
   658    673   fts5parse.c:	$(TOP)/ext/fts5/fts5parse.y lemon 
   659    674   	cp $(TOP)/ext/fts5/fts5parse.y .
   660    675   	rm -f fts5parse.h
   661    676   	./lemon $(OPTS) fts5parse.y
   662    677   
   663    678   fts5parse.h: fts5parse.c
................................................................................
   697    712   TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE 
   698    713   
   699    714   testfixture$(EXE): $(TESTSRC2) libsqlite3.a $(TESTSRC) $(TOP)/src/tclsqlite.c
   700    715   	$(TCCX) $(TCL_FLAGS) -DTCLSH=1 $(TESTFIXTURE_FLAGS)                  \
   701    716   		$(TESTSRC) $(TESTSRC2) $(TOP)/src/tclsqlite.c                \
   702    717   		-o testfixture$(EXE) $(LIBTCL) libsqlite3.a $(THREADLIB)
   703    718   
   704         -amalgamation-testfixture$(EXE): sqlite3.c fts5.c $(TESTSRC) $(TOP)/src/tclsqlite.c
          719  +amalgamation-testfixture$(EXE): sqlite3.c $(TESTSRC) $(TOP)/src/tclsqlite.c
   705    720   	$(TCCX) $(TCL_FLAGS) -DTCLSH=1 $(TESTFIXTURE_FLAGS)                  \
   706         -		$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c fts5.c           \
          721  +		$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c                  \
   707    722   		-o testfixture$(EXE) $(LIBTCL) $(THREADLIB)
   708    723   
   709    724   fts3-testfixture$(EXE): sqlite3.c fts3amal.c $(TESTSRC) $(TOP)/src/tclsqlite.c
   710    725   	$(TCCX) $(TCL_FLAGS) -DTCLSH=1 $(TESTFIXTURE_FLAGS)                  \
   711    726   	-DSQLITE_ENABLE_FTS3=1                                               \
   712    727   		$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c fts3amal.c       \
   713    728   		-o testfixture$(EXE) $(LIBTCL) $(THREADLIB)

Changes to src/btree.c.

   663    663   
   664    664     rc = saveCursorKey(pCur);
   665    665     if( rc==SQLITE_OK ){
   666    666       btreeReleaseAllCursorPages(pCur);
   667    667       pCur->eState = CURSOR_REQUIRESEEK;
   668    668     }
   669    669   
   670         -  invalidateOverflowCache(pCur);
          670  +  pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl|BTCF_AtLast);
   671    671     return rc;
   672    672   }
   673    673   
   674    674   /* Forward reference */
   675    675   static int SQLITE_NOINLINE saveCursorsOnList(BtCursor*,Pgno,BtCursor*);
   676    676   
   677    677   /*
................................................................................
  7647   7647       ** for which the pointer is stored within the content being copied.
  7648   7648       **
  7649   7649       ** It is critical that the child page be defragmented before being
  7650   7650       ** copied into the parent, because if the parent is page 1 then it will
  7651   7651       ** by smaller than the child due to the database header, and so all the
  7652   7652       ** free space needs to be up front.
  7653   7653       */
  7654         -    assert( nNew==1 );
         7654  +    assert( nNew==1 || CORRUPT_DB );
  7655   7655       rc = defragmentPage(apNew[0]);
  7656   7656       testcase( rc!=SQLITE_OK );
  7657   7657       assert( apNew[0]->nFree == 
  7658   7658           (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2)
  7659   7659         || rc!=SQLITE_OK
  7660   7660       );
  7661   7661       copyNodeContent(apNew[0], pParent, &rc);

Changes to src/build.c.

   188    188             OP_Transaction,                    /* Opcode */
   189    189             iDb,                               /* P1 */
   190    190             DbMaskTest(pParse->writeMask,iDb), /* P2 */
   191    191             pParse->cookieValue[iDb],          /* P3 */
   192    192             db->aDb[iDb].pSchema->iGeneration  /* P4 */
   193    193           );
   194    194           if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1);
          195  +        VdbeComment((v,
          196  +              "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite));
   195    197         }
   196    198   #ifndef SQLITE_OMIT_VIRTUALTABLE
   197    199         for(i=0; i<pParse->nVtabLock; i++){
   198    200           char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
   199    201           sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
   200    202         }
   201    203         pParse->nVtabLock = 0;
................................................................................
  2078   2080     DbFixer sFix;
  2079   2081     Token *pName = 0;
  2080   2082     int iDb;
  2081   2083     sqlite3 *db = pParse->db;
  2082   2084   
  2083   2085     if( pParse->nVar>0 ){
  2084   2086       sqlite3ErrorMsg(pParse, "parameters are not allowed in views");
  2085         -    sqlite3SelectDelete(db, pSelect);
  2086         -    return;
         2087  +    goto create_view_fail;
  2087   2088     }
  2088   2089     sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr);
  2089   2090     p = pParse->pNewTable;
  2090   2091     if( p==0 || pParse->nErr ) goto create_view_fail;
  2091   2092     sqlite3TwoPartName(pParse, pName1, pName2, &pName);
  2092   2093     iDb = sqlite3SchemaToIndex(db, p->pSchema);
  2093   2094     sqlite3FixInit(&sFix, pParse, iDb, "view", pName);
................................................................................
  3131   3132     }else{
  3132   3133       sortOrderMask = 0;    /* Ignore DESC */
  3133   3134     }
  3134   3135   
  3135   3136     /* Analyze the list of expressions that form the terms of the index and
  3136   3137     ** report any errors.  In the common case where the expression is exactly
  3137   3138     ** a table column, store that column in aiColumn[].  For general expressions,
  3138         -  ** populate pIndex->aColExpr and store -2 in aiColumn[].
         3139  +  ** populate pIndex->aColExpr and store XN_EXPR (-2) in aiColumn[].
  3139   3140     **
  3140   3141     ** TODO: Issue a warning if two or more columns of the index are identical.
  3141   3142     ** TODO: Issue a warning if the table primary key is used as part of the
  3142   3143     ** index key.
  3143   3144     */
  3144   3145     for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
  3145   3146       Expr *pCExpr;                  /* The i-th index expression */
................................................................................
  3160   3161           ExprList *pCopy = sqlite3ExprListDup(db, pList, 0);
  3161   3162           pIndex->aColExpr = pCopy;
  3162   3163           if( !db->mallocFailed ){
  3163   3164             assert( pCopy!=0 );
  3164   3165             pListItem = &pCopy->a[i];
  3165   3166           }
  3166   3167         }
  3167         -      j = -2;
  3168         -      pIndex->aiColumn[i] = -2;
         3168  +      j = XN_EXPR;
         3169  +      pIndex->aiColumn[i] = XN_EXPR;
  3169   3170         pIndex->uniqNotNull = 0;
  3170   3171       }else{
  3171   3172         j = pCExpr->iColumn;
  3172   3173         assert( j<=0x7fff );
  3173   3174         if( j<0 ){
  3174   3175           j = pTab->iPKey;
  3175   3176         }else if( pTab->aCol[j].notNull==0 ){
................................................................................
  3214   3215           pIndex->azColl[i] = pPk->azColl[j];
  3215   3216           pIndex->aSortOrder[i] = pPk->aSortOrder[j];
  3216   3217           i++;
  3217   3218         }
  3218   3219       }
  3219   3220       assert( i==pIndex->nColumn );
  3220   3221     }else{
  3221         -    pIndex->aiColumn[i] = -1;
         3222  +    pIndex->aiColumn[i] = XN_ROWID;
  3222   3223       pIndex->azColl[i] = "BINARY";
  3223   3224     }
  3224   3225     sqlite3DefaultRowEst(pIndex);
  3225   3226     if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex);
  3226   3227   
  3227   3228     if( pTab==pParse->pNewTable ){
  3228   3229       /* This routine has been called to create an automatic index as a

Changes to src/ctime.c.

    91     91     "ENABLE_FTS3",
    92     92   #endif
    93     93   #if SQLITE_ENABLE_FTS3_PARENTHESIS
    94     94     "ENABLE_FTS3_PARENTHESIS",
    95     95   #endif
    96     96   #if SQLITE_ENABLE_FTS4
    97     97     "ENABLE_FTS4",
           98  +#endif
           99  +#if SQLITE_ENABLE_FTS5
          100  +  "ENABLE_FTS5",
    98    101   #endif
    99    102   #if SQLITE_ENABLE_ICU
   100    103     "ENABLE_ICU",
   101    104   #endif
   102    105   #if SQLITE_ENABLE_IOTRACE
   103    106     "ENABLE_IOTRACE",
          107  +#endif
          108  +#if SQLITE_ENABLE_JSON1
          109  +  "ENABLE_JSON1",
   104    110   #endif
   105    111   #if SQLITE_ENABLE_LOAD_EXTENSION
   106    112     "ENABLE_LOAD_EXTENSION",
   107    113   #endif
   108    114   #if SQLITE_ENABLE_LOCKING_STYLE
   109    115     "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
   110    116   #endif

Changes to src/delete.c.

   407    407       **  ONEPASS_OFF:    Two-pass approach - use a FIFO for rowids/PK values.
   408    408       **  ONEPASS_SINGLE: One-pass approach - at most one row deleted.
   409    409       **  ONEPASS_MULTI:  One-pass approach - any number of rows may be deleted.
   410    410       */
   411    411       pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1);
   412    412       if( pWInfo==0 ) goto delete_from_cleanup;
   413    413       eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
   414         -    assert( IsVirtual(pTab)==0 || eOnePass==ONEPASS_OFF );
          414  +    assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI );
   415    415       assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF );
   416    416     
   417    417       /* Keep track of the number of rows to be deleted */
   418    418       if( db->flags & SQLITE_CountRows ){
   419    419         sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
   420    420       }
   421    421     
   422    422       /* Extract the rowid or primary key for the current row */
   423    423       if( pPk ){
   424    424         for(i=0; i<nPk; i++){
   425         -        assert( pPk->aiColumn[i]>=(-1) );
          425  +        assert( pPk->aiColumn[i]>=0 );
   426    426           sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur,
   427    427                                           pPk->aiColumn[i], iPk+i);
   428    428         }
   429    429         iKey = iPk;
   430    430       }else{
   431    431         iKey = pParse->nMem + 1;
   432    432         iKey = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iKey, 0);
................................................................................
   490    490       }
   491    491     
   492    492       /* Set up a loop over the rowids/primary-keys that were found in the
   493    493       ** where-clause loop above.
   494    494       */
   495    495       if( eOnePass!=ONEPASS_OFF ){
   496    496         assert( nKey==nPk );  /* OP_Found will use an unpacked key */
   497         -      if( aToOpen[iDataCur-iTabCur] ){
          497  +      if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){
   498    498           assert( pPk!=0 || pTab->pSelect!=0 );
   499    499           sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
   500    500           VdbeCoverage(v);
   501    501         }
   502    502       }else if( pPk ){
   503    503         addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v);
   504    504         sqlite3VdbeAddOp2(v, OP_RowKey, iEphCur, iKey);
................................................................................
   512    512       /* Delete the row */
   513    513   #ifndef SQLITE_OMIT_VIRTUALTABLE
   514    514       if( IsVirtual(pTab) ){
   515    515         const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
   516    516         sqlite3VtabMakeWritable(pParse, pTab);
   517    517         sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB);
   518    518         sqlite3VdbeChangeP5(v, OE_Abort);
          519  +      assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE );
   519    520         sqlite3MayAbort(pParse);
          521  +      if( eOnePass==ONEPASS_SINGLE && sqlite3IsToplevel(pParse) ){
          522  +        pParse->isMultiWrite = 0;
          523  +      }
   520    524       }else
   521    525   #endif
   522    526       {
   523    527         int count = (pParse->nested==0);    /* True to count changes */
   524    528         int iIdxNoSeek = -1;
   525    529         if( bComplex==0 && aiCurOnePass[1]!=iDataCur ){
   526    530           iIdxNoSeek = aiCurOnePass[1];
................................................................................
   850    854     }
   851    855     nCol = (prefixOnly && pIdx->uniqNotNull) ? pIdx->nKeyCol : pIdx->nColumn;
   852    856     regBase = sqlite3GetTempRange(pParse, nCol);
   853    857     if( pPrior && (regBase!=regPrior || pPrior->pPartIdxWhere) ) pPrior = 0;
   854    858     for(j=0; j<nCol; j++){
   855    859       if( pPrior
   856    860        && pPrior->aiColumn[j]==pIdx->aiColumn[j]
   857         -     && pPrior->aiColumn[j]>=(-1)
          861  +     && pPrior->aiColumn[j]!=XN_EXPR
   858    862       ){
   859    863         /* This column was already computed by the previous index */
   860    864         continue;
   861    865       }
   862    866       sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iDataCur, j, regBase+j);
   863    867       /* If the column affinity is REAL but the number is an integer, then it
   864    868       ** might be stored in the table as an integer (using a compact

Changes to src/expr.c.

  2439   2439     Parse *pParse,  /* The parsing context */
  2440   2440     Index *pIdx,    /* The index whose column is to be loaded */
  2441   2441     int iTabCur,    /* Cursor pointing to a table row */
  2442   2442     int iIdxCol,    /* The column of the index to be loaded */
  2443   2443     int regOut      /* Store the index column value in this register */
  2444   2444   ){
  2445   2445     i16 iTabCol = pIdx->aiColumn[iIdxCol];
  2446         -  if( iTabCol>=(-1) ){
         2446  +  if( iTabCol==XN_EXPR ){
         2447  +    assert( pIdx->aColExpr );
         2448  +    assert( pIdx->aColExpr->nExpr>iIdxCol );
         2449  +    pParse->iSelfTab = iTabCur;
         2450  +    sqlite3ExprCode(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut);
         2451  +  }else{
  2447   2452       sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable, iTabCur,
  2448   2453                                       iTabCol, regOut);
  2449         -    return;
  2450   2454     }
  2451         -  assert( pIdx->aColExpr );
  2452         -  assert( pIdx->aColExpr->nExpr>iIdxCol );
  2453         -  pParse->iSelfTab = iTabCur;
  2454         -  sqlite3ExprCode(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut);
  2455   2455   }
  2456   2456   
  2457   2457   /*
  2458   2458   ** Generate code to extract the value of the iCol-th column of a table.
  2459   2459   */
  2460   2460   void sqlite3ExprCodeGetColumnOfTable(
  2461   2461     Vdbe *v,        /* The VDBE under construction */

Changes to src/fkey.c.

   248    248           ** the default collation sequences for each column. */
   249    249           int i, j;
   250    250           for(i=0; i<nCol; i++){
   251    251             i16 iCol = pIdx->aiColumn[i];     /* Index of column in parent tbl */
   252    252             char *zDfltColl;                  /* Def. collation for column */
   253    253             char *zIdxCol;                    /* Name of indexed column */
   254    254   
          255  +          if( iCol<0 ) break; /* No foreign keys against expression indexes */
          256  +
   255    257             /* If the index uses a collation sequence that is different from
   256    258             ** the default collation sequence for the column, this index is
   257    259             ** unusable. Bail out early in this case.  */
   258    260             zDfltColl = pParent->aCol[iCol].zColl;
   259    261             if( !zDfltColl ){
   260    262               zDfltColl = "BINARY";
   261    263             }
................................................................................
   400    402         ** none of the child key values are).
   401    403         */
   402    404         if( pTab==pFKey->pFrom && nIncr==1 ){
   403    405           int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1;
   404    406           for(i=0; i<nCol; i++){
   405    407             int iChild = aiCol[i]+1+regData;
   406    408             int iParent = pIdx->aiColumn[i]+1+regData;
          409  +          assert( pIdx->aiColumn[i]>=0 );
   407    410             assert( aiCol[i]!=pTab->iPKey );
   408    411             if( pIdx->aiColumn[i]==pTab->iPKey ){
   409    412               /* The parent key is a composite key that includes the IPK column */
   410    413               iParent = regData;
   411    414             }
   412    415             sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent); VdbeCoverage(v);
   413    416             sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
................................................................................
   608    611         pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight, 0);
   609    612       }else{
   610    613         Expr *pEq, *pAll = 0;
   611    614         Index *pPk = sqlite3PrimaryKeyIndex(pTab);
   612    615         assert( pIdx!=0 );
   613    616         for(i=0; i<pPk->nKeyCol; i++){
   614    617           i16 iCol = pIdx->aiColumn[i];
          618  +        assert( iCol>=0 );
   615    619           pLeft = exprTableRegister(pParse, pTab, regData, iCol);
   616    620           pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol);
   617    621           pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0);
   618    622           pAll = sqlite3ExprAnd(db, pAll, pEq);
   619    623         }
   620    624         pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0, 0);
   621    625       }
................................................................................
   927    931         iCol = pFKey->aCol[0].iFrom;
   928    932         aiCol = &iCol;
   929    933       }
   930    934       for(i=0; i<pFKey->nCol; i++){
   931    935         if( aiCol[i]==pTab->iPKey ){
   932    936           aiCol[i] = -1;
   933    937         }
          938  +      assert( pIdx==0 || pIdx->aiColumn[i]>=0 );
   934    939   #ifndef SQLITE_OMIT_AUTHORIZATION
   935    940         /* Request permission to read the parent key columns. If the 
   936    941         ** authorization callback returns SQLITE_IGNORE, behave as if any
   937    942         ** values read from the parent table are NULL. */
   938    943         if( db->xAuth ){
   939    944           int rcauth;
   940    945           char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName;
................................................................................
  1058   1063       for(p=pTab->pFKey; p; p=p->pNextFrom){
  1059   1064         for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom);
  1060   1065       }
  1061   1066       for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
  1062   1067         Index *pIdx = 0;
  1063   1068         sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
  1064   1069         if( pIdx ){
  1065         -        for(i=0; i<pIdx->nKeyCol; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
         1070  +        for(i=0; i<pIdx->nKeyCol; i++){
         1071  +          assert( pIdx->aiColumn[i]>=0 );
         1072  +          mask |= COLUMN_MASK(pIdx->aiColumn[i]);
         1073  +        }
  1066   1074         }
  1067   1075       }
  1068   1076     }
  1069   1077     return mask;
  1070   1078   }
  1071   1079   
  1072   1080   
................................................................................
  1181   1189         Token tToCol;               /* Name of column in parent table */
  1182   1190         int iFromCol;               /* Idx of column in child table */
  1183   1191         Expr *pEq;                  /* tFromCol = OLD.tToCol */
  1184   1192   
  1185   1193         iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
  1186   1194         assert( iFromCol>=0 );
  1187   1195         assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) );
         1196  +      assert( pIdx==0 || pIdx->aiColumn[i]>=0 );
  1188   1197         tToCol.z = pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName;
  1189   1198         tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName;
  1190   1199   
  1191   1200         tToCol.n = sqlite3Strlen30(tToCol.z);
  1192   1201         tFromCol.n = sqlite3Strlen30(tFromCol.z);
  1193   1202   
  1194   1203         /* Create the expression "OLD.zToCol = zFromCol". It is important

Changes to src/insert.c.

    86     86         db->mallocFailed = 1;
    87     87         return 0;
    88     88       }
    89     89       for(n=0; n<pIdx->nColumn; n++){
    90     90         i16 x = pIdx->aiColumn[n];
    91     91         if( x>=0 ){
    92     92           pIdx->zColAff[n] = pTab->aCol[x].affinity;
    93         -      }else if( x==(-1) ){
           93  +      }else if( x==XN_ROWID ){
    94     94           pIdx->zColAff[n] = SQLITE_AFF_INTEGER;
    95     95         }else{
    96     96           char aff;
    97         -        assert( x==(-2) );
           97  +        assert( x==XN_EXPR );
    98     98           assert( pIdx->aColExpr!=0 );
    99     99           aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr);
   100    100           if( aff==0 ) aff = SQLITE_AFF_BLOB;
   101    101           pIdx->zColAff[n] = aff;
   102    102         }
   103    103       }
   104    104       pIdx->zColAff[n] = 0;
................................................................................
   256    256     int memId;                 /* Register holding max rowid */
   257    257     int addr;                  /* A VDBE address */
   258    258     Vdbe *v = pParse->pVdbe;   /* VDBE under construction */
   259    259   
   260    260     /* This routine is never called during trigger-generation.  It is
   261    261     ** only called from the top-level */
   262    262     assert( pParse->pTriggerTab==0 );
   263         -  assert( pParse==sqlite3ParseToplevel(pParse) );
          263  +  assert( sqlite3IsToplevel(pParse) );
   264    264   
   265    265     assert( v );   /* We failed long ago if this is not so */
   266    266     for(p = pParse->pAinc; p; p = p->pNext){
   267    267       pDb = &db->aDb[p->iDb];
   268    268       memId = p->regCtr;
   269    269       assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) );
   270    270       sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead);
................................................................................
  1404   1404       /* Create a record for this index entry as it should appear after
  1405   1405       ** the insert or update.  Store that record in the aRegIdx[ix] register
  1406   1406       */
  1407   1407       regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn);
  1408   1408       for(i=0; i<pIdx->nColumn; i++){
  1409   1409         int iField = pIdx->aiColumn[i];
  1410   1410         int x;
  1411         -      if( iField==(-2) ){
         1411  +      if( iField==XN_EXPR ){
  1412   1412           pParse->ckBase = regNewData+1;
  1413   1413           sqlite3ExprCode(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i);
  1414   1414           pParse->ckBase = 0;
  1415   1415           VdbeComment((v, "%s column %d", pIdx->zName, i));
  1416   1416         }else{
  1417         -        if( iField==(-1) || iField==pTab->iPKey ){
         1417  +        if( iField==XN_ROWID || iField==pTab->iPKey ){
  1418   1418             if( regRowid==regIdx+i ) continue; /* ROWID already in regIdx+i */
  1419   1419             x = regNewData;
  1420   1420             regRowid =  pIdx->pPartIdxWhere ? -1 : regIdx+i;
  1421   1421           }else{
  1422   1422             x = iField + regNewData + 1;
  1423   1423           }
  1424   1424           sqlite3VdbeAddOp2(v, OP_SCopy, x, regIdx+i);
................................................................................
  1469   1469           }
  1470   1470         }else{
  1471   1471           int x;
  1472   1472           /* Extract the PRIMARY KEY from the end of the index entry and
  1473   1473           ** store it in registers regR..regR+nPk-1 */
  1474   1474           if( pIdx!=pPk ){
  1475   1475             for(i=0; i<pPk->nKeyCol; i++){
         1476  +            assert( pPk->aiColumn[i]>=0 );
  1476   1477               x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]);
  1477   1478               sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i);
  1478   1479               VdbeComment((v, "%s.%s", pTab->zName,
  1479   1480                            pTab->aCol[pPk->aiColumn[i]].zName));
  1480   1481             }
  1481   1482           }
  1482   1483           if( isUpdate ){
................................................................................
  1490   1491             int addrJump = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol;
  1491   1492             int op = OP_Ne;
  1492   1493             int regCmp = (IsPrimaryKeyIndex(pIdx) ? regIdx : regR);
  1493   1494     
  1494   1495             for(i=0; i<pPk->nKeyCol; i++){
  1495   1496               char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]);
  1496   1497               x = pPk->aiColumn[i];
         1498  +            assert( x>=0 );
  1497   1499               if( i==(pPk->nKeyCol-1) ){
  1498   1500                 addrJump = addrUniqueOk;
  1499   1501                 op = OP_Eq;
  1500   1502               }
  1501   1503               sqlite3VdbeAddOp4(v, op, 
  1502   1504                   regOldData+1+x, addrJump, regCmp+i, p4, P4_COLLSEQ
  1503   1505               );
................................................................................
  1741   1743     if( pDest->onError!=pSrc->onError ){
  1742   1744       return 0;   /* Different conflict resolution strategies */
  1743   1745     }
  1744   1746     for(i=0; i<pSrc->nKeyCol; i++){
  1745   1747       if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){
  1746   1748         return 0;   /* Different columns indexed */
  1747   1749       }
  1748         -    if( pSrc->aiColumn[i]==(-2) ){
         1750  +    if( pSrc->aiColumn[i]==XN_EXPR ){
  1749   1751         assert( pSrc->aColExpr!=0 && pDest->aColExpr!=0 );
  1750   1752         if( sqlite3ExprCompare(pSrc->aColExpr->a[i].pExpr,
  1751   1753                                pDest->aColExpr->a[i].pExpr, -1)!=0 ){
  1752   1754           return 0;   /* Different expressions in the index */
  1753   1755         }
  1754   1756       }
  1755   1757       if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){

Changes to src/main.c.

    24     24   #endif
    25     25   #ifdef SQLITE_ENABLE_RTREE
    26     26   # include "rtree.h"
    27     27   #endif
    28     28   #ifdef SQLITE_ENABLE_ICU
    29     29   # include "sqliteicu.h"
    30     30   #endif
           31  +#ifdef SQLITE_ENABLE_JSON1
           32  +int sqlite3Json1Init(sqlite3*);
           33  +#endif
           34  +#ifdef SQLITE_ENABLE_FTS5
           35  +int sqlite3Fts5Init(sqlite3*);
           36  +#endif
    31     37   
    32     38   #ifndef SQLITE_AMALGAMATION
    33     39   /* IMPLEMENTATION-OF: R-46656-45156 The sqlite3_version[] string constant
    34     40   ** contains the text of SQLITE_VERSION macro. 
    35     41   */
    36     42   const char sqlite3_version[] = SQLITE_VERSION;
    37     43   #endif
................................................................................
  2964   2970   #ifdef SQLITE_ENABLE_FTS2
  2965   2971     if( !db->mallocFailed && rc==SQLITE_OK ){
  2966   2972       extern int sqlite3Fts2Init(sqlite3*);
  2967   2973       rc = sqlite3Fts2Init(db);
  2968   2974     }
  2969   2975   #endif
  2970   2976   
  2971         -#ifdef SQLITE_ENABLE_FTS3
         2977  +#ifdef SQLITE_ENABLE_FTS3 /* automatically defined by SQLITE_ENABLE_FTS4 */
  2972   2978     if( !db->mallocFailed && rc==SQLITE_OK ){
  2973   2979       rc = sqlite3Fts3Init(db);
  2974   2980     }
  2975   2981   #endif
         2982  +
         2983  +#ifdef SQLITE_ENABLE_FTS5
         2984  +  if( !db->mallocFailed && rc==SQLITE_OK ){
         2985  +    rc = sqlite3Fts5Init(db);
         2986  +  }
         2987  +#endif
  2976   2988   
  2977   2989   #ifdef SQLITE_ENABLE_ICU
  2978   2990     if( !db->mallocFailed && rc==SQLITE_OK ){
  2979   2991       rc = sqlite3IcuInit(db);
  2980   2992     }
  2981   2993   #endif
  2982   2994   
................................................................................
  2987   2999   #endif
  2988   3000   
  2989   3001   #ifdef SQLITE_ENABLE_DBSTAT_VTAB
  2990   3002     if( !db->mallocFailed && rc==SQLITE_OK){
  2991   3003       rc = sqlite3DbstatRegister(db);
  2992   3004     }
  2993   3005   #endif
         3006  +
         3007  +#ifdef SQLITE_ENABLE_JSON1
         3008  +  if( !db->mallocFailed && rc==SQLITE_OK){
         3009  +    rc = sqlite3Json1Init(db);
         3010  +  }
         3011  +#endif
  2994   3012   
  2995   3013     /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking
  2996   3014     ** mode.  -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking
  2997   3015     ** mode.  Doing nothing at all also makes NORMAL the default.
  2998   3016     */
  2999   3017   #ifdef SQLITE_DEFAULT_LOCKING_MODE
  3000   3018     db->dfltLockMode = SQLITE_DEFAULT_LOCKING_MODE;

Changes to src/mutex_unix.c.

    77     77   }
    78     78   static int pthreadMutexNotheld(sqlite3_mutex *p){
    79     79     return p->nRef==0 || pthread_equal(p->owner, pthread_self())==0;
    80     80   }
    81     81   #endif
    82     82   
    83     83   /*
    84         -** Try to provide a memory barrier operation, needed for initialization only.
           84  +** Try to provide a memory barrier operation, needed for initialization
           85  +** and also for the implementation of xShmBarrier in the VFS in cases
           86  +** where SQLite is compiled without mutexes.
    85     87   */
    86     88   void sqlite3MemoryBarrier(void){
    87     89   #if defined(SQLITE_MEMORY_BARRIER)
    88     90     SQLITE_MEMORY_BARRIER;
    89     91   #elif defined(__GNUC__) && GCC_VERSION>=4001000
    90     92     __sync_synchronize();
    91     93   #endif

Changes to src/mutex_w32.c.

    74     74   static int winMutexNotheld(sqlite3_mutex *p){
    75     75     DWORD tid = GetCurrentThreadId();
    76     76     return winMutexNotheld2(p, tid);
    77     77   }
    78     78   #endif
    79     79   
    80     80   /*
    81         -** Try to provide a memory barrier operation, needed for initialization only.
           81  +** Try to provide a memory barrier operation, needed for initialization
           82  +** and also for the xShmBarrier method of the VFS in cases when SQLite is
           83  +** compiled without mutexes (SQLITE_THREADSAFE=0).
    82     84   */
    83     85   void sqlite3MemoryBarrier(void){
    84     86   #if defined(SQLITE_MEMORY_BARRIER)
    85     87     SQLITE_MEMORY_BARRIER;
    86     88   #elif defined(__GNUC__)
    87     89     __sync_synchronize();
    88         -#else
           90  +#elif !defined(SQLITE_DISABLE_INTRINSIC) && \
           91  +      defined(_MSC_VER) && _MSC_VER>=1300
           92  +  _ReadWriteBarrier();
           93  +#elif defined(MemoryBarrier)
    89     94     MemoryBarrier();
    90     95   #endif
    91     96   }
    92     97   
    93     98   /*
    94     99   ** Initialize and deinitialize the mutex subsystem.
    95    100   */

Changes to src/pragma.c.

  1374   1374   
  1375   1375       /* Code that appears at the end of the integrity check.  If no error
  1376   1376       ** messages have been generated, output OK.  Otherwise output the
  1377   1377       ** error message
  1378   1378       */
  1379   1379       static const int iLn = VDBE_OFFSET_LINENO(2);
  1380   1380       static const VdbeOpList endCode[] = {
  1381         -      { OP_IfNeg,       1, 0,        0},    /* 0 */
  1382         -      { OP_String8,     0, 3,        0},    /* 1 */
         1381  +      { OP_AddImm,      1, 0,        0},    /* 0 */
         1382  +      { OP_If,          1, 0,        0},    /* 1 */
         1383  +      { OP_String8,     0, 3,        0},    /* 2 */
  1383   1384         { OP_ResultRow,   3, 1,        0},
  1384   1385       };
  1385   1386   
  1386   1387       int isQuick = (sqlite3Tolower(zLeft[0])=='q');
  1387   1388   
  1388   1389       /* If the PRAGMA command was of the form "PRAGMA <db>.integrity_check",
  1389   1390       ** then iDb is set to the index of the database identified by <db>.
................................................................................
  1537   1538             ** or (2) the next entry has a different key */
  1538   1539             if( IsUniqueIndex(pIdx) ){
  1539   1540               int uniqOk = sqlite3VdbeMakeLabel(v);
  1540   1541               int jmp6;
  1541   1542               int kk;
  1542   1543               for(kk=0; kk<pIdx->nKeyCol; kk++){
  1543   1544                 int iCol = pIdx->aiColumn[kk];
  1544         -              assert( iCol>=0 && iCol<pTab->nCol );
  1545         -              if( pTab->aCol[iCol].notNull ) continue;
         1545  +              assert( iCol!=XN_ROWID && iCol<pTab->nCol );
         1546  +              if( iCol>=0 && pTab->aCol[iCol].notNull ) continue;
  1546   1547                 sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk);
  1547   1548                 VdbeCoverage(v);
  1548   1549               }
  1549   1550               jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v);
  1550   1551               sqlite3VdbeGoto(v, uniqOk);
  1551   1552               sqlite3VdbeJumpHere(v, jmp6);
  1552   1553               sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1,
................................................................................
  1576   1577             sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7);
  1577   1578             sqlite3VdbeAddOp2(v, OP_ResultRow, 7, 1);
  1578   1579           }
  1579   1580   #endif /* SQLITE_OMIT_BTREECOUNT */
  1580   1581         } 
  1581   1582       }
  1582   1583       addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
  1583         -    sqlite3VdbeChangeP3(v, addr, -mxErr);
  1584         -    sqlite3VdbeJumpHere(v, addr);
  1585         -    sqlite3VdbeChangeP4(v, addr+1, "ok", P4_STATIC);
         1584  +    sqlite3VdbeChangeP2(v, addr, -mxErr);
         1585  +    sqlite3VdbeJumpHere(v, addr+1);
         1586  +    sqlite3VdbeChangeP4(v, addr+2, "ok", P4_STATIC);
  1586   1587     }
  1587   1588     break;
  1588   1589   #endif /* SQLITE_OMIT_INTEGRITY_CHECK */
  1589   1590   
  1590   1591   #ifndef SQLITE_OMIT_UTF16
  1591   1592     /*
  1592   1593     **   PRAGMA encoding

Changes to src/select.c.

   575    575       int addr;
   576    576       int iLimit;
   577    577       if( pSelect->iOffset ){
   578    578         iLimit = pSelect->iOffset+1;
   579    579       }else{
   580    580         iLimit = pSelect->iLimit;
   581    581       }
   582         -    addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, -1); VdbeCoverage(v);
          582  +    addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, 1); VdbeCoverage(v);
   583    583       sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
   584    584       sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor);
   585    585       sqlite3VdbeJumpHere(v, addr);
   586    586     }
   587    587   }
   588    588   
   589    589   /*
................................................................................
   591    591   */
   592    592   static void codeOffset(
   593    593     Vdbe *v,          /* Generate code into this VM */
   594    594     int iOffset,      /* Register holding the offset counter */
   595    595     int iContinue     /* Jump here to skip the current record */
   596    596   ){
   597    597     if( iOffset>0 ){
   598         -    int addr;
   599         -    addr = sqlite3VdbeAddOp3(v, OP_IfNeg, iOffset, 0, -1); VdbeCoverage(v);
   600         -    sqlite3VdbeGoto(v, iContinue);
   601         -    VdbeComment((v, "skip OFFSET records"));
   602         -    sqlite3VdbeJumpHere(v, addr);
          598  +    sqlite3VdbeAddOp3(v, OP_IfPos, iOffset, iContinue, 1); VdbeCoverage(v);
          599  +    VdbeComment((v, "OFFSET"));
   603    600     }
   604    601   }
   605    602   
   606    603   /*
   607    604   ** Add code that will check to make sure the N registers starting at iMem
   608    605   ** form a distinct entry.  iTab is a sorting index that holds previously
   609    606   ** seen combinations of the N values.  A new entry is made in iTab
................................................................................
  1811   1808   ** the reuse of the same limit and offset registers across multiple
  1812   1809   ** SELECT statements.
  1813   1810   */
  1814   1811   static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
  1815   1812     Vdbe *v = 0;
  1816   1813     int iLimit = 0;
  1817   1814     int iOffset;
  1818         -  int addr1, n;
         1815  +  int n;
  1819   1816     if( p->iLimit ) return;
  1820   1817   
  1821   1818     /* 
  1822   1819     ** "LIMIT -1" always shows all rows.  There is some
  1823   1820     ** controversy about what the correct behavior should be.
  1824   1821     ** The current implementation interprets "LIMIT 0" to mean
  1825   1822     ** no rows.
................................................................................
  1846   1843       }
  1847   1844       if( p->pOffset ){
  1848   1845         p->iOffset = iOffset = ++pParse->nMem;
  1849   1846         pParse->nMem++;   /* Allocate an extra register for limit+offset */
  1850   1847         sqlite3ExprCode(pParse, p->pOffset, iOffset);
  1851   1848         sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v);
  1852   1849         VdbeComment((v, "OFFSET counter"));
  1853         -      addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset); VdbeCoverage(v);
  1854         -      sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset);
  1855         -      sqlite3VdbeJumpHere(v, addr1);
         1850  +      sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iOffset, iOffset, 0);
  1856   1851         sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1);
  1857   1852         VdbeComment((v, "LIMIT+OFFSET"));
  1858         -      addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit); VdbeCoverage(v);
  1859         -      sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset+1);
  1860         -      sqlite3VdbeJumpHere(v, addr1);
         1853  +      sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iLimit, iOffset+1, -1);
  1861   1854       }
  1862   1855     }
  1863   1856   }
  1864   1857   
  1865   1858   #ifndef SQLITE_OMIT_COMPOUND_SELECT
  1866   1859   /*
  1867   1860   ** Return the appropriate collating sequence for the iCol-th column of
................................................................................
  2269   2262         }
  2270   2263         p->pPrior = 0;
  2271   2264         p->iLimit = pPrior->iLimit;
  2272   2265         p->iOffset = pPrior->iOffset;
  2273   2266         if( p->iLimit ){
  2274   2267           addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
  2275   2268           VdbeComment((v, "Jump ahead if LIMIT reached"));
         2269  +        if( p->iOffset ){
         2270  +          sqlite3VdbeAddOp3(v, OP_SetIfNotPos, p->iOffset, p->iOffset, 0);
         2271  +          sqlite3VdbeAddOp3(v, OP_Add, p->iLimit, p->iOffset, p->iOffset+1);
         2272  +          sqlite3VdbeAddOp3(v, OP_SetIfNotPos, p->iLimit, p->iOffset+1, -1);
         2273  +        }
  2276   2274         }
  2277   2275         explainSetInteger(iSub2, pParse->iNextSelectId);
  2278   2276         rc = sqlite3Select(pParse, p, &dest);
  2279   2277         testcase( rc!=SQLITE_OK );
  2280   2278         pDelete = p->pPrior;
  2281   2279         p->pPrior = pPrior;
  2282   2280         p->nSelectRow += pPrior->nSelectRow;
................................................................................
  4217   4215   
  4218   4216     /* Look up every table named in the FROM clause of the select.  If
  4219   4217     ** an entry of the FROM clause is a subquery instead of a table or view,
  4220   4218     ** then create a transient table structure to describe the subquery.
  4221   4219     */
  4222   4220     for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
  4223   4221       Table *pTab;
  4224         -    assert( pFrom->fg.isRecursive==0 || pFrom->pTab );
         4222  +    assert( pFrom->fg.isRecursive==0 || pFrom->pTab!=0 );
  4225   4223       if( pFrom->fg.isRecursive ) continue;
  4226         -    if( pFrom->pTab!=0 ){
  4227         -      /* This statement has already been prepared.  There is no need
  4228         -      ** to go further. */
  4229         -      assert( i==0 );
  4230         -#ifndef SQLITE_OMIT_CTE
  4231         -      selectPopWith(pWalker, p);
  4232         -#endif
  4233         -      return WRC_Prune;
  4234         -    }
         4224  +    assert( pFrom->pTab==0 );
  4235   4225   #ifndef SQLITE_OMIT_CTE
  4236   4226       if( withExpand(pWalker, pFrom) ) return WRC_Abort;
  4237   4227       if( pFrom->pTab ) {} else
  4238   4228   #endif
  4239   4229       if( pFrom->zName==0 ){
  4240   4230   #ifndef SQLITE_OMIT_SUBQUERY
  4241   4231         Select *pSel = pFrom->pSelect;
................................................................................
  4519   4509   static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
  4520   4510     Parse *pParse;
  4521   4511     int i;
  4522   4512     SrcList *pTabList;
  4523   4513     struct SrcList_item *pFrom;
  4524   4514   
  4525   4515     assert( p->selFlags & SF_Resolved );
  4526         -  if( (p->selFlags & SF_HasTypeInfo)==0 ){
  4527         -    p->selFlags |= SF_HasTypeInfo;
  4528         -    pParse = pWalker->pParse;
  4529         -    pTabList = p->pSrc;
  4530         -    for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
  4531         -      Table *pTab = pFrom->pTab;
  4532         -      if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){
  4533         -        /* A sub-query in the FROM clause of a SELECT */
  4534         -        Select *pSel = pFrom->pSelect;
  4535         -        if( pSel ){
  4536         -          while( pSel->pPrior ) pSel = pSel->pPrior;
  4537         -          selectAddColumnTypeAndCollation(pParse, pTab, pSel);
  4538         -        }
         4516  +  assert( (p->selFlags & SF_HasTypeInfo)==0 );
         4517  +  p->selFlags |= SF_HasTypeInfo;
         4518  +  pParse = pWalker->pParse;
         4519  +  pTabList = p->pSrc;
         4520  +  for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
         4521  +    Table *pTab = pFrom->pTab;
         4522  +    assert( pTab!=0 );
         4523  +    if( (pTab->tabFlags & TF_Ephemeral)!=0 ){
         4524  +      /* A sub-query in the FROM clause of a SELECT */
         4525  +      Select *pSel = pFrom->pSelect;
         4526  +      if( pSel ){
         4527  +        while( pSel->pPrior ) pSel = pSel->pPrior;
         4528  +        selectAddColumnTypeAndCollation(pParse, pTab, pSel);
  4539   4529         }
  4540   4530       }
  4541   4531     }
  4542   4532   }
  4543   4533   #endif
  4544   4534   
  4545   4535   
................................................................................
  4857   4847     /* Try to flatten subqueries in the FROM clause up into the main query
  4858   4848     */
  4859   4849   #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
  4860   4850     for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
  4861   4851       struct SrcList_item *pItem = &pTabList->a[i];
  4862   4852       Select *pSub = pItem->pSelect;
  4863   4853       int isAggSub;
         4854  +    Table *pTab = pItem->pTab;
  4864   4855       if( pSub==0 ) continue;
         4856  +
         4857  +    /* Catch mismatch in the declared columns of a view and the number of
         4858  +    ** columns in the SELECT on the RHS */
         4859  +    if( pTab->nCol!=pSub->pEList->nExpr ){
         4860  +      sqlite3ErrorMsg(pParse, "expected %d columns for '%s' but got %d",
         4861  +                      pTab->nCol, pTab->zName, pSub->pEList->nExpr);
         4862  +      goto select_end;
         4863  +    }
         4864  +
  4865   4865       isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
  4866   4866       if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
  4867   4867         /* This subquery can be absorbed into its parent. */
  4868   4868         if( isAggSub ){
  4869   4869           isAgg = 1;
  4870   4870           p->selFlags |= SF_Aggregate;
  4871   4871         }

Changes to src/shell.c.

  2608   2608       sqlite3_free(zSql);
  2609   2609       fprintf(p->out, "%-20s %d\n", aQuery[i].zName, val);
  2610   2610     }
  2611   2611     sqlite3_free(zSchemaTab);
  2612   2612     return 0;
  2613   2613   }
  2614   2614   
         2615  +/*
         2616  +** Print the current sqlite3_errmsg() value to stderr and return 1.
         2617  +*/
         2618  +static int shellDatabaseError(sqlite3 *db){
         2619  +  const char *zErr = sqlite3_errmsg(db);
         2620  +  fprintf(stderr, "Error: %s\n", zErr);
         2621  +  return 1;
         2622  +}
         2623  +
         2624  +/*
         2625  +** Print an out-of-memory message to stderr and return 1.
         2626  +*/
         2627  +static int shellNomemError(void){
         2628  +  fprintf(stderr, "Error: out of memory\n");
         2629  +  return 1;
         2630  +}
  2615   2631   
  2616   2632   /*
  2617   2633   ** If an input line begins with "." then invoke this routine to
  2618   2634   ** process that line.
  2619   2635   **
  2620   2636   ** Return 1 on error, 2 to exit, and 0 otherwise.
  2621   2637   */
................................................................................
  3709   3725       sqlite3_stmt *pStmt;
  3710   3726       char **azResult;
  3711   3727       int nRow, nAlloc;
  3712   3728       char *zSql = 0;
  3713   3729       int ii;
  3714   3730       open_db(p, 0);
  3715   3731       rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
  3716         -    if( rc ) return rc;
         3732  +    if( rc ) return shellDatabaseError(p->db);
         3733  +
         3734  +    /* Create an SQL statement to query for the list of tables in the
         3735  +    ** main and all attached databases where the table name matches the
         3736  +    ** LIKE pattern bound to variable "?1". */
  3717   3737       zSql = sqlite3_mprintf(
  3718   3738           "SELECT name FROM sqlite_master"
  3719   3739           " WHERE type IN ('table','view')"
  3720   3740           "   AND name NOT LIKE 'sqlite_%%'"
  3721   3741           "   AND name LIKE ?1");
  3722         -    while( sqlite3_step(pStmt)==SQLITE_ROW ){
         3742  +    while( zSql && sqlite3_step(pStmt)==SQLITE_ROW ){
  3723   3743         const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
  3724   3744         if( zDbName==0 || strcmp(zDbName,"main")==0 ) continue;
  3725   3745         if( strcmp(zDbName,"temp")==0 ){
  3726   3746           zSql = sqlite3_mprintf(
  3727   3747                    "%z UNION ALL "
  3728   3748                    "SELECT 'temp.' || name FROM sqlite_temp_master"
  3729   3749                    " WHERE type IN ('table','view')"
................................................................................
  3734   3754                    "%z UNION ALL "
  3735   3755                    "SELECT '%q.' || name FROM \"%w\".sqlite_master"
  3736   3756                    " WHERE type IN ('table','view')"
  3737   3757                    "   AND name NOT LIKE 'sqlite_%%'"
  3738   3758                    "   AND name LIKE ?1", zSql, zDbName, zDbName);
  3739   3759         }
  3740   3760       }
  3741         -    sqlite3_finalize(pStmt);
  3742         -    zSql = sqlite3_mprintf("%z ORDER BY 1", zSql);
  3743         -    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
         3761  +    rc = sqlite3_finalize(pStmt);
         3762  +    if( zSql && rc==SQLITE_OK ){
         3763  +      zSql = sqlite3_mprintf("%z ORDER BY 1", zSql);
         3764  +      if( zSql ) rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
         3765  +    }
  3744   3766       sqlite3_free(zSql);
  3745         -    if( rc ) return rc;
         3767  +    if( !zSql ) return shellNomemError();
         3768  +    if( rc ) return shellDatabaseError(p->db);
         3769  +
         3770  +    /* Run the SQL statement prepared by the above block. Store the results
         3771  +    ** as an array of nul-terminated strings in azResult[].  */
  3746   3772       nRow = nAlloc = 0;
  3747   3773       azResult = 0;
  3748   3774       if( nArg>1 ){
  3749   3775         sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
  3750   3776       }else{
  3751   3777         sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
  3752   3778       }
  3753   3779       while( sqlite3_step(pStmt)==SQLITE_ROW ){
  3754   3780         if( nRow>=nAlloc ){
  3755   3781           char **azNew;
  3756   3782           int n2 = nAlloc*2 + 10;
  3757   3783           azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
  3758   3784           if( azNew==0 ){
  3759         -          fprintf(stderr, "Error: out of memory\n");
         3785  +          rc = shellNomemError();
  3760   3786             break;
  3761   3787           }
  3762   3788           nAlloc = n2;
  3763   3789           azResult = azNew;
  3764   3790         }
  3765   3791         azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
  3766         -      if( azResult[nRow] ) nRow++;
         3792  +      if( 0==azResult[nRow] ){
         3793  +        rc = shellNomemError();
         3794  +        break;
         3795  +      }
         3796  +      nRow++;
  3767   3797       }
  3768         -    sqlite3_finalize(pStmt);        
  3769         -    if( nRow>0 ){
         3798  +    if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
         3799  +      rc = shellDatabaseError(p->db);
         3800  +    }
         3801  +
         3802  +    /* Pretty-print the contents of array azResult[] to the output */
         3803  +    if( rc==0 && nRow>0 ){
  3770   3804         int len, maxlen = 0;
  3771   3805         int i, j;
  3772   3806         int nPrintCol, nPrintRow;
  3773   3807         for(i=0; i<nRow; i++){
  3774   3808           len = strlen30(azResult[i]);
  3775   3809           if( len>maxlen ) maxlen = len;
  3776   3810         }
................................................................................
  3781   3815           for(j=i; j<nRow; j+=nPrintRow){
  3782   3816             char *zSp = j<nPrintRow ? "" : "  ";
  3783   3817             fprintf(p->out, "%s%-*s", zSp, maxlen, azResult[j] ? azResult[j]:"");
  3784   3818           }
  3785   3819           fprintf(p->out, "\n");
  3786   3820         }
  3787   3821       }
         3822  +
  3788   3823       for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
  3789   3824       sqlite3_free(azResult);
  3790   3825     }else
  3791   3826   
  3792   3827     if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){
  3793   3828       static const struct {
  3794   3829          const char *zCtrlName;   /* Name of a test-control option */
................................................................................
  4615   4650   #else
  4616   4651       fprintf(stderr,"%s: Error: no database filename specified\n", Argv0);
  4617   4652       return 1;
  4618   4653   #endif
  4619   4654     }
  4620   4655     data.out = stdout;
  4621   4656   
  4622         -#ifdef SQLITE_ENABLE_JSON1
  4623         -  {
  4624         -    extern int sqlite3_json_init(sqlite3*);
  4625         -    sqlite3_auto_extension((void(*)(void))sqlite3_json_init);
  4626         -  }
  4627         -#endif
  4628         -
  4629   4657     /* Go ahead and open the database file if it already exists.  If the
  4630   4658     ** file does not exist, delay opening it.  This prevents empty database
  4631   4659     ** files from being created if a user mistypes the database name argument
  4632   4660     ** to the sqlite command-line tool.
  4633   4661     */
  4634   4662     if( access(data.zDbFilename, 0)==0 ){
  4635   4663       open_db(&data, 0);

Changes to src/sqlite.h.in.

  4357   4357   const void *sqlite3_value_text16(sqlite3_value*);
  4358   4358   const void *sqlite3_value_text16le(sqlite3_value*);
  4359   4359   const void *sqlite3_value_text16be(sqlite3_value*);
  4360   4360   int sqlite3_value_type(sqlite3_value*);
  4361   4361   int sqlite3_value_numeric_type(sqlite3_value*);
  4362   4362   
  4363   4363   /*
  4364         -** CAPI3REF: Obtaining SQL Values
         4364  +** CAPI3REF: Finding The Subtype Of SQL Values
  4365   4365   ** METHOD: sqlite3_value
  4366   4366   **
  4367   4367   ** The sqlite3_value_subtype(V) function returns the subtype for
  4368   4368   ** an [application-defined SQL function] argument V.  The subtype
  4369   4369   ** information can be used to pass a limited amount of context from
  4370   4370   ** one SQL function to another.  Use the [sqlite3_result_subtype()]
  4371   4371   ** routine to set the subtype for the return value of an SQL function.
................................................................................
  5630   5630   ** strategy. A cost of N indicates that the cost of the strategy is similar
  5631   5631   ** to a linear scan of an SQLite table with N rows. A cost of log(N) 
  5632   5632   ** indicates that the expense of the operation is similar to that of a
  5633   5633   ** binary search on a unique indexed field of an SQLite table with N rows.
  5634   5634   **
  5635   5635   ** ^The estimatedRows value is an estimate of the number of rows that
  5636   5636   ** will be returned by the strategy.
         5637  +**
         5638  +** The xBestIndex method may optionally populate the idxFlags field with a 
         5639  +** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag -
         5640  +** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite
         5641  +** assumes that the strategy may visit at most one row. 
         5642  +**
         5643  +** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then
         5644  +** SQLite also assumes that if a call to the xUpdate() method is made as
         5645  +** part of the same statement to delete or update a virtual table row and the
         5646  +** implementation returns SQLITE_CONSTRAINT, then there is no need to rollback
         5647  +** any database changes. In other words, if the xUpdate() returns
         5648  +** SQLITE_CONSTRAINT, the database contents must be exactly as they were
         5649  +** before xUpdate was called. By contrast, if SQLITE_INDEX_SCAN_UNIQUE is not
         5650  +** set and xUpdate returns SQLITE_CONSTRAINT, any database changes made by
         5651  +** the xUpdate method are automatically rolled back by SQLite.
  5637   5652   **
  5638   5653   ** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info
  5639   5654   ** structure for SQLite version 3.8.2. If a virtual table extension is
  5640   5655   ** used with an SQLite version earlier than 3.8.2, the results of attempting 
  5641   5656   ** to read or write the estimatedRows field are undefined (but are likely 
  5642   5657   ** to included crashing the application). The estimatedRows field should
  5643   5658   ** therefore only be used if [sqlite3_libversion_number()] returns a
  5644         -** value greater than or equal to 3008002.
         5659  +** value greater than or equal to 3008002. Similarly, the idxFlags field
         5660  +** was added for version 3.8.12. It may therefore only be used if
         5661  +** sqlite3_libversion_number() returns a value greater than or equal to
         5662  +** 3008012.
  5645   5663   */
  5646   5664   struct sqlite3_index_info {
  5647   5665     /* Inputs */
  5648   5666     int nConstraint;           /* Number of entries in aConstraint */
  5649   5667     struct sqlite3_index_constraint {
  5650   5668        int iColumn;              /* Column on left-hand side of constraint */
  5651   5669        unsigned char op;         /* Constraint operator */
................................................................................
  5665   5683     int idxNum;                /* Number used to identify the index */
  5666   5684     char *idxStr;              /* String, possibly obtained from sqlite3_malloc */
  5667   5685     int needToFreeIdxStr;      /* Free idxStr using sqlite3_free() if true */
  5668   5686     int orderByConsumed;       /* True if output is already ordered */
  5669   5687     double estimatedCost;           /* Estimated cost of using this index */
  5670   5688     /* Fields below are only available in SQLite 3.8.2 and later */
  5671   5689     sqlite3_int64 estimatedRows;    /* Estimated number of rows returned */
         5690  +  /* Fields below are only available in SQLite 3.8.12 and later */
         5691  +  int idxFlags;              /* Mask of SQLITE_INDEX_SCAN_* flags */
  5672   5692   };
  5673   5693   
         5694  +/*
         5695  +** CAPI3REF: Virtual Table Scan Flags
         5696  +*/
         5697  +#define SQLITE_INDEX_SCAN_UNIQUE      1     /* Scan visits at most 1 row */
         5698  +
  5674   5699   /*
  5675   5700   ** CAPI3REF: Virtual Table Constraint Operator Codes
  5676   5701   **
  5677   5702   ** These macros defined the allowed values for the
  5678   5703   ** [sqlite3_index_info].aConstraint[].op field.  Each value represents
  5679   5704   ** an operator that is part of a constraint term in the wHERE clause of
  5680   5705   ** a query that uses a [virtual table].

Changes to src/sqliteInt.h.

   192    192   */
   193    193   #if !defined(SQLITE_DISABLE_INTRINSIC)
   194    194   #  if defined(_MSC_VER) && _MSC_VER>=1300
   195    195   #    if !defined(_WIN32_WCE)
   196    196   #      include <intrin.h>
   197    197   #      pragma intrinsic(_byteswap_ushort)
   198    198   #      pragma intrinsic(_byteswap_ulong)
          199  +#      pragma intrinsic(_ReadWriteBarrier)
   199    200   #    else
   200    201   #      include <cmnintrin.h>
   201    202   #    endif
   202    203   #  endif
   203    204   #endif
   204    205   
   205    206   /*
................................................................................
  1923   1924   
  1924   1925   /* Return true if index X is a PRIMARY KEY index */
  1925   1926   #define IsPrimaryKeyIndex(X)  ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY)
  1926   1927   
  1927   1928   /* Return true if index X is a UNIQUE index */
  1928   1929   #define IsUniqueIndex(X)      ((X)->onError!=OE_None)
  1929   1930   
         1931  +/* The Index.aiColumn[] values are normally positive integer.  But
         1932  +** there are some negative values that have special meaning:
         1933  +*/
         1934  +#define XN_ROWID     (-1)     /* Indexed column is the rowid */
         1935  +#define XN_EXPR      (-2)     /* Indexed column is an expression */
         1936  +
  1930   1937   /*
  1931   1938   ** Each sample stored in the sqlite_stat3 table is represented in memory 
  1932   1939   ** using a structure of this type.  See documentation at the top of the
  1933   1940   ** analyze.c source file for additional information.
  1934   1941   */
  1935   1942   struct IndexSample {
  1936   1943     void *p;          /* Pointer to sampled record */
................................................................................
  3510   3517                                           Select*,u8);
  3511   3518     TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8);
  3512   3519     TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*);
  3513   3520     void sqlite3DeleteTrigger(sqlite3*, Trigger*);
  3514   3521     void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
  3515   3522     u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int);
  3516   3523   # define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p))
         3524  +# define sqlite3IsToplevel(p) ((p)->pToplevel==0)
  3517   3525   #else
  3518   3526   # define sqlite3TriggersExist(B,C,D,E,F) 0
  3519   3527   # define sqlite3DeleteTrigger(A,B)
  3520   3528   # define sqlite3DropTriggerPtr(A,B)
  3521   3529   # define sqlite3UnlinkAndDeleteTrigger(A,B,C)
  3522   3530   # define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I)
  3523   3531   # define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F)
  3524   3532   # define sqlite3TriggerList(X, Y) 0
  3525   3533   # define sqlite3ParseToplevel(p) p
         3534  +# define sqlite3IsToplevel(p) 1
  3526   3535   # define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0
  3527   3536   #endif
  3528   3537   
  3529   3538   int sqlite3JoinType(Parse*, Token*, Token*, Token*);
  3530   3539   void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
  3531   3540   void sqlite3DeferForeignKey(Parse*, int);
  3532   3541   #ifndef SQLITE_OMIT_AUTHORIZATION

Changes to src/test1.c.

  6565   6565   ){
  6566   6566     extern int sqlite3_amatch_init(sqlite3*,char**,const sqlite3_api_routines*);
  6567   6567     extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*);
  6568   6568     extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*);
  6569   6569     extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*);
  6570   6570     extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*);
  6571   6571     extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*);
  6572         -  extern int sqlite3_json_init(sqlite3*,char**,const sqlite3_api_routines*);
  6573   6572     extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*);
  6574   6573     extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*);
  6575   6574     extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*);
  6576   6575     extern int sqlite3_series_init(sqlite3*,char**,const sqlite3_api_routines*);
  6577   6576     extern int sqlite3_spellfix_init(sqlite3*,char**,const sqlite3_api_routines*);
  6578   6577     extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*);
  6579   6578     extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*);
  6580         -  extern int sqlite3_fts5_init(sqlite3*,char**,const sqlite3_api_routines*);
  6581   6579     static const struct {
  6582   6580       const char *zExtName;
  6583   6581       int (*pInit)(sqlite3*,char**,const sqlite3_api_routines*);
  6584   6582     } aExtension[] = {
  6585   6583       { "amatch",                sqlite3_amatch_init               },
  6586   6584       { "closure",               sqlite3_closure_init              },
  6587   6585       { "eval",                  sqlite3_eval_init                 },
  6588         -#ifdef SQLITE_ENABLE_FTS5
  6589         -    { "fts5",                  sqlite3_fts5_init                 },
  6590         -#endif
  6591   6586       { "fileio",                sqlite3_fileio_init               },
  6592   6587       { "fuzzer",                sqlite3_fuzzer_init               },
  6593   6588       { "ieee754",               sqlite3_ieee_init                 },
  6594         -    { "json",                  sqlite3_json_init                 },
  6595   6589       { "nextchar",              sqlite3_nextchar_init             },
  6596   6590       { "percentile",            sqlite3_percentile_init           },
  6597   6591       { "regexp",                sqlite3_regexp_init               },
  6598   6592       { "series",                sqlite3_series_init               },
  6599   6593       { "spellfix",              sqlite3_spellfix_init             },
  6600   6594       { "totype",                sqlite3_totype_init               },
  6601   6595       { "wholenumber",           sqlite3_wholenumber_init          },
................................................................................
  6614   6608       for(i=0; i<ArraySize(aExtension); i++){
  6615   6609         if( strcmp(zName, aExtension[i].zExtName)==0 ) break;
  6616   6610       }
  6617   6611       if( i>=ArraySize(aExtension) ){
  6618   6612         Tcl_AppendResult(interp, "no such extension: ", zName, (char*)0);
  6619   6613         return TCL_ERROR;
  6620   6614       }
  6621         -    rc = aExtension[i].pInit(db, &zErrMsg, 0);
         6615  +    if( aExtension[i].pInit ){
         6616  +      rc = aExtension[i].pInit(db, &zErrMsg, 0);
         6617  +    }else{
         6618  +      rc = SQLITE_OK;
         6619  +    }
  6622   6620       if( rc!=SQLITE_OK || zErrMsg ){
  6623   6621         Tcl_AppendResult(interp, "initialization of ", zName, " failed: ", zErrMsg,
  6624   6622                          (char*)0);
  6625   6623         sqlite3_free(zErrMsg);
  6626   6624         return TCL_ERROR;
  6627   6625       }
  6628   6626     }

Changes to src/test_config.c.

   162    162   #endif
   163    163   
   164    164   #ifdef SQLITE_ENABLE_ATOMIC_WRITE
   165    165     Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "1", TCL_GLOBAL_ONLY);
   166    166   #else
   167    167     Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "0", TCL_GLOBAL_ONLY);
   168    168   #endif
          169  +
          170  +#ifdef SQLITE_ENABLE_JSON1
          171  +  Tcl_SetVar2(interp, "sqlite_options", "json1", "1", TCL_GLOBAL_ONLY);
          172  +#else
          173  +  Tcl_SetVar2(interp, "sqlite_options", "json1", "0", TCL_GLOBAL_ONLY);
          174  +#endif
   169    175   
   170    176   #ifdef SQLITE_OMIT_ATTACH
   171    177     Tcl_SetVar2(interp, "sqlite_options", "attach", "0", TCL_GLOBAL_ONLY);
   172    178   #else
   173    179     Tcl_SetVar2(interp, "sqlite_options", "attach", "1", TCL_GLOBAL_ONLY);
   174    180   #endif
   175    181   

Changes to src/threads.c.

    63     63   
    64     64     *ppThread = 0;
    65     65     p = sqlite3Malloc(sizeof(*p));
    66     66     if( p==0 ) return SQLITE_NOMEM;
    67     67     memset(p, 0, sizeof(*p));
    68     68     p->xTask = xTask;
    69     69     p->pIn = pIn;
           70  +  /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a 
           71  +  ** function that returns SQLITE_ERROR when passed the argument 200, that
           72  +  ** forces worker threads to run sequentially and deterministically 
           73  +  ** for testing purposes. */
    70     74     if( sqlite3FaultSim(200) ){
    71     75       rc = 1;
    72     76     }else{    
    73     77       rc = pthread_create(&p->tid, 0, xTask, pIn);
    74     78     }
    75     79     if( rc ){
    76     80       p->done = 1;
................................................................................
   147    151     SQLiteThread *p;
   148    152   
   149    153     assert( ppThread!=0 );
   150    154     assert( xTask!=0 );
   151    155     *ppThread = 0;
   152    156     p = sqlite3Malloc(sizeof(*p));
   153    157     if( p==0 ) return SQLITE_NOMEM;
   154         -  if( sqlite3GlobalConfig.bCoreMutex==0 ){
          158  +  /* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a 
          159  +  ** function that returns SQLITE_ERROR when passed the argument 200, that
          160  +  ** forces worker threads to run sequentially and deterministically 
          161  +  ** (via the sqlite3FaultSim() term of the conditional) for testing
          162  +  ** purposes. */
          163  +  if( sqlite3GlobalConfig.bCoreMutex==0 || sqlite3FaultSim(200) ){
   155    164       memset(p, 0, sizeof(*p));
   156    165     }else{
   157    166       p->xTask = xTask;
   158    167       p->pIn = pIn;
   159    168       p->tid = (void*)_beginthreadex(0, 0, sqlite3ThreadProc, p, 0, &p->id);
   160    169       if( p->tid==0 ){
   161    170         memset(p, 0, sizeof(*p));
................................................................................
   175    184   int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
   176    185     DWORD rc;
   177    186     BOOL bRc;
   178    187   
   179    188     assert( ppOut!=0 );
   180    189     if( NEVER(p==0) ) return SQLITE_NOMEM;
   181    190     if( p->xTask==0 ){
   182         -    assert( p->id==GetCurrentThreadId() );
          191  +    /* assert( p->id==GetCurrentThreadId() ); */
   183    192       rc = WAIT_OBJECT_0;
   184    193       assert( p->tid==0 );
   185    194     }else{
   186    195       assert( p->id!=0 && p->id!=GetCurrentThreadId() );
   187    196       rc = sqlite3Win32Wait((HANDLE)p->tid);
   188    197       assert( rc!=WAIT_IO_COMPLETION );
   189    198       bRc = CloseHandle((HANDLE)p->tid);

Changes to src/update.c.

   130    130     int newmask;           /* Mask of NEW.* columns accessed by BEFORE triggers */
   131    131     int iEph = 0;          /* Ephemeral table holding all primary key values */
   132    132     int nKey = 0;          /* Number of elements in regKey for WITHOUT ROWID */
   133    133     int aiCurOnePass[2];   /* The write cursors opened by WHERE_ONEPASS */
   134    134   
   135    135     /* Register Allocations */
   136    136     int regRowCount = 0;   /* A count of rows changed */
   137         -  int regOldRowid;       /* The old rowid */
   138         -  int regNewRowid;       /* The new rowid */
   139         -  int regNew;            /* Content of the NEW.* table in triggers */
          137  +  int regOldRowid = 0;   /* The old rowid */
          138  +  int regNewRowid = 0;   /* The new rowid */
          139  +  int regNew = 0;        /* Content of the NEW.* table in triggers */
   140    140     int regOld = 0;        /* Content of OLD.* table in triggers */
   141    141     int regRowSet = 0;     /* Rowset of rows to be updated */
   142    142     int regKey = 0;        /* composite PRIMARY KEY value */
   143    143   
   144    144     memset(&sContext, 0, sizeof(sContext));
   145    145     db = pParse->db;
   146    146     if( pParse->nErr || db->mallocFailed ){
................................................................................
   296    296   
   297    297     /* Begin generating code. */
   298    298     v = sqlite3GetVdbe(pParse);
   299    299     if( v==0 ) goto update_cleanup;
   300    300     if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
   301    301     sqlite3BeginWriteOperation(pParse, 1, iDb);
   302    302   
   303         -#ifndef SQLITE_OMIT_VIRTUALTABLE
   304         -  /* Virtual tables must be handled separately */
   305         -  if( IsVirtual(pTab) ){
   306         -    updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef,
   307         -                       pWhere, onError);
   308         -    pWhere = 0;
   309         -    pTabList = 0;
   310         -    goto update_cleanup;
   311         -  }
   312         -#endif
   313         -
   314    303     /* Allocate required registers. */
   315         -  regRowSet = ++pParse->nMem;
   316         -  regOldRowid = regNewRowid = ++pParse->nMem;
   317         -  if( chngPk || pTrigger || hasFK ){
   318         -    regOld = pParse->nMem + 1;
          304  +  if( !IsVirtual(pTab) ){
          305  +    regRowSet = ++pParse->nMem;
          306  +    regOldRowid = regNewRowid = ++pParse->nMem;
          307  +    if( chngPk || pTrigger || hasFK ){
          308  +      regOld = pParse->nMem + 1;
          309  +      pParse->nMem += pTab->nCol;
          310  +    }
          311  +    if( chngKey || pTrigger || hasFK ){
          312  +      regNewRowid = ++pParse->nMem;
          313  +    }
          314  +    regNew = pParse->nMem + 1;
   319    315       pParse->nMem += pTab->nCol;
   320    316     }
   321         -  if( chngKey || pTrigger || hasFK ){
   322         -    regNewRowid = ++pParse->nMem;
   323         -  }
   324         -  regNew = pParse->nMem + 1;
   325         -  pParse->nMem += pTab->nCol;
   326    317   
   327    318     /* Start the view context. */
   328    319     if( isView ){
   329    320       sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
   330    321     }
   331    322   
   332    323     /* If we are trying to update a view, realize that view into
................................................................................
   340    331   
   341    332     /* Resolve the column names in all the expressions in the
   342    333     ** WHERE clause.
   343    334     */
   344    335     if( sqlite3ResolveExprNames(&sNC, pWhere) ){
   345    336       goto update_cleanup;
   346    337     }
          338  +
          339  +#ifndef SQLITE_OMIT_VIRTUALTABLE
          340  +  /* Virtual tables must be handled separately */
          341  +  if( IsVirtual(pTab) ){
          342  +    updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef,
          343  +                       pWhere, onError);
          344  +    goto update_cleanup;
          345  +  }
          346  +#endif
   347    347   
   348    348     /* Begin the database scan
   349    349     */
   350    350     if( HasRowid(pTab) ){
   351    351       sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
   352    352       pWInfo = sqlite3WhereBegin(
   353    353           pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, iIdxCur
................................................................................
   380    380       addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk);
   381    381       sqlite3VdbeSetP4KeyInfo(pParse, pPk);
   382    382       pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, 
   383    383                                  WHERE_ONEPASS_DESIRED, iIdxCur);
   384    384       if( pWInfo==0 ) goto update_cleanup;
   385    385       okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
   386    386       for(i=0; i<nPk; i++){
   387         -      assert( pPk->aiColumn[i]>=(-1) );
          387  +      assert( pPk->aiColumn[i]>=0 );
   388    388         sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, pPk->aiColumn[i],
   389    389                                         iPk+i);
   390    390       }
   391    391       if( okOnePass ){
   392    392         sqlite3VdbeChangeToNoop(v, addrOpen);
   393    393         nKey = nPk;
   394    394         regKey = iPk;
................................................................................
   503    503     ** the database after the BEFORE triggers are fired anyway (as the trigger 
   504    504     ** may have modified them). So not loading those that are not going to
   505    505     ** be used eliminates some redundant opcodes.
   506    506     */
   507    507     newmask = sqlite3TriggerColmask(
   508    508         pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
   509    509     );
   510         -  /*sqlite3VdbeAddOp3(v, OP_Null, 0, regNew, regNew+pTab->nCol-1);*/
   511    510     for(i=0; i<pTab->nCol; i++){
   512    511       if( i==pTab->iPKey ){
   513    512         sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
   514    513       }else{
   515    514         j = aXRef[i];
   516    515         if( j>=0 ){
   517    516           sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
................................................................................
   681    680    #undef pTrigger
   682    681   #endif
   683    682   
   684    683   #ifndef SQLITE_OMIT_VIRTUALTABLE
   685    684   /*
   686    685   ** Generate code for an UPDATE of a virtual table.
   687    686   **
   688         -** The strategy is that we create an ephemeral table that contains
          687  +** There are two possible strategies - the default and the special 
          688  +** "onepass" strategy. Onepass is only used if the virtual table 
          689  +** implementation indicates that pWhere may match at most one row.
          690  +**
          691  +** The default strategy is to create an ephemeral table that contains
   689    692   ** for each row to be changed:
   690    693   **
   691    694   **   (A)  The original rowid of that row.
   692         -**   (B)  The revised rowid for the row. (note1)
          695  +**   (B)  The revised rowid for the row.
   693    696   **   (C)  The content of every column in the row.
   694    697   **
   695         -** Then we loop over this ephemeral table and for each row in
   696         -** the ephemeral table call VUpdate.
          698  +** Then loop through the contents of this ephemeral table executing a
          699  +** VUpdate for each row. When finished, drop the ephemeral table.
   697    700   **
   698         -** When finished, drop the ephemeral table.
   699         -**
   700         -** (note1) Actually, if we know in advance that (A) is always the same
   701         -** as (B) we only store (A), then duplicate (A) when pulling
   702         -** it out of the ephemeral table before calling VUpdate.
          701  +** The "onepass" strategy does not use an ephemeral table. Instead, it
          702  +** stores the same values (A, B and C above) in a register array and
          703  +** makes a single invocation of VUpdate.
   703    704   */
   704    705   static void updateVirtualTable(
   705    706     Parse *pParse,       /* The parsing context */
   706    707     SrcList *pSrc,       /* The virtual table to be modified */
   707    708     Table *pTab,         /* The virtual table */
   708    709     ExprList *pChanges,  /* The columns to change in the UPDATE statement */
   709    710     Expr *pRowid,        /* Expression used to recompute the rowid */
   710    711     int *aXRef,          /* Mapping from columns of pTab to entries in pChanges */
   711    712     Expr *pWhere,        /* WHERE clause of the UPDATE statement */
   712    713     int onError          /* ON CONFLICT strategy */
   713    714   ){
   714    715     Vdbe *v = pParse->pVdbe;  /* Virtual machine under construction */
   715         -  ExprList *pEList = 0;     /* The result set of the SELECT statement */
   716         -  Select *pSelect = 0;      /* The SELECT statement */
   717         -  Expr *pExpr;              /* Temporary expression */
   718    716     int ephemTab;             /* Table holding the result of the SELECT */
   719    717     int i;                    /* Loop counter */
   720         -  int addr;                 /* Address of top of loop */
   721         -  int iReg;                 /* First register in set passed to OP_VUpdate */
   722    718     sqlite3 *db = pParse->db; /* Database connection */
   723    719     const char *pVTab = (const char*)sqlite3GetVTable(db, pTab);
   724         -  SelectDest dest;
          720  +  WhereInfo *pWInfo;
          721  +  int nArg = 2 + pTab->nCol;      /* Number of arguments to VUpdate */
          722  +  int regArg;                     /* First register in VUpdate arg array */
          723  +  int regRec;                     /* Register in which to assemble record */
          724  +  int regRowid;                   /* Register for ephem table rowid */
          725  +  int iCsr = pSrc->a[0].iCursor;  /* Cursor used for virtual table scan */
          726  +  int aDummy[2];                  /* Unused arg for sqlite3WhereOkOnePass() */
          727  +  int bOnePass;                   /* True to use onepass strategy */
          728  +  int addr;                       /* Address of OP_OpenEphemeral */
   725    729   
   726         -  /* Construct the SELECT statement that will find the new values for
   727         -  ** all updated rows. 
   728         -  */
   729         -  pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, "_rowid_"));
   730         -  if( pRowid ){
   731         -    pEList = sqlite3ExprListAppend(pParse, pEList,
   732         -                                   sqlite3ExprDup(db, pRowid, 0));
   733         -  }
   734         -  assert( pTab->iPKey<0 );
   735         -  for(i=0; i<pTab->nCol; i++){
   736         -    if( aXRef[i]>=0 ){
   737         -      pExpr = sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0);
   738         -    }else{
   739         -      pExpr = sqlite3Expr(db, TK_ID, pTab->aCol[i].zName);
   740         -    }
   741         -    pEList = sqlite3ExprListAppend(pParse, pEList, pExpr);
   742         -  }
   743         -  pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0);
   744         -  
   745         -  /* Create the ephemeral table into which the update results will
   746         -  ** be stored.
   747         -  */
          730  +  /* Allocate nArg registers to martial the arguments to VUpdate. Then
          731  +  ** create and open the ephemeral table in which the records created from
          732  +  ** these arguments will be temporarily stored. */
   748    733     assert( v );
   749    734     ephemTab = pParse->nTab++;
          735  +  addr= sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, nArg);
          736  +  regArg = pParse->nMem + 1;
          737  +  pParse->nMem += nArg;
          738  +  regRec = ++pParse->nMem;
          739  +  regRowid = ++pParse->nMem;
   750    740   
   751         -  /* fill the ephemeral table 
   752         -  */
   753         -  sqlite3SelectDestInit(&dest, SRT_EphemTab, ephemTab);
   754         -  sqlite3Select(pParse, pSelect, &dest);
          741  +  /* Start scanning the virtual table */
          742  +  pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0,0,WHERE_ONEPASS_DESIRED,0);
          743  +  if( pWInfo==0 ) return;
   755    744   
   756         -  /* Generate code to scan the ephemeral table and call VUpdate. */
   757         -  iReg = ++pParse->nMem;
   758         -  pParse->nMem += pTab->nCol+1;
   759         -  addr = sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0); VdbeCoverage(v);
   760         -  sqlite3VdbeAddOp3(v, OP_Column,  ephemTab, 0, iReg);
   761         -  sqlite3VdbeAddOp3(v, OP_Column, ephemTab, (pRowid?1:0), iReg+1);
          745  +  /* Populate the argument registers. */
          746  +  sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg);
          747  +  if( pRowid ){
          748  +    sqlite3ExprCode(pParse, pRowid, regArg+1);
          749  +  }else{
          750  +    sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1);
          751  +  }
   762    752     for(i=0; i<pTab->nCol; i++){
   763         -    sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i+1+(pRowid!=0), iReg+2+i);
          753  +    if( aXRef[i]>=0 ){
          754  +      sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
          755  +    }else{
          756  +      sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i);
          757  +    }
          758  +  }
          759  +
          760  +  bOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy);
          761  +
          762  +  if( bOnePass ){
          763  +    /* If using the onepass strategy, no-op out the OP_OpenEphemeral coded
          764  +    ** above. Also, if this is a top-level parse (not a trigger), clear the
          765  +    ** multi-write flag so that the VM does not open a statement journal */
          766  +    sqlite3VdbeChangeToNoop(v, addr);
          767  +    if( sqlite3IsToplevel(pParse) ){
          768  +      pParse->isMultiWrite = 0;
          769  +    }
          770  +  }else{
          771  +    /* Create a record from the argument register contents and insert it into
          772  +    ** the ephemeral table. */
          773  +    sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec);
          774  +    sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid);
          775  +    sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid);
          776  +  }
          777  +
          778  +
          779  +  if( bOnePass==0 ){
          780  +    /* End the virtual table scan */
          781  +    sqlite3WhereEnd(pWInfo);
          782  +
          783  +    /* Begin scannning through the ephemeral table. */
          784  +    addr = sqlite3VdbeAddOp1(v, OP_Rewind, ephemTab); VdbeCoverage(v);
          785  +
          786  +    /* Extract arguments from the current row of the ephemeral table and 
          787  +    ** invoke the VUpdate method.  */
          788  +    for(i=0; i<nArg; i++){
          789  +      sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i, regArg+i);
          790  +    }
   764    791     }
   765    792     sqlite3VtabMakeWritable(pParse, pTab);
   766         -  sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVTab, P4_VTAB);
          793  +  sqlite3VdbeAddOp4(v, OP_VUpdate, 0, nArg, regArg, pVTab, P4_VTAB);
   767    794     sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
   768    795     sqlite3MayAbort(pParse);
   769         -  sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v);
   770         -  sqlite3VdbeJumpHere(v, addr);
   771         -  sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);
   772    796   
   773         -  /* Cleanup */
   774         -  sqlite3SelectDelete(db, pSelect);  
          797  +  /* End of the ephemeral table scan. Or, if using the onepass strategy,
          798  +  ** jump to here if the scan visited zero rows. */
          799  +  if( bOnePass==0 ){
          800  +    sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v);
          801  +    sqlite3VdbeJumpHere(v, addr);
          802  +    sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);
          803  +  }else{
          804  +    sqlite3WhereEnd(pWInfo);
          805  +  }
   775    806   }
   776    807   #endif /* SQLITE_OMIT_VIRTUALTABLE */

Changes to src/vdbe.c.

  5668   5668     if( pIn1->u.i<pIn2->u.i){
  5669   5669       pIn1->u.i = pIn2->u.i;
  5670   5670     }
  5671   5671     break;
  5672   5672   }
  5673   5673   #endif /* SQLITE_OMIT_AUTOINCREMENT */
  5674   5674   
  5675         -/* Opcode: IfPos P1 P2 * * *
  5676         -** Synopsis: if r[P1]>0 goto P2
         5675  +/* Opcode: IfPos P1 P2 P3 * *
         5676  +** Synopsis: if r[P1]>0 then r[P1]-=P3, goto P2
  5677   5677   **
  5678   5678   ** Register P1 must contain an integer.
  5679         -** If the value of register P1 is 1 or greater, jump to P2 and
  5680         -** add the literal value P3 to register P1.
         5679  +** If the value of register P1 is 1 or greater, subtract P3 from the
         5680  +** value in P1 and jump to P2.
  5681   5681   **
  5682   5682   ** If the initial value of register P1 is less than 1, then the
  5683   5683   ** value is unchanged and control passes through to the next instruction.
  5684   5684   */
  5685   5685   case OP_IfPos: {        /* jump, in1 */
  5686   5686     pIn1 = &aMem[pOp->p1];
  5687   5687     assert( pIn1->flags&MEM_Int );
  5688   5688     VdbeBranchTaken( pIn1->u.i>0, 2);
  5689         -  if( pIn1->u.i>0 ) goto jump_to_p2;
         5689  +  if( pIn1->u.i>0 ){
         5690  +    pIn1->u.i -= pOp->p3;
         5691  +    goto jump_to_p2;
         5692  +  }
  5690   5693     break;
  5691   5694   }
  5692   5695   
  5693         -/* Opcode: IfNeg P1 P2 P3 * *
  5694         -** Synopsis: r[P1]+=P3, if r[P1]<0 goto P2
         5696  +/* Opcode: SetIfNotPos P1 P2 P3 * *
         5697  +** Synopsis: if r[P1]<=0 then r[P2]=P3
  5695   5698   **
  5696         -** Register P1 must contain an integer.  Add literal P3 to the value in
  5697         -** register P1 then if the value of register P1 is less than zero, jump to P2. 
         5699  +** Register P1 must contain an integer.
         5700  +** If the value of register P1 is not positive (if it is less than 1) then
         5701  +** set the value of register P2 to be the integer P3.
  5698   5702   */
  5699         -case OP_IfNeg: {        /* jump, in1 */
         5703  +case OP_SetIfNotPos: {        /* in1, in2 */
  5700   5704     pIn1 = &aMem[pOp->p1];
  5701   5705     assert( pIn1->flags&MEM_Int );
  5702         -  pIn1->u.i += pOp->p3;
  5703         -  VdbeBranchTaken(pIn1->u.i<0, 2);
  5704         -  if( pIn1->u.i<0 ) goto jump_to_p2;
         5706  +  if( pIn1->u.i<=0 ){
         5707  +    pOut = out2Prerelease(p, pOp);
         5708  +    pOut->u.i = pOp->p3;
         5709  +  }
  5705   5710     break;
  5706   5711   }
  5707   5712   
  5708   5713   /* Opcode: IfNotZero P1 P2 P3 * *
  5709         -** Synopsis: if r[P1]!=0 then r[P1]+=P3, goto P2
         5714  +** Synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2
  5710   5715   **
  5711   5716   ** Register P1 must contain an integer.  If the content of register P1 is
  5712         -** initially nonzero, then add P3 to P1 and jump to P2.  If register P1 is
  5713         -** initially zero, leave it unchanged and fall through.
         5717  +** initially nonzero, then subtract P3 from the value in register P1 and
         5718  +** jump to P2.  If register P1 is initially zero, leave it unchanged
         5719  +** and fall through.
  5714   5720   */
  5715   5721   case OP_IfNotZero: {        /* jump, in1 */
  5716   5722     pIn1 = &aMem[pOp->p1];
  5717   5723     assert( pIn1->flags&MEM_Int );
  5718   5724     VdbeBranchTaken(pIn1->u.i<0, 2);
  5719   5725     if( pIn1->u.i ){
  5720         -     pIn1->u.i += pOp->p3;
         5726  +     pIn1->u.i -= pOp->p3;
  5721   5727        goto jump_to_p2;
  5722   5728     }
  5723   5729     break;
  5724   5730   }
  5725   5731   
  5726   5732   /* Opcode: DecrJumpZero P1 P2 * * *
  5727   5733   ** Synopsis: if (--r[P1])==0 goto P2

Changes to src/vdbeblob.c.

   244    244           }
   245    245         }
   246    246   #endif
   247    247         for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
   248    248           int j;
   249    249           for(j=0; j<pIdx->nKeyCol; j++){
   250    250             /* FIXME: Be smarter about indexes that use expressions */
   251         -          if( pIdx->aiColumn[j]==iCol || pIdx->aiColumn[j]==(-2) ){
          251  +          if( pIdx->aiColumn[j]==iCol || pIdx->aiColumn[j]==XN_EXPR ){
   252    252               zFault = "indexed";
   253    253             }
   254    254           }
   255    255         }
   256    256         if( zFault ){
   257    257           sqlite3DbFree(db, zErr);
   258    258           zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault);

Changes to src/vtab.c.

   933    933   
   934    934       /* Invoke the xBegin method. If successful, add the vtab to the 
   935    935       ** sqlite3.aVTrans[] array. */
   936    936       rc = growVTrans(db);
   937    937       if( rc==SQLITE_OK ){
   938    938         rc = pModule->xBegin(pVTab->pVtab);
   939    939         if( rc==SQLITE_OK ){
          940  +        int iSvpt = db->nStatement + db->nSavepoint;
   940    941           addToVTrans(db, pVTab);
          942  +        if( iSvpt ) rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, iSvpt-1);
   941    943         }
   942    944       }
   943    945     }
   944    946     return rc;
   945    947   }
   946    948   
   947    949   /*
................................................................................
  1139   1141   
  1140   1142   /*
  1141   1143   ** Erase the eponymous virtual table instance associated with
  1142   1144   ** virtual table module pMod, if it exists.
  1143   1145   */
  1144   1146   void sqlite3VtabEponymousTableClear(sqlite3 *db, Module *pMod){
  1145   1147     Table *pTab = pMod->pEpoTab;
  1146         -  if( (pTab = pMod->pEpoTab)!=0 ){
         1148  +  if( pTab!=0 ){
  1147   1149       sqlite3DeleteColumnNames(db, pTab);
  1148   1150       sqlite3VtabClear(db, pTab);
  1149   1151       sqlite3DbFree(db, pTab);
  1150   1152       pMod->pEpoTab = 0;
  1151   1153     }
  1152   1154   }
  1153   1155   

Changes to src/where.c.

    83     83   ** Any cursors returned will have been opened for writing.
    84     84   **
    85     85   ** aiCur[0] and aiCur[1] both get -1 if the where-clause logic is
    86     86   ** unable to use the ONEPASS optimization.
    87     87   */
    88     88   int sqlite3WhereOkOnePass(WhereInfo *pWInfo, int *aiCur){
    89     89     memcpy(aiCur, pWInfo->aiCurOnePass, sizeof(int)*2);
           90  +#ifdef WHERETRACE_ENABLED
           91  +  if( sqlite3WhereTrace && pWInfo->eOnePass!=ONEPASS_OFF ){
           92  +    sqlite3DebugPrintf("%s cursors: %d %d\n",
           93  +         pWInfo->eOnePass==ONEPASS_SINGLE ? "ONEPASS_SINGLE" : "ONEPASS_MULTI",
           94  +         aiCur[0], aiCur[1]);
           95  +  }
           96  +#endif
    90     97     return pWInfo->eOnePass;
    91     98   }
    92     99   
    93    100   /*
    94    101   ** Move the content of pSrc into pDest
    95    102   */
    96    103   static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){
................................................................................
   178    185     WhereClause *pWC;    /* Shorthand for pScan->pWC */
   179    186     WhereTerm *pTerm;    /* The term being tested */
   180    187     int k = pScan->k;    /* Where to start scanning */
   181    188   
   182    189     while( pScan->iEquiv<=pScan->nEquiv ){
   183    190       iCur = pScan->aiCur[pScan->iEquiv-1];
   184    191       iColumn = pScan->aiColumn[pScan->iEquiv-1];
   185         -    if( iColumn==(-2) && pScan->pIdxExpr==0 ) return 0;
          192  +    if( iColumn==XN_EXPR && pScan->pIdxExpr==0 ) return 0;
   186    193       while( (pWC = pScan->pWC)!=0 ){
   187    194         for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
   188    195           if( pTerm->leftCursor==iCur
   189    196            && pTerm->u.leftColumn==iColumn
   190         -         && (iColumn!=(-2)
   191         -               || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0)
          197  +         && (iColumn!=XN_EXPR
          198  +             || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0)
   192    199            && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin))
   193    200           ){
   194    201             if( (pTerm->eOperator & WO_EQUIV)!=0
   195    202              && pScan->nEquiv<ArraySize(pScan->aiCur)
   196    203              && (pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight))->op==TK_COLUMN
   197    204             ){
   198    205               int j;
................................................................................
   277    284     /* memset(pScan, 0, sizeof(*pScan)); */
   278    285     pScan->pOrigWC = pWC;
   279    286     pScan->pWC = pWC;
   280    287     pScan->pIdxExpr = 0;
   281    288     if( pIdx ){
   282    289       j = iColumn;
   283    290       iColumn = pIdx->aiColumn[j];
   284         -    if( iColumn==(-2) ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
          291  +    if( iColumn==XN_EXPR ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
   285    292     }
   286    293     if( pIdx && iColumn>=0 ){
   287    294       pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
   288    295       pScan->zCollName = pIdx->azColl[j];
   289    296     }else{
   290    297       pScan->idxaff = 0;
   291    298       pScan->zCollName = 0;
................................................................................
   716    723       for(i=BMS-1; i<pTable->nCol; i++){
   717    724         pIdx->aiColumn[n] = i;
   718    725         pIdx->azColl[n] = "BINARY";
   719    726         n++;
   720    727       }
   721    728     }
   722    729     assert( n==nKeyCol );
   723         -  pIdx->aiColumn[n] = -1;
          730  +  pIdx->aiColumn[n] = XN_ROWID;
   724    731     pIdx->azColl[n] = "BINARY";
   725    732   
   726    733     /* Create the automatic index */
   727    734     assert( pLevel->iIdxCur>=0 );
   728    735     pLevel->iIdxCur = pParse->nTab++;
   729    736     sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1);
   730    737     sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
................................................................................
  1155   1162   
  1156   1163   
  1157   1164   #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
  1158   1165   /*
  1159   1166   ** Return the affinity for a single column of an index.
  1160   1167   */
  1161   1168   static char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCol){
         1169  +  assert( iCol>=0 && iCol<pIdx->nColumn );
  1162   1170     if( !pIdx->zColAff ){
  1163   1171       if( sqlite3IndexAffinityStr(db, pIdx)==0 ) return SQLITE_AFF_BLOB;
  1164   1172     }
  1165   1173     return pIdx->zColAff[iCol];
  1166   1174   }
  1167   1175   #endif
  1168   1176   
................................................................................
  1212   1220   ){
  1213   1221     Index *p = pLoop->u.btree.pIndex;
  1214   1222     int nEq = pLoop->u.btree.nEq;
  1215   1223     sqlite3 *db = pParse->db;
  1216   1224     int nLower = -1;
  1217   1225     int nUpper = p->nSample+1;
  1218   1226     int rc = SQLITE_OK;
  1219         -  int iCol = p->aiColumn[nEq];
  1220         -  u8 aff = sqlite3IndexColumnAffinity(db, p, iCol);
         1227  +  u8 aff = sqlite3IndexColumnAffinity(db, p, nEq);
  1221   1228     CollSeq *pColl;
  1222   1229     
  1223   1230     sqlite3_value *p1 = 0;          /* Value extracted from pLower */
  1224   1231     sqlite3_value *p2 = 0;          /* Value extracted from pUpper */
  1225   1232     sqlite3_value *pVal = 0;        /* Value extracted from record */
  1226   1233   
  1227   1234     pColl = sqlite3LocateCollSeq(pParse, p->azColl[nEq]);
................................................................................
  2231   2238         assert( nIn>0 );  /* RHS always has 2 or more terms...  The parser
  2232   2239                           ** changes "x IN (?)" into "x=?". */
  2233   2240   
  2234   2241       }else if( eOp & (WO_EQ|WO_IS) ){
  2235   2242         int iCol = pProbe->aiColumn[saved_nEq];
  2236   2243         pNew->wsFlags |= WHERE_COLUMN_EQ;
  2237   2244         assert( saved_nEq==pNew->u.btree.nEq );
  2238         -      if( iCol==(-1) || (iCol>0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) ){
         2245  +      if( iCol==XN_ROWID 
         2246  +       || (iCol>0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1)
         2247  +      ){
  2239   2248           if( iCol>=0 && pProbe->uniqNotNull==0 ){
  2240   2249             pNew->wsFlags |= WHERE_UNQ_WANTED;
  2241   2250           }else{
  2242   2251             pNew->wsFlags |= WHERE_ONEROW;
  2243   2252           }
  2244   2253         }
  2245   2254       }else if( eOp & WO_ISNULL ){
................................................................................
  2417   2426   */
  2418   2427   static int indexMightHelpWithOrderBy(
  2419   2428     WhereLoopBuilder *pBuilder,
  2420   2429     Index *pIndex,
  2421   2430     int iCursor
  2422   2431   ){
  2423   2432     ExprList *pOB;
         2433  +  ExprList *aColExpr;
  2424   2434     int ii, jj;
  2425   2435   
  2426   2436     if( pIndex->bUnordered ) return 0;
  2427   2437     if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0;
  2428   2438     for(ii=0; ii<pOB->nExpr; ii++){
  2429   2439       Expr *pExpr = sqlite3ExprSkipCollate(pOB->a[ii].pExpr);
  2430         -    if( pExpr->op!=TK_COLUMN ) return 0;
  2431         -    if( pExpr->iTable==iCursor ){
         2440  +    if( pExpr->op==TK_COLUMN && pExpr->iTable==iCursor ){
  2432   2441         if( pExpr->iColumn<0 ) return 1;
  2433   2442         for(jj=0; jj<pIndex->nKeyCol; jj++){
  2434   2443           if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1;
         2444  +      }
         2445  +    }else if( (aColExpr = pIndex->aColExpr)!=0 ){
         2446  +      for(jj=0; jj<pIndex->nKeyCol; jj++){
         2447  +        if( pIndex->aiColumn[jj]!=XN_EXPR ) continue;
         2448  +        if( sqlite3ExprCompare(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){
         2449  +          return 1;
         2450  +        }
  2435   2451         }
  2436   2452       }
  2437   2453     }
  2438   2454     return 0;
  2439   2455   }
  2440   2456   
  2441   2457   /*
................................................................................
  2576   2592   #ifndef SQLITE_OMIT_AUTOMATIC_INDEX
  2577   2593     /* Automatic indexes */
  2578   2594     if( !pBuilder->pOrSet      /* Not part of an OR optimization */
  2579   2595      && (pWInfo->wctrlFlags & WHERE_NO_AUTOINDEX)==0
  2580   2596      && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
  2581   2597      && pSrc->pIBIndex==0      /* Has no INDEXED BY clause */
  2582   2598      && !pSrc->fg.notIndexed   /* Has no NOT INDEXED clause */
  2583         -   && HasRowid(pTab)         /* Is not a WITHOUT ROWID table. (FIXME: Why not?) */
         2599  +   && HasRowid(pTab)         /* Not WITHOUT ROWID table. (FIXME: Why not?) */
  2584   2600      && !pSrc->fg.isCorrelated /* Not a correlated subquery */
  2585   2601      && !pSrc->fg.isRecursive  /* Not a recursive common table expression. */
  2586   2602     ){
  2587   2603       /* Generate auto-index WhereLoops */
  2588   2604       WhereTerm *pTerm;
  2589   2605       WhereTerm *pWCEnd = pWC->a + pWC->nTerm;
  2590   2606       for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){
................................................................................
  2821   2837       if( pIdxInfo->needToFreeIdxStr ) sqlite3_free(pIdxInfo->idxStr);
  2822   2838       pIdxInfo->idxStr = 0;
  2823   2839       pIdxInfo->idxNum = 0;
  2824   2840       pIdxInfo->needToFreeIdxStr = 0;
  2825   2841       pIdxInfo->orderByConsumed = 0;
  2826   2842       pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2;
  2827   2843       pIdxInfo->estimatedRows = 25;
         2844  +    pIdxInfo->idxFlags = 0;
  2828   2845       rc = vtabBestIndex(pParse, pTab, pIdxInfo);
  2829   2846       if( rc ) goto whereLoopAddVtab_exit;
  2830   2847       pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
  2831   2848       pNew->prereq = mExtra;
  2832   2849       mxTerm = -1;
  2833   2850       assert( pNew->nLSlot>=nConstraint );
  2834   2851       for(i=0; i<nConstraint; i++) pNew->aLTerm[i] = 0;
................................................................................
  2866   2883             }
  2867   2884             /* A virtual table that is constrained by an IN clause may not
  2868   2885             ** consume the ORDER BY clause because (1) the order of IN terms
  2869   2886             ** is not necessarily related to the order of output terms and
  2870   2887             ** (2) Multiple outputs from a single IN value will not merge
  2871   2888             ** together.  */
  2872   2889             pIdxInfo->orderByConsumed = 0;
         2890  +          pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE;
  2873   2891           }
  2874   2892         }
  2875   2893       }
  2876   2894       if( i>=nConstraint ){
  2877   2895         pNew->nLTerm = mxTerm+1;
  2878   2896         assert( pNew->nLTerm<=pNew->nLSlot );
  2879   2897         pNew->u.vtab.idxNum = pIdxInfo->idxNum;
................................................................................
  2881   2899         pIdxInfo->needToFreeIdxStr = 0;
  2882   2900         pNew->u.vtab.idxStr = pIdxInfo->idxStr;
  2883   2901         pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ?
  2884   2902                                         pIdxInfo->nOrderBy : 0);
  2885   2903         pNew->rSetup = 0;
  2886   2904         pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
  2887   2905         pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows);
         2906  +
         2907  +      /* Set the WHERE_ONEROW flag if the xBestIndex() method indicated
         2908  +      ** that the scan will visit at most one row. Clear it otherwise. */
         2909  +      if( pIdxInfo->idxFlags & SQLITE_INDEX_SCAN_UNIQUE ){
         2910  +        pNew->wsFlags |= WHERE_ONEROW;
         2911  +      }else{
         2912  +        pNew->wsFlags &= ~WHERE_ONEROW;
         2913  +      }
  2888   2914         whereLoopInsert(pBuilder, pNew);
  2889   2915         if( pNew->u.vtab.needFree ){
  2890   2916           sqlite3_free(pNew->u.vtab.idxStr);
  2891   2917           pNew->u.vtab.needFree = 0;
  2892   2918         }
  2893   2919       }
  2894   2920     }  
................................................................................
  3202   3228           nColumn = 1;
  3203   3229         }else if( (pIndex = pLoop->u.btree.pIndex)==0 || pIndex->bUnordered ){
  3204   3230           return 0;
  3205   3231         }else{
  3206   3232           nKeyCol = pIndex->nKeyCol;
  3207   3233           nColumn = pIndex->nColumn;
  3208   3234           assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
  3209         -        assert( pIndex->aiColumn[nColumn-1]==(-1) || !HasRowid(pIndex->pTable));
         3235  +        assert( pIndex->aiColumn[nColumn-1]==XN_ROWID
         3236  +                          || !HasRowid(pIndex->pTable));
  3210   3237           isOrderDistinct = IsUniqueIndex(pIndex);
  3211   3238         }
  3212   3239   
  3213   3240         /* Loop through all columns of the index and deal with the ones
  3214   3241         ** that are not constrained by == or IN.
  3215   3242         */
  3216   3243         rev = revSet = 0;
................................................................................
  3234   3261           ** (revIdx) for the j-th column of the index.
  3235   3262           */
  3236   3263           if( pIndex ){
  3237   3264             iColumn = pIndex->aiColumn[j];
  3238   3265             revIdx = pIndex->aSortOrder[j];
  3239   3266             if( iColumn==pIndex->pTable->iPKey ) iColumn = -1;
  3240   3267           }else{
  3241         -          iColumn = -1;
         3268  +          iColumn = XN_ROWID;
  3242   3269             revIdx = 0;
  3243   3270           }
  3244   3271   
  3245   3272           /* An unconstrained column that might be NULL means that this
  3246   3273           ** WhereLoop is not well-ordered
  3247   3274           */
  3248   3275           if( isOrderDistinct
................................................................................
  3260   3287           isMatch = 0;
  3261   3288           for(i=0; bOnce && i<nOrderBy; i++){
  3262   3289             if( MASKBIT(i) & obSat ) continue;
  3263   3290             pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr);
  3264   3291             testcase( wctrlFlags & WHERE_GROUPBY );
  3265   3292             testcase( wctrlFlags & WHERE_DISTINCTBY );
  3266   3293             if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
  3267         -          if( pOBExpr->op!=TK_COLUMN ) continue;
  3268         -          if( pOBExpr->iTable!=iCur ) continue;
  3269         -          if( pOBExpr->iColumn!=iColumn ) continue;
         3294  +          if( iColumn>=(-1) ){
         3295  +            if( pOBExpr->op!=TK_COLUMN ) continue;
         3296  +            if( pOBExpr->iTable!=iCur ) continue;
         3297  +            if( pOBExpr->iColumn!=iColumn ) continue;
         3298  +          }else{
         3299  +            if( sqlite3ExprCompare(pOBExpr,pIndex->aColExpr->a[j].pExpr,iCur) ){
         3300  +              continue;
         3301  +            }
         3302  +          }
  3270   3303             if( iColumn>=0 ){
  3271   3304               pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
  3272   3305               if( !pColl ) pColl = db->pDfltColl;
  3273   3306               if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue;
  3274   3307             }
  3275   3308             isMatch = 1;
  3276   3309             break;
................................................................................
  4093   4126         /* Try to ORDER BY the result set to make distinct processing easier */
  4094   4127         pWInfo->wctrlFlags |= WHERE_DISTINCTBY;
  4095   4128         pWInfo->pOrderBy = pResultSet;
  4096   4129       }
  4097   4130     }
  4098   4131   
  4099   4132     /* Construct the WhereLoop objects */
  4100         -  WHERETRACE(0xffff,("*** Optimizer Start ***\n"));
         4133  +  WHERETRACE(0xffff,("*** Optimizer Start *** (wctrlFlags: 0x%x)\n",
         4134  +             wctrlFlags));
  4101   4135   #if defined(WHERETRACE_ENABLED)
  4102   4136     if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */
  4103   4137       int i;
  4104   4138       for(i=0; i<sWLB.pWC->nTerm; i++){
  4105   4139         whereTermPrint(&sWLB.pWC->a[i], i);
  4106   4140       }
  4107   4141     }
................................................................................
  4512   4546       ** reference the index.
  4513   4547       */
  4514   4548       if( pLoop->wsFlags & (WHERE_INDEXED|WHERE_IDX_ONLY) ){
  4515   4549         pIdx = pLoop->u.btree.pIndex;
  4516   4550       }else if( pLoop->wsFlags & WHERE_MULTI_OR ){
  4517   4551         pIdx = pLevel->u.pCovidx;
  4518   4552       }
  4519         -    if( pIdx && !db->mallocFailed ){
         4553  +    if( pIdx
         4554  +     && (pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable))
         4555  +     && !db->mallocFailed
         4556  +    ){
  4520   4557         last = sqlite3VdbeCurrentAddr(v);
  4521   4558         k = pLevel->addrBody;
  4522   4559         pOp = sqlite3VdbeGetOp(v, k);
  4523   4560         for(; k<last; k++, pOp++){
  4524   4561           if( pOp->p1!=pLevel->iTabCur ) continue;
  4525   4562           if( pOp->opcode==OP_Column ){
  4526   4563             int x = pOp->p2;
  4527   4564             assert( pIdx->pTable==pTab );
  4528   4565             if( !HasRowid(pTab) ){
  4529   4566               Index *pPk = sqlite3PrimaryKeyIndex(pTab);
  4530   4567               x = pPk->aiColumn[x];
         4568  +            assert( x>=0 );
  4531   4569             }
  4532   4570             x = sqlite3ColumnOfIndex(pIdx, x);
  4533   4571             if( x>=0 ){
  4534   4572               pOp->p2 = x;
  4535   4573               pOp->p1 = pLevel->iIdxCur;
  4536   4574             }
  4537   4575             assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0 );

Changes to src/wherecode.c.

    42     42   }
    43     43   
    44     44   /*
    45     45   ** Return the name of the i-th column of the pIdx index.
    46     46   */
    47     47   static const char *explainIndexColumnName(Index *pIdx, int i){
    48     48     i = pIdx->aiColumn[i];
    49         -  if( i==(-2) ) return "<expr>";
    50         -  if( i==(-1) ) return "rowid";
           49  +  if( i==XN_EXPR ) return "<expr>";
           50  +  if( i==XN_ROWID ) return "rowid";
    51     51     return pIdx->pTable->aCol[i].zName;
    52     52   }
    53     53   
    54     54   /*
    55     55   ** Argument pLevel describes a strategy for scanning table pTab. This 
    56     56   ** function appends text to pStr that describes the subset of table
    57     57   ** rows scanned by the strategy in the form of an SQL expression.
................................................................................
   510    510       pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT),
   511    511                               iIdxCur, 0, regBase, nSkip);
   512    512       VdbeCoverageIf(v, bRev==0);
   513    513       VdbeCoverageIf(v, bRev!=0);
   514    514       sqlite3VdbeJumpHere(v, j);
   515    515       for(j=0; j<nSkip; j++){
   516    516         sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, j, regBase+j);
   517         -      testcase( pIdx->aiColumn[j]==(-2) );
          517  +      testcase( pIdx->aiColumn[j]==XN_EXPR );
   518    518         VdbeComment((v, "%s", explainIndexColumnName(pIdx, j)));
   519    519       }
   520    520     }    
   521    521   
   522    522     /* Evaluate the equality constraints
   523    523     */
   524    524     assert( zAff==0 || (int)strlen(zAff)>=nEq );
................................................................................
   696    696       VdbeCoverage(v);
   697    697       pLoop->u.vtab.needFree = 0;
   698    698       for(j=0; j<nConstraint && j<16; j++){
   699    699         if( (pLoop->u.vtab.omitMask>>j)&1 ){
   700    700           disableTerm(pLevel, pLoop->aLTerm[j]);
   701    701         }
   702    702       }
   703         -    pLevel->op = OP_VNext;
   704    703       pLevel->p1 = iCur;
          704  +    pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext;
   705    705       pLevel->p2 = sqlite3VdbeCurrentAddr(v);
   706    706       sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2);
   707    707       sqlite3ExprCachePop(pParse);
   708    708     }else
   709    709   #endif /* SQLITE_OMIT_VIRTUALTABLE */
   710    710   
   711    711     if( (pLoop->wsFlags & WHERE_IPK)!=0

Changes to src/whereexpr.c.

   946    946             eExtraOp = WO_EQUIV;
   947    947           }
   948    948         }else{
   949    949           pDup = pExpr;
   950    950           pNew = pTerm;
   951    951         }
   952    952         exprCommute(pParse, pDup);
   953         -      pLeft = sqlite3ExprSkipCollate(pDup->pLeft);
   954    953         pNew->leftCursor = iCur;
   955    954         pNew->u.leftColumn = iColumn;
   956    955         testcase( (prereqLeft | extraRight) != prereqLeft );
   957    956         pNew->prereqRight = prereqLeft | extraRight;
   958    957         pNew->prereqAll = prereqAll;
   959    958         pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
   960    959       }

Changes to test/delete4.test.

    93     93   do_execsql_test 3.3 {
    94     94     SELECT i FROM t1 ORDER BY i;
    95     95   } {1 3 5 7}
    96     96   
    97     97   do_execsql_test 3.4 { 
    98     98     PRAGMA integrity_check; 
    99     99   } {ok}
          100  +
          101  +# Between 2015-09-14 and 2015-09-28, the following test cases would result
          102  +# in corruption (wrong # of entries in index) due to a bug in the ONEPASS
          103  +# optimization.
          104  +#
          105  +do_execsql_test 4.1 {
          106  +  DROP TABLE IF EXISTS t4;
          107  +  CREATE TABLE t4(col0, col1);
          108  +  INSERT INTO "t4" VALUES(14, 'abcde');
          109  +  CREATE INDEX idx_t4_0 ON t4 (col1, col0);
          110  +  CREATE INDEX idx_t4_3 ON t4 (col0);
          111  +  DELETE FROM t4 WHERE col0=69 OR col0>7;
          112  +  PRAGMA integrity_check;
          113  +} {ok}
          114  +do_execsql_test 4.2 {
          115  +  DROP TABLE IF EXISTS t4;
          116  +  CREATE TABLE t4(col0, col1);
          117  +  INSERT INTO "t4" VALUES(14, 'abcde');
          118  +  CREATE INDEX idx_t4_3 ON t4 (col0);
          119  +  CREATE INDEX idx_t4_0 ON t4 (col1, col0);
          120  +  DELETE FROM t4 WHERE col0=69 OR col0>7;
          121  +  PRAGMA integrity_check;
          122  +} {ok}
          123  +do_execsql_test 4.11 {
          124  +  DROP TABLE IF EXISTS t4;
          125  +  CREATE TABLE t4(col0, col1, pk PRIMARY KEY) WITHOUT ROWID;
          126  +  INSERT INTO t4 VALUES(14, 'abcde','xyzzy');
          127  +  CREATE INDEX idx_t4_0 ON t4 (col1, col0);
          128  +  CREATE INDEX idx_t4_3 ON t4 (col0);
          129  +  DELETE FROM t4 WHERE col0=69 OR col0>7;
          130  +  PRAGMA integrity_check;
          131  +} {ok}
          132  +do_execsql_test 4.12 {
          133  +  DROP TABLE IF EXISTS t4;
          134  +  CREATE TABLE t4(col0, col1, pk PRIMARY KEY) WITHOUT ROWID;
          135  +  INSERT INTO t4 VALUES(14, 'abcde','xyzzy');
          136  +  CREATE INDEX idx_t4_3 ON t4 (col0);
          137  +  CREATE INDEX idx_t4_0 ON t4 (col1, col0);
          138  +  DELETE FROM t4 WHERE col0=69 OR col0>7;
          139  +  PRAGMA integrity_check;
          140  +} {ok}
          141  +
          142  +
   100    143   
   101    144   
   102    145   finish_test

Changes to test/fkey1.test.

   146    146     SELECT 1, """5" FROM """4";
   147    147     DELETE FROM """1";
   148    148     SELECT 2, """5" FROM """4";
   149    149   } {1 abc}
   150    150   do_execsql_test fkey1-4.2 {
   151    151     PRAGMA table_info="""1";
   152    152   } {0 {"2} TEXT 0 {} 1 1 {"3} TEXT 0 {} 0}
          153  +
          154  +#-------------------------------------------------------------------------
          155  +#
          156  +do_execsql_test fkey1-5.1 {
          157  +  CREATE TABLE t11(
          158  +    x INTEGER PRIMARY KEY, 
          159  +    parent REFERENCES t11 ON DELETE CASCADE
          160  +  );
          161  +  INSERT INTO t11 VALUES (1, NULL), (2, 1), (3, 2);
          162  +} {}
          163  +
          164  +# The REPLACE part of this statement deletes the row (2, 1). Then the 
          165  +# DELETE CASCADE caused by deleting that row removes the (3, 2) row. Which
          166  +# would have been the parent of the new row being inserted. Causing an
          167  +# FK violation.
          168  +#
          169  +do_catchsql_test fkey1-5.2 {
          170  +  INSERT OR REPLACE INTO t11 VALUES (2, 3);
          171  +} {1 {FOREIGN KEY constraint failed}}
          172  +
          173  +# A similar test to the above.
          174  +do_execsql_test fkey1-5.3 {
          175  +  CREATE TABLE Foo (
          176  +    Id INTEGER PRIMARY KEY, 
          177  +    ParentId INTEGER REFERENCES Foo(Id) ON DELETE CASCADE, C1
          178  +  );
          179  +  INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (1, null, 'A');
          180  +  INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (2, 1, 'A-2-1');
          181  +  INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (3, 2, 'A-3-2');
          182  +  INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (4, 3, 'A-4-3');
          183  +}
          184  +do_catchsql_test fkey1-5.4 {
          185  +  INSERT OR REPLACE INTO Foo(Id, ParentId, C1) VALUES (2, 3, 'A-2-3');
          186  +} {1 {FOREIGN KEY constraint failed}}
   153    187   
   154    188   finish_test

Changes to test/fts3conf.test.

    82     82   
    83     83     6    "INSERT OR ROLLBACK $T2"   1 1 {{a b c d} {e f g h}}
    84     84     7    "INSERT OR ABORT    $T2"   1 1 {{a b c d} {e f g h} {i j k l}}
    85     85     8    "INSERT OR FAIL     $T2"   1 1 {{a b c d} {e f g h} {i j k l} z}
    86     86     9    "INSERT OR IGNORE   $T2"   1 0 {{a b c d} {e f g h} {i j k l} z}
    87     87     10   "INSERT OR REPLACE  $T2"   1 0 {{a b c d} y {i j k l} z}
    88     88   
    89         -  11   "UPDATE OR ROLLBACK $T3"   1 1 {{a b c d} {e f g h}}
    90         -  12   "UPDATE OR ABORT    $T3"   1 1 {{a b c d} {e f g h} {i j k l}}
    91         -  13   "UPDATE OR FAIL     $T3"   1 1 {{a b c d} {e f g h} {i j k l}}
    92         -  14   "UPDATE OR IGNORE   $T3"   1 0 {{a b c d} {e f g h} {i j k l}}
    93         -  15   "UPDATE OR REPLACE  $T3"   1 0 {{a b c d} {i j k l}}
           89  +  11   "UPDATE OR ROLLBACK $T3"   0 1 {{a b c d} {e f g h}}
           90  +  12   "UPDATE OR ABORT    $T3"   0 1 {{a b c d} {e f g h} {i j k l}}
           91  +  13   "UPDATE OR FAIL     $T3"   0 1 {{a b c d} {e f g h} {i j k l}}
           92  +  14   "UPDATE OR IGNORE   $T3"   0 0 {{a b c d} {e f g h} {i j k l}}
           93  +  15   "UPDATE OR REPLACE  $T3"   0 0 {{a b c d} {i j k l}}
    94     94   
    95     95     16   "UPDATE OR ROLLBACK $T4"   1 1 {{a b c d} {e f g h}}
    96     96     17   "UPDATE OR ABORT    $T4"   1 1 {{a b c d} {e f g h} {i j k l}}
    97     97     18   "UPDATE OR FAIL     $T4"   1 1 {{e f g h} {i j k l} {a b c d}}
    98     98     19   "UPDATE OR IGNORE   $T4"   1 0 {{e f g h} {i j k l} {a b c d}}
    99     99     20   "UPDATE OR REPLACE  $T4"   1 0 {{e f g h} {a b c d}}
   100    100   }] {
................................................................................
   173    173     SELECT docid FROM t3;
   174    174   } {3 4 5}
   175    175   
   176    176   do_execsql_test 3.8 {
   177    177     UPDATE OR REPLACE t3 SET docid = 5, content='three four' WHERE docid = 4;
   178    178     SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'one'
   179    179   } {X'0200000002000000'}
          180  +
          181  +#-------------------------------------------------------------------------
          182  +# Test that the xSavepoint is invoked correctly if the first write 
          183  +# operation within a transaction is to a virtual table. 
          184  +# 
          185  +do_catchsql_test 4.1.1 {
          186  +  CREATE VIRTUAL TABLE t0 USING fts4;
          187  +  BEGIN;
          188  +    INSERT INTO t0(rowid, content) SELECT
          189  +      1, 'abc' UNION ALL SELECT
          190  +      2, 'def' UNION ALL SELECT
          191  +      1, 'ghi';
          192  +} {1 {constraint failed}}
          193  +do_execsql_test 4.1.2 {
          194  +  COMMIT;
          195  +}
          196  +do_execsql_test 4.1.3 {
          197  +  SELECT * FROM t0 WHERE t0 MATCH 'abc';
          198  +  INSERT INTO t0(t0) VALUES('integrity-check');
          199  +} {}
          200  +
          201  +do_execsql_test 4.2.1 {
          202  +  CREATE VIRTUAL TABLE t01 USING fts4;
          203  +  BEGIN;
          204  +    SAVEPOINT abc;
          205  +      INSERT INTO t01 VALUES('a b c');
          206  +    ROLLBACK TO abc;
          207  +  COMMIT;
          208  +}
          209  +do_execsql_test 4.2.2 {
          210  +  SELECT * FROM t01 WHERE t01 MATCH 'b';
          211  +  INSERT INTO t01(t01) VALUES('integrity-check');
          212  +} {}
   180    213   
   181    214   finish_test
          215  +

Changes to test/fts3expr3.test.

   117    117   proc balanced_andor_tree {nEntry} {
   118    118     set tree [balanced_exprtree_structure $nEntry]
   119    119     set node "{[balanced_and_tree $nEntry]}"
   120    120     regsub -all AND $node OR node
   121    121     regsub -all xxx $tree $node tree
   122    122     return $tree
   123    123   }
          124  +
          125  +if 1 {
   124    126   
   125    127   # Test that queries like "1 AND 2 AND 3 AND 4..." are transformed to 
   126    128   # balanced trees by FTS.
   127    129   #
   128    130   for {set i 1} {$i < 100} {incr i} {
   129    131     do_test 1.$i {
   130    132       test_fts3expr2 [random_and_query $i]
................................................................................
   197    199   set query [random_andor_query 12]
   198    200   set result [balanced_andor_tree 12]
   199    201   do_faultsim_test fts3expr3-fault-1 -faults oom-* -body {
   200    202     test_fts3expr2 $::query
   201    203   } -test {
   202    204     faultsim_test_result [list 0 $::result]
   203    205   }
          206  +
          207  +}
          208  +
          209  +#-------------------------------------------------------------------
          210  +
          211  +foreach {tn expr res} {
          212  +  1 {1 OR 2 OR 3 OR 4}           {OR {OR {P 1} {P 2}} {OR {P 3} {P 4}}} 
          213  +  2 {1 OR (2 AND 3 AND 4 AND 5)} 
          214  +    {OR {P 1} {AND {AND {P 2} {P 3}} {AND {P 4} {P 5}}}}
          215  +  3 {(2 AND 3 AND 4 AND 5) OR 1} 
          216  +    {OR {AND {AND {P 2} {P 3}} {AND {P 4} {P 5}}} {P 1}}
          217  +
          218  +  4 {1 AND (2 OR 3 OR 4 OR 5)} 
          219  +    {AND {P 1} {OR {OR {P 2} {P 3}} {OR {P 4} {P 5}}}}
          220  +  5 {(2 OR 3 OR 4 OR 5) AND 1} 
          221  +    {AND {OR {OR {P 2} {P 3}} {OR {P 4} {P 5}}} {P 1}}
          222  +
          223  +  6 {(2 OR 3 OR 4 OR 5) NOT 1} 
          224  +    {NOT {OR {OR {P 2} {P 3}} {OR {P 4} {P 5}}} {P 1}}
          225  +
          226  +  7 {1 NOT (2 OR 3 OR 4 OR 5)} 
          227  +    {NOT {P 1} {OR {OR {P 2} {P 3}} {OR {P 4} {P 5}}}}
          228  +
          229  +  8 {(1 OR 2 OR 3 OR 4) NOT (5 AND 6 AND 7 AND 8)}
          230  +    {NOT {OR {OR {P 1} {P 2}} {OR {P 3} {P 4}}} {AND {AND {P 5} {P 6}} {AND {P 7} {P 8}}}}
          231  +} {
          232  +  do_test 5.1.$tn {
          233  +    test_fts3expr2 $expr
          234  +  } $res
          235  +}
   204    236   
   205    237   set sqlite_fts3_enable_parentheses 0
   206    238   finish_test

Added test/fts4onepass.test.

            1  +# 2015 Sep 27
            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  +set testdir [file dirname $argv0]
           14  +source $testdir/tester.tcl
           15  +source $testdir/fts3_common.tcl
           16  +set ::testprefix fts4onepass
           17  +
           18  +# If SQLITE_ENABLE_FTS3 is defined, omit this file.
           19  +ifcapable !fts3 {
           20  +  finish_test
           21  +  return
           22  +}
           23  +
           24  +do_execsql_test 1.0 {
           25  +  CREATE VIRTUAL TABLE ft USING fts3;
           26  +  INSERT INTO ft(rowid, content) VALUES(1, '1 2 3');
           27  +  INSERT INTO ft(rowid, content) VALUES(2, '4 5 6');
           28  +  INSERT INTO ft(rowid, content) VALUES(3, '7 8 9');
           29  +}
           30  +
           31  +#-------------------------------------------------------------------------
           32  +# Check that UPDATE and DELETE statements that feature "WHERE rowid=?" or 
           33  +# or "WHERE docid=?" clauses do not use statement journals. But that other
           34  +# DELETE and UPDATE statements do.
           35  +#
           36  +# Note: "MATCH ? AND docid=?" does use a statement journal.
           37  +#
           38  +foreach {tn sql uses} {
           39  +  1.1 { DELETE FROM ft } 1
           40  +  1.2 { DELETE FROM ft WHERE docid=? } 0
           41  +  1.3 { DELETE FROM ft WHERE rowid=? } 0
           42  +  1.4 { DELETE FROM ft WHERE ft MATCH '1' } 1
           43  +  1.5 { DELETE FROM ft WHERE ft MATCH '1' AND docid=? } 1
           44  +  1.6 { DELETE FROM ft WHERE ft MATCH '1' AND rowid=? } 1
           45  +
           46  +  2.1 { UPDATE ft SET content='a b c' } 1
           47  +  2.2 { UPDATE ft SET content='a b c' WHERE docid=? } 0
           48  +  2.3 { UPDATE ft SET content='a b c' WHERE rowid=? } 0
           49  +  2.4 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' } 1
           50  +  2.5 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' AND docid=? } 1
           51  +  2.6 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' AND rowid=? } 1
           52  +} {
           53  +  do_test 1.$tn { sql_uses_stmt db $sql } $uses
           54  +}
           55  +
           56  +#-------------------------------------------------------------------------
           57  +# Check that putting a "DELETE/UPDATE ... WHERE rowid=?" statement in a
           58  +# trigger program does not prevent the VM from using a statement 
           59  +# transaction. Even if the calling statement cannot hit a constraint.
           60  +#
           61  +do_execsql_test 2.0 {
           62  +  CREATE TABLE t1(x);
           63  +
           64  +  CREATE TRIGGER t1_ai AFTER INSERT ON t1 BEGIN
           65  +    DELETE FROM ft WHERE rowid=new.x;
           66  +  END;
           67  +
           68  +  CREATE TRIGGER t1_ad AFTER DELETE ON t1 BEGIN
           69  +    UPDATE ft SET content = 'a b c' WHERE rowid=old.x;
           70  +  END;
           71  +
           72  +  CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 BEGIN
           73  +    DELETE FROM ft WHERE rowid=old.x;
           74  +  END;
           75  +}
           76  +
           77  +foreach {tn sql uses} {
           78  +  1 { INSERT INTO t1 VALUES(1)      } 1
           79  +  2 { DELETE FROM t1 WHERE x=4      } 1
           80  +  3 { UPDATE t1 SET x=10 WHERE x=11 } 1
           81  +} {
           82  +  do_test 2.$tn { sql_uses_stmt db $sql } $uses
           83  +}
           84  +
           85  +#-------------------------------------------------------------------------
           86  +# Test that an "UPDATE ... WHERE rowid=?" works and does not corrupt the
           87  +# index when it strikes a constraint. Both inside and outside a 
           88  +# transaction.
           89  +#
           90  +foreach {tn tcl1 tcl2}  {
           91  +  1 {} {}
           92  +
           93  +  2 {
           94  +    execsql BEGIN
           95  +  } {
           96  +    if {[sqlite3_get_autocommit db]==1} { error "transaction rolled back!" }
           97  +    execsql COMMIT
           98  +  }
           99  +} {
          100  +
          101  +  do_execsql_test 3.$tn.0 {
          102  +    DROP TABLE IF EXISTS ft2;
          103  +    CREATE VIRTUAL TABLE ft2 USING fts4;
          104  +    INSERT INTO ft2(rowid, content) VALUES(1, 'a b c');
          105  +    INSERT INTO ft2(rowid, content) VALUES(2, 'a b d');
          106  +    INSERT INTO ft2(rowid, content) VALUES(3, 'a b e');
          107  +  }
          108  +
          109  +  eval $tcl1
          110  +  foreach {tn2 sql content} {
          111  +    1 { UPDATE ft2 SET docid=2 WHERE docid=1 }
          112  +      { 1 {a b c} 2 {a b d} 3 {a b e} }
          113  +
          114  +    2 { 
          115  +      INSERT INTO ft2(rowid, content) VALUES(4, 'a b f');
          116  +      UPDATE ft2 SET docid=5 WHERE docid=4;
          117  +      UPDATE ft2 SET docid=3 WHERE docid=5;
          118  +    } { 1 {a b c} 2 {a b d} 3 {a b e} 5 {a b f} }
          119  +
          120  +    3 {
          121  +      UPDATE ft2 SET docid=3 WHERE docid=4;           -- matches 0 rows
          122  +      UPDATE ft2 SET docid=2 WHERE docid=3;
          123  +    } { 1 {a b c} 2 {a b d} 3 {a b e} 5 {a b f} }
          124  +
          125  +    4 {
          126  +      INSERT INTO ft2(rowid, content) VALUES(4, 'a b g');
          127  +      UPDATE ft2 SET docid=-1 WHERE docid=4;
          128  +      UPDATE ft2 SET docid=3 WHERE docid=-1;
          129  +    } {-1 {a b g} 1 {a b c} 2 {a b d} 3 {a b e} 5 {a b f} }
          130  +
          131  +    5 {
          132  +      DELETE FROM ft2 WHERE rowid=451;
          133  +      DELETE FROM ft2 WHERE rowid=-1;
          134  +      UPDATE ft2 SET docid = 2 WHERE docid = 1;
          135  +    } {1 {a b c} 2 {a b d} 3 {a b e} 5 {a b f} }
          136  +  } {
          137  +    do_catchsql_test 3.$tn.$tn2.a $sql {1 {constraint failed}}
          138  +    do_execsql_test  3.$tn.$tn2.b { SELECT rowid, content FROM ft2 } $content
          139  +    do_execsql_test  3.$tn.$tn2.c { 
          140  +      INSERT INTO ft2(ft2) VALUES('integrity-check');
          141  +    }
          142  +  }
          143  +  eval $tcl2
          144  +}
          145  +
          146  +finish_test
          147  +

Changes to test/fuzzdata3.db.

cannot compute difference between binary files

Changes to test/indexexpr1.test.

    84     84   } {1 1 1}
    85     85   do_execsql_test indexexpr1-160eqp {
    86     86     EXPLAIN QUERY PLAN
    87     87     SELECT rowid, b, c FROM t1
    88     88      WHERE substr(a,27,3)=='ord' AND d>=29;
    89     89   } {/USING INDEX t1a2/}
    90     90   
           91  +# ORDER BY using an indexed expression
           92  +#
           93  +do_execsql_test indexexpr1-170 {
           94  +  CREATE INDEX t1alen ON t1(length(a));
           95  +  SELECT length(a) FROM t1 ORDER BY length(a);
           96  +} {20 25 27 29 38 52}
           97  +do_execsql_test indexexpr1-170eqp {
           98  +  EXPLAIN QUERY PLAN
           99  +  SELECT length(a) FROM t1 ORDER BY length(a);
          100  +} {/SCAN TABLE t1 USING INDEX t1alen/}
          101  +do_execsql_test indexexpr1-171 {
          102  +  SELECT length(a) FROM t1 ORDER BY length(a) DESC;
          103  +} {52 38 29 27 25 20}
          104  +do_execsql_test indexexpr1-171eqp {
          105  +  EXPLAIN QUERY PLAN
          106  +  SELECT length(a) FROM t1 ORDER BY length(a) DESC;
          107  +} {/SCAN TABLE t1 USING INDEX t1alen/}
    91    108   
    92    109   do_execsql_test indexexpr1-200 {
    93    110     DROP TABLE t1;
    94    111     CREATE TABLE t1(id ANY PRIMARY KEY, a,b,c) WITHOUT ROWID;
    95    112     INSERT INTO t1(id,a,b,c)
    96    113     VALUES(1,'In_the_beginning_was_the_Word',1,1),
    97    114           (2,'and_the_Word_was_with_God',1,2),
................................................................................
   189    206   do_execsql_test indexexpr1-400 {
   190    207     CREATE TABLE t3(a,b,c);
   191    208     WITH RECURSIVE c(x) AS (VALUES(1) UNION SELECT x+1 FROM c WHERE x<30)
   192    209     INSERT INTO t3(a,b,c)
   193    210       SELECT x, printf('ab%04xyz',x), random() FROM c;
   194    211     CREATE UNIQUE INDEX t3abc ON t3(CAST(a AS text), b, substr(c,1,3));
   195    212     SELECT a FROM t3 WHERE CAST(a AS text)<='10' ORDER BY +a;
   196         -} {1 10}
          213  +  PRAGMA integrity_check;
          214  +} {1 10 ok}
   197    215   do_catchsql_test indexexpr1-410 {
   198    216     INSERT INTO t3 SELECT * FROM t3 WHERE rowid=10;
   199    217   } {1 {UNIQUE constraint failed: index 't3abc'}}
   200    218   
   201    219   do_execsql_test indexexpr1-500 {
   202    220     CREATE TABLE t5(a);
   203    221     CREATE TABLE cnt(x);
................................................................................
   250    268     CREATE INDEX t72yz ON t72(y+z);
   251    269     INSERT INTO t71(a,b,c) VALUES(1,11,2),(2,7,15),(3,5,4);
   252    270     INSERT INTO t72(x,y,z) VALUES(1,10,3),(2,8,14),(3,9,9);
   253    271     SELECT a, x, '|' FROM t71, t72
   254    272      WHERE b+c=y+z
   255    273     ORDER BY +a, +x;
   256    274   } {1 1 | 2 2 |}
          275  +
          276  +# Collating sequences on indexes of expressions
          277  +#
          278  +do_execsql_test indexexpr1-800 {
          279  +  DROP TABLE IF EXISTS t8;
          280  +  CREATE TABLE t8(a INTEGER PRIMARY KEY, b TEXT);
          281  +  CREATE UNIQUE INDEX t8bx ON t8(substr(b,2,4) COLLATE nocase);
          282  +  INSERT INTO t8(a,b) VALUES(1,'Alice'),(2,'Bartholemew'),(3,'Cynthia');
          283  +  SELECT * FROM t8 WHERE substr(b,2,4)='ARTH' COLLATE nocase;
          284  +} {2 Bartholemew}
          285  +do_catchsql_test indexexpr1-810 {
          286  +  INSERT INTO t8(a,b) VALUES(4,'BARTHMERE');
          287  +} {1 {UNIQUE constraint failed: index 't8bx'}}
          288  +do_catchsql_test indexexpr1-820 {
          289  +  DROP INDEX t8bx;
          290  +  CREATE UNIQUE INDEX t8bx ON t8(substr(b,2,4) COLLATE rtrim);
          291  +  INSERT INTO t8(a,b) VALUES(4,'BARTHMERE');
          292  +} {0 {}}
          293  +
          294  +# Check that PRAGMA integrity_check works correctly on a
          295  +# UNIQUE index that includes rowid and expression terms.
          296  +#
          297  +do_execsql_test indexexpr1-900 {
          298  +  CREATE TABLE t9(a,b,c,d);
          299  +  CREATE UNIQUE INDEX t9x1 ON t9(c,abs(d),b);
          300  +  INSERT INTO t9(rowid,a,b,c,d) VALUES(1,2,3,4,5);
          301  +  INSERT INTO t9(rowid,a,b,c,d) VALUES(2,NULL,NULL,NULL,NULL);
          302  +  INSERT INTO t9(rowid,a,b,c,d) VALUES(3,NULL,NULL,NULL,NULL);
          303  +  INSERT INTO t9(rowid,a,b,c,d) VALUES(4,5,6,7,8);
          304  +  PRAGMA integrity_check;
          305  +} {ok}
          306  +do_catchsql_test indexexpr1-910 {
          307  +  INSERT INTO t9(a,b,c,d) VALUES(5,6,7,-8);
          308  +} {1 {UNIQUE constraint failed: index 't9x1'}}
          309  +
   257    310   
   258    311   finish_test

Changes to test/json101.test.

    11     11   # This file implements tests for JSON SQL functions extension to the
    12     12   # SQLite library.
    13     13   #
    14     14   
    15     15   set testdir [file dirname $argv0]
    16     16   source $testdir/tester.tcl
    17     17   
    18         -load_static_extension db json
           18  +ifcapable !json1 {
           19  +  finish_test
           20  +  return
           21  +}
           22  +
    19     23   do_execsql_test json101-1.1.00 {
    20     24     SELECT json_array(1,2.5,null,'hello');
    21     25   } {[1,2.5,null,"hello"]}
    22     26   do_execsql_test json101-1.1.01 {
    23     27     SELECT json_array(1,'{"abc":2.5,"def":null,"ghi":hello}',99);
    24     28     -- the second term goes in as a string:
    25     29   } {[1,"{\\"abc\\":2.5,\\"def\\":null,\\"ghi\\":hello}",99]}

Changes to test/json102.test.

    14     14   # This file contains tests automatically generated from the json1
    15     15   # documentation.
    16     16   #
    17     17   
    18     18   set testdir [file dirname $argv0]
    19     19   source $testdir/tester.tcl
    20     20   
    21         -load_static_extension db json
           21  +ifcapable !json1 {
           22  +  finish_test
           23  +  return
           24  +}
           25  +
    22     26   do_execsql_test json102-100 {
    23     27     SELECT json_object('ex','[52,3.14159]');
    24     28   } {{{"ex":"[52,3.14159]"}}}
    25     29   do_execsql_test json102-110 {
    26     30     SELECT json_object('ex',json('[52,3.14159]'));
    27     31   } {{{"ex":[52,3.14159]}}}
    28     32   do_execsql_test json102-120 {

Added test/offset1.test.

            1  +# 2015-10-06
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +# 
           12  +# This file implements test cases for the [b65cb2c8d91f6685841d7d1e13b6]
           13  +# bug:  Correct handling of LIMIT and OFFSET on a UNION ALL query where
           14  +# the right-hand SELECT contains an ORDER BY in a subquery.
           15  +#
           16  +
           17  +set testdir [file dirname $argv0]
           18  +source $testdir/tester.tcl
           19  +
           20  +ifcapable !compound {
           21  +  finish_test
           22  +  return
           23  +}
           24  +
           25  +do_execsql_test offset1-1.1 {
           26  +  CREATE TABLE t1(a,b);
           27  +  INSERT INTO t1 VALUES(1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e');
           28  +  CREATE TABLE t2(x,y);
           29  +  INSERT INTO t2 VALUES(8,'y'),(9,'z'),(6,'w'),(7,'x');
           30  +  SELECT count(*) FROM t1, t2;
           31  +} {20}
           32  +
           33  +do_execsql_test offset1-1.2.0 {
           34  +  SELECT a, b FROM t1
           35  +  UNION ALL
           36  +  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
           37  +  LIMIT 3 OFFSET 0;
           38  +} {1 a 2 b 3 c}
           39  +do_execsql_test offset1-1.2.1 {
           40  +  SELECT a, b FROM t1
           41  +  UNION ALL
           42  +  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
           43  +  LIMIT 3 OFFSET 1;
           44  +} {2 b 3 c 4 d}
           45  +do_execsql_test offset1-1.2.2 {
           46  +  SELECT a, b FROM t1
           47  +  UNION ALL
           48  +  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
           49  +  LIMIT 3 OFFSET 2;
           50  +} {3 c 4 d 5 e}
           51  +do_execsql_test offset1-1.2.3 {
           52  +  SELECT a, b FROM t1
           53  +  UNION ALL
           54  +  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
           55  +  LIMIT 3 OFFSET 3;
           56  +} {4 d 5 e 6 w}
           57  +do_execsql_test offset1-1.2.4 {
           58  +  SELECT a, b FROM t1
           59  +  UNION ALL
           60  +  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
           61  +  LIMIT 3 OFFSET 4;
           62  +} {5 e 6 w 7 x}
           63  +do_execsql_test offset1-1.2.5 {
           64  +  SELECT a, b FROM t1
           65  +  UNION ALL
           66  +  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
           67  +  LIMIT 3 OFFSET 5;
           68  +} {6 w 7 x 8 y}
           69  +do_execsql_test offset1-1.2.6 {
           70  +  SELECT a, b FROM t1
           71  +  UNION ALL
           72  +  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
           73  +  LIMIT 3 OFFSET 6;
           74  +} {7 x 8 y 9 z}
           75  +do_execsql_test offset1-1.2.7 {
           76  +  SELECT a, b FROM t1
           77  +  UNION ALL
           78  +  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
           79  +  LIMIT 3 OFFSET 7;
           80  +} {8 y 9 z}
           81  +do_execsql_test offset1-1.2.8 {
           82  +  SELECT a, b FROM t1
           83  +  UNION ALL
           84  +  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
           85  +  LIMIT 3 OFFSET 8;
           86  +} {9 z}
           87  +do_execsql_test offset1-1.2.9 {
           88  +  SELECT a, b FROM t1
           89  +  UNION ALL
           90  +  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
           91  +  LIMIT 3 OFFSET 9;
           92  +} {}
           93  +
           94  +do_execsql_test offset1-1.3.0 {
           95  +  SELECT * FROM t1 LIMIT 0;
           96  +} {}
           97  +
           98  +do_execsql_test offset1-1.4.0 {
           99  +  SELECT a, b FROM t1
          100  +  UNION ALL
          101  +  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
          102  +  LIMIT 0 OFFSET 1;
          103  +} {}
          104  +do_execsql_test offset1-1.4.1 {
          105  +  SELECT a, b FROM t1
          106  +  UNION ALL
          107  +  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
          108  +  LIMIT 1 OFFSET 1;
          109  +} {2 b}
          110  +do_execsql_test offset1-1.4.2 {
          111  +  SELECT a, b FROM t1
          112  +  UNION ALL
          113  +  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
          114  +  LIMIT 2 OFFSET 1;
          115  +} {2 b 3 c}
          116  +do_execsql_test offset1-1.4.3 {
          117  +  SELECT a, b FROM t1
          118  +  UNION ALL
          119  +  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
          120  +  LIMIT 3 OFFSET 1;
          121  +} {2 b 3 c 4 d}
          122  +do_execsql_test offset1-1.4.4 {
          123  +  SELECT a, b FROM t1
          124  +  UNION ALL
          125  +  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
          126  +  LIMIT 4 OFFSET 1;
          127  +} {2 b 3 c 4 d 5 e}
          128  +do_execsql_test offset1-1.4.5 {
          129  +  SELECT a, b FROM t1
          130  +  UNION ALL
          131  +  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
          132  +  LIMIT 5 OFFSET 1;
          133  +} {2 b 3 c 4 d 5 e 6 w}
          134  +do_execsql_test offset1-1.4.6 {
          135  +  SELECT a, b FROM t1
          136  +  UNION ALL
          137  +  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
          138  +  LIMIT 6 OFFSET 1;
          139  +} {2 b 3 c 4 d 5 e 6 w 7 x}
          140  +do_execsql_test offset1-1.4.7 {
          141  +  SELECT a, b FROM t1
          142  +  UNION ALL
          143  +  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
          144  +  LIMIT 7 OFFSET 1;
          145  +} {2 b 3 c 4 d 5 e 6 w 7 x 8 y}
          146  +do_execsql_test offset1-1.4.8 {
          147  +  SELECT a, b FROM t1
          148  +  UNION ALL
          149  +  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
          150  +  LIMIT 8 OFFSET 1;
          151  +} {2 b 3 c 4 d 5 e 6 w 7 x 8 y 9 z}
          152  +do_execsql_test offset1-1.4.9 {
          153  +  SELECT a, b FROM t1
          154  +  UNION ALL
          155  +  SELECT * FROM (SELECT x, y FROM t2 ORDER BY y)
          156  +  LIMIT 9 OFFSET 1;
          157  +} {2 b 3 c 4 d 5 e 6 w 7 x 8 y 9 z}
          158  +
          159  +
          160  +
          161  +finish_test

Changes to test/releasetest.tcl.

    74     74       -DSQLITE_SOUNDEX=1
    75     75     }
    76     76     "Update-Delete-Limit" {
    77     77       -O2
    78     78       -DSQLITE_DEFAULT_FILE_FORMAT=4
    79     79       -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
    80     80       -DSQLITE_ENABLE_STMT_SCANSTATUS
           81  +    --enable-json1
    81     82     }
    82     83     "Check-Symbols" {
    83     84       -DSQLITE_MEMDEBUG=1
    84     85       -DSQLITE_ENABLE_FTS3_PARENTHESIS=1
    85     86       -DSQLITE_ENABLE_FTS3=1
    86     87       -DSQLITE_ENABLE_RTREE=1
    87     88       -DSQLITE_ENABLE_MEMSYS5=1
................................................................................
    91     92       -DSQLITE_SECURE_DELETE=1
    92     93       -DSQLITE_SOUNDEX=1
    93     94       -DSQLITE_ENABLE_ATOMIC_WRITE=1
    94     95       -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
    95     96       -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
    96     97       -DSQLITE_ENABLE_STAT4
    97     98       -DSQLITE_ENABLE_STMT_SCANSTATUS
           99  +    --enable-json1 --enable-fts5
    98    100     }
    99    101     "Debug-One" {
   100    102       --disable-shared
   101    103       -O2
   102    104       -DSQLITE_DEBUG=1
   103    105       -DSQLITE_MEMDEBUG=1
   104    106       -DSQLITE_MUTEX_NOOP=1
................................................................................
   131    133       -DSQLITE_ENABLE_IOTRACE=1
   132    134       -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
   133    135       -DSQLITE_MAX_PAGE_SIZE=4096
   134    136       -DSQLITE_OMIT_LOAD_EXTENSION=1
   135    137       -DSQLITE_OMIT_PROGRESS_CALLBACK=1
   136    138       -DSQLITE_OMIT_VIRTUALTABLE=1
   137    139       -DSQLITE_TEMP_STORE=3
          140  +    --enable-json1
   138    141     }
   139    142     "Device-Two" {
   140    143       -DSQLITE_4_BYTE_ALIGNED_MALLOC=1
   141    144       -DSQLITE_DEFAULT_AUTOVACUUM=1
   142    145       -DSQLITE_DEFAULT_CACHE_SIZE=1000
   143    146       -DSQLITE_DEFAULT_LOCKING_MODE=0
   144    147       -DSQLITE_DEFAULT_PAGE_SIZE=1024
................................................................................
   148    151       -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
   149    152       -DSQLITE_ENABLE_RTREE=1
   150    153       -DSQLITE_MAX_COMPOUND_SELECT=50
   151    154       -DSQLITE_MAX_PAGE_SIZE=32768
   152    155       -DSQLITE_OMIT_TRACE=1
   153    156       -DSQLITE_TEMP_STORE=3
   154    157       -DSQLITE_THREADSAFE=2
          158  +    --enable-json1 --enable-fts5
   155    159     }
   156    160     "Locking-Style" {
   157    161       -O2
   158    162       -DSQLITE_ENABLE_LOCKING_STYLE=1
   159    163     }
   160    164     "OS-X" {
   161    165       -O1   # Avoid a compiler bug in gcc 4.2.1 build 5658
   162    166       -DSQLITE_OMIT_LOAD_EXTENSION=1
   163    167       -DSQLITE_DEFAULT_MEMSTATUS=0
   164    168       -DSQLITE_THREADSAFE=2
   165    169       -DSQLITE_OS_UNIX=1
          170  +    -DSQLITE_ENABLE_JSON1=1
   166    171       -DSQLITE_ENABLE_LOCKING_STYLE=1
   167    172       -DUSE_PREAD=1
   168    173       -DSQLITE_ENABLE_RTREE=1
   169    174       -DSQLITE_ENABLE_FTS3=1
   170    175       -DSQLITE_ENABLE_FTS3_PARENTHESIS=1
   171    176       -DSQLITE_DEFAULT_CACHE_SIZE=1000
   172    177       -DSQLITE_MAX_LENGTH=2147483645
   173    178       -DSQLITE_MAX_VARIABLE_NUMBER=500000
   174    179       -DSQLITE_DEBUG=1
   175    180       -DSQLITE_PREFER_PROXY_LOCKING=1
   176    181       -DSQLITE_ENABLE_API_ARMOR=1
          182  +    --enable-json1 --enable-fts5
   177    183     }
   178    184     "Extra-Robustness" {
   179    185       -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
   180    186       -DSQLITE_MAX_ATTACHED=62
   181    187     }
   182    188     "Devkit" {
   183    189       -DSQLITE_DEFAULT_FILE_FORMAT=4
   184    190       -DSQLITE_MAX_ATTACHED=30
   185    191       -DSQLITE_ENABLE_COLUMN_METADATA
   186    192       -DSQLITE_ENABLE_FTS4
   187    193       -DSQLITE_ENABLE_FTS4_PARENTHESIS
   188    194       -DSQLITE_DISABLE_FTS4_DEFERRED
   189    195       -DSQLITE_ENABLE_RTREE
          196  +    --enable-json1 --enable-fts5
   190    197     }
   191    198     "No-lookaside" {
   192    199       -DSQLITE_TEST_REALLOC_STRESS=1
   193    200       -DSQLITE_OMIT_LOOKASIDE=1
   194    201       -DHAVE_USLEEP=1
   195    202     }
   196    203     "Valgrind" {
   197    204       -DSQLITE_ENABLE_STAT4
   198    205       -DSQLITE_ENABLE_FTS4
   199    206       -DSQLITE_ENABLE_RTREE
          207  +    --enable-json1
   200    208     }
   201    209   
   202    210     # The next group of configurations are used only by the
   203    211     # Failure-Detection platform.  They are all the same, but we need
   204    212     # different names for them all so that they results appear in separate
   205    213     # subdirectories.
   206    214     #

Changes to test/spellfix2.test.

    72     72     WHERE word MATCH 'amstedam*' AND distance <= 100 AND top=20;
    73     73   } {
    74     74     32 20
    75     75   }
    76     76   
    77     77   do_execsql_test 1.6 {
    78     78     SELECT word, distance, matchlen FROM demo 
    79         -  WHERE word MATCH 'amstedam*' AND distance <= 100;
           79  +  WHERE word MATCH 'amstedam*' AND distance <= 100
           80  +  ORDER BY distance, word;
    80     81   } {
    81         -  amsterdam         100 9        amsterdamh        100 9
    82         -  amsterdamm        100 9        amsterdamn        100 9
    83         -  amsterdama        100 9        amsterdame        100 9
    84         -  amsterdami        100 9        amsterdamo        100 9
    85         -  amsterdamu        100 9        amsterdamy        100 9
    86         -  amsterdammetje    100 9        amsterdamania     100 9
    87         -  amsterdamb        100 9        amsterdamf        100 9
    88         -  amsterdamp        100 9        amsterdamv        100 9
    89         -  amsterdamw        100 9        amsterdamweg      100 9
    90         -  amsterdamc        100 9        amsterdamg        100 9
    91         -  amsterdamj        100 9        amsterdamk        100 9
    92         -  amsterdamq        100 9        amsterdams        100 9
    93         -  amsterdamx        100 9        amsterdamz        100 9
    94         -  amsterdamsestraat 100 9        amsterdamd        100 9
    95         -  amsterdamt        100 9        amsterdaml        100 9
    96         -  amsterdamlaan     100 9        amsterdamr        100 9
           82  +  amsterdam         100 9        amsterdama        100 9
           83  +  amsterdamania     100 9        amsterdamb        100 9
           84  +  amsterdamc        100 9        amsterdamd        100 9
           85  +  amsterdame        100 9        amsterdamf        100 9
           86  +  amsterdamg        100 9        amsterdamh        100 9
           87  +  amsterdami        100 9        amsterdamj        100 9
           88  +  amsterdamk        100 9        amsterdaml        100 9
           89  +  amsterdamlaan     100 9        amsterdamm        100 9
           90  +  amsterdammetje    100 9        amsterdamn        100 9
           91  +  amsterdamo        100 9        amsterdamp        100 9
           92  +  amsterdamq        100 9        amsterdamr        100 9
           93  +  amsterdams        100 9        amsterdamsestraat 100 9
           94  +  amsterdamt        100 9        amsterdamu        100 9
           95  +  amsterdamv        100 9        amsterdamw        100 9
           96  +  amsterdamweg      100 9        amsterdamx        100 9
           97  +  amsterdamy        100 9        amsterdamz        100 9
    97     98   }
    98     99   
    99    100   do_execsql_test 1.7 {
   100    101     SELECT word, distance, matchlen FROM demo 
   101         -  WHERE word MATCH 'amstedam*' AND distance <= 100 AND top=20;
          102  +  WHERE word MATCH 'amstedam*' AND distance <= 100 AND top=20
          103  +  ORDER BY distance, word;
   102    104   } {
   103         -  amsterdam         100 9        amsterdamh        100 9
   104         -  amsterdamm        100 9        amsterdamn        100 9
   105         -  amsterdama        100 9        amsterdame        100 9
   106         -  amsterdami        100 9        amsterdamo        100 9
   107         -  amsterdamu        100 9        amsterdamy        100 9
   108         -  amsterdammetje    100 9        amsterdamania     100 9
   109         -  amsterdamb        100 9        amsterdamf        100 9
   110         -  amsterdamp        100 9        amsterdamv        100 9
   111         -  amsterdamw        100 9        amsterdamweg      100 9
   112         -  amsterdamc        100 9        amsterdamg        100 9
          105  +  amsterdam         100 9        amsterdama        100 9
          106  +  amsterdamania     100 9        amsterdamb        100 9
          107  +  amsterdamc        100 9        amsterdame        100 9
          108  +  amsterdamf        100 9        amsterdamg        100 9
          109  +  amsterdamh        100 9        amsterdami        100 9
          110  +  amsterdamm        100 9        amsterdammetje    100 9
          111  +  amsterdamn        100 9        amsterdamo        100 9
          112  +  amsterdamp        100 9        amsterdamu        100 9
          113  +  amsterdamv        100 9        amsterdamw        100 9
          114  +  amsterdamweg      100 9        amsterdamy        100 9
   113    115   }
   114    116   
   115    117   
   116    118   finish_test

Changes to test/uri.test.

    59     59       #
    60     60       # NOTE: Due to limits on legal characters for file names imposed by
    61     61       #       Windows, we must skip the final two tests here (i.e. the
    62     62       #       question mark is illegal in a file name on Windows).
    63     63       #
    64     64       if {$tn>14} break
    65     65   
           66  +    #
           67  +    # NOTE: When running on Tcl 8.6 (or higher?) on Windows, a colon within
           68  +    #       the file name no longer tries to access an alternate data stream
           69  +    #       (ADS) named "test.db" for the "http" file, causing some spurious
           70  +    #       failures of this test.
           71  +    #
           72  +    if {$tn==12 && $::tcl_version>=8.6} continue
           73  +
    66     74       #
    67     75       # NOTE: On Windows, we need to account for the fact that the current
    68     76       #       directory does not start with a forward slash.
    69     77       #
    70     78       set uri  [string map [list PWD/ /[test_pwd /]] $uri]
    71     79     } else {
    72     80       set uri  [string map [list PWD/ [test_pwd /]] $uri]

Changes to test/view.test.

   157    157       CREATE VIEW v1c(x,y,z) AS SELECT a, b+c, c-b FROM t1;
   158    158       SELECT * FROM v1c LIMIT 1;
   159    159     }
   160    160   } {x 2 y 7 z 1}
   161    161   do_catchsql_test view-3.3.4 {
   162    162     CREATE VIEW v1err(x,y DESC,z) AS SELECT a, b+c, c-b FROM t1;
   163    163   } {1 {syntax error after column name "y"}}
          164  +do_catchsql_test view-3.3.5 {
          165  +  DROP VIEW IF EXISTS v1err;
          166  +  CREATE VIEW v1err(x,y) AS SELECT a, b+c, c-b FROM t1;
          167  +  SELECT * FROM v1err;
          168  +} {1 {expected 2 columns for 'v1err' but got 3}}
          169  +do_catchsql_test view-3.3.6 {
          170  +  DROP VIEW IF EXISTS v1err;
          171  +  CREATE VIEW v1err(w,x,y,z) AS SELECT a, b+c, c-b FROM t1;
          172  +  SELECT * FROM v1err;
          173  +} {1 {expected 4 columns for 'v1err' but got 3}}
   164    174   
   165    175   ifcapable compound {
   166    176   do_test  view-3.4 {
   167    177     execsql2 {
   168    178       CREATE VIEW v3 AS SELECT a FROM t1 UNION SELECT b FROM t1 ORDER BY b;
   169    179       SELECT * FROM v3 LIMIT 4;
   170    180     }
................................................................................
   459    469   
   460    470   # Ticket #1270:  Do not allow parameters in view definitions.
   461    471   #
   462    472   do_test view-12.1 {
   463    473     catchsql {
   464    474       CREATE VIEW v12 AS SELECT a FROM t1 WHERE b=?
   465    475     }
          476  +} {1 {parameters are not allowed in views}}
          477  +do_test view-12.2 {
          478  +  catchsql {
          479  +    CREATE VIEW v12(x) AS SELECT a FROM t1 WHERE b=?
          480  +  }
   466    481   } {1 {parameters are not allowed in views}}
   467    482   
   468    483   ifcapable attach {
   469    484     do_test view-13.1 {
   470    485       forcedelete test2.db
   471    486       catchsql {
   472    487         ATTACH 'test2.db' AS two;

Deleted tool/diffdb.c.

     1         -/*
     2         -** A utility for printing the differences between two SQLite database files.
     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 <unistd.h>
    10         -#include <stdlib.h>
    11         -
    12         -
    13         -#define PAGESIZE 1024
    14         -static int db1 = -1;
    15         -static int db2 = -1;
    16         -
    17         -int main(int argc, char **argv){
    18         -  int iPg;
    19         -  unsigned char a1[PAGESIZE], a2[PAGESIZE];
    20         -  if( argc!=3 ){
    21         -    fprintf(stderr,"Usage: %s FILENAME FILENAME\n", argv[0]);
    22         -    exit(1);
    23         -  }
    24         -  db1 = open(argv[1], O_RDONLY);
    25         -  if( db1<0 ){
    26         -    fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]);
    27         -    exit(1);
    28         -  }
    29         -  db2 = open(argv[2], O_RDONLY);
    30         -  if( db2<0 ){
    31         -    fprintf(stderr,"%s: can't open %s\n", argv[0], argv[2]);
    32         -    exit(1);
    33         -  }
    34         -  iPg = 1;
    35         -  while( read(db1, a1, PAGESIZE)==PAGESIZE && read(db2,a2,PAGESIZE)==PAGESIZE ){
    36         -    if( memcmp(a1,a2,PAGESIZE) ){
    37         -      printf("Page %d\n", iPg);
    38         -    }
    39         -    iPg++;
    40         -  }
    41         -  printf("%d pages checked\n", iPg-1);
    42         -  close(db1);
    43         -  close(db2);
    44         -}

Changes to tool/mksqlite3c.tcl.

   208    208           # begin/end markers with the harmless substring "**".
   209    209           puts $out "/* [string map [list /* ** */ **] $line] */"
   210    210         }
   211    211       } elseif {[regexp {^#ifdef __cplusplus} $line]} {
   212    212         puts $out "#if 0"
   213    213       } elseif {!$linemacros && [regexp {^#line} $line]} {
   214    214         # Skip #line directives.
   215         -    } elseif {$addstatic && ![regexp {^(static|typedef)} $line]} {
          215  +    } elseif {$addstatic
          216  +               && ![regexp {^(static|typedef|SQLITE_PRIVATE)} $line]} {
   216    217         # Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before
   217    218         # functions if this header file does not need it.
   218    219         if {![info exists varonly_hdr($tail)]
   219    220          && [regexp $declpattern $line all rettype funcname rest]} {
   220    221           regsub {^SQLITE_API } $line {} line
   221    222           # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
   222    223           # so that linkage can be modified at compile-time.
................................................................................
   376    377   
   377    378      rtree.c
   378    379      icu.c
   379    380      fts3_icu.c
   380    381      sqlrr.c
   381    382      sqlite3rbu.c
   382    383      dbstat.c
          384  +   json1.c
          385  +   fts5.c
   383    386   } {
   384    387     copy_file tsrc/$file
   385    388   }
   386    389   
   387    390   close $out

Changes to tool/mksqlite3h.tcl.

    67     67   
    68     68   # Force the output to use unix line endings, even on Windows.
    69     69   fconfigure stdout -translation lf
    70     70   
    71     71   set filelist [subst {
    72     72     $TOP/src/sqlite.h.in
    73     73     $TOP/ext/rtree/sqlite3rtree.h
           74  +  $TOP/ext/fts5/fts5.h
    74     75   }]
    75     76   
    76     77   # These are the functions that accept a variable number of arguments.  They
    77     78   # always need to use the "cdecl" calling convention even when another calling
    78     79   # convention (e.g. "stcall") is being used for the rest of the library.
    79     80   set cdecllist {
    80     81     sqlite3_config

Deleted tool/opcodeDoc.awk.

     1         -#
     2         -# Extract opcode documentation for sqliteVdbe.c and generate HTML
     3         -#
     4         -BEGIN {
     5         -  print "<html><body bgcolor=white>"
     6         -  print "<h1>SQLite Virtual Database Engine Opcodes</h1>"
     7         -  print "<table>"
     8         -}
     9         -/ Opcode: /,/\*\// {
    10         -  if( $2=="Opcode:" ){
    11         -    printf "<tr><td>%s&nbsp;%s&nbsp;%s&nbsp;%s</td>\n<td>\n", $3, $4, $5, $6
    12         -  }else if( $1=="*/" ){
    13         -    printf "</td></tr>\n"
    14         -  }else if( NF>1 ){
    15         -    sub(/^ *\*\* /,"")
    16         -    gsub(/</,"&lt;")
    17         -    gsub(/&/,"&amp;")
    18         -    print
    19         -  }
    20         -}
    21         -END {
    22         -  print "</table></body></html>"
    23         -}

Deleted tool/space_used.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
     3         -# versus how much space is unused.
     4         -#
     5         -
     6         -# Get the name of the database to analyze
     7         -#
     8         -if {[llength $argv]!=1} {
     9         -  puts stderr "Usage: $argv0 database-name"
    10         -  exit 1
    11         -}
    12         -set file_to_analyze [lindex $argv 0]
    13         -
    14         -# Open the database
    15         -#
    16         -sqlite db [lindex $argv 0]
    17         -set DB [btree_open [lindex $argv 0]]
    18         -
    19         -# Output the schema for the generated report
    20         -#
    21         -puts \
    22         -{BEGIN;
    23         -CREATE TABLE space_used(
    24         -   name clob,        -- Name of a table or index in the database file
    25         -   is_index boolean, -- TRUE if it is an index, false for a table
    26         -   payload int,      -- Total amount of data stored in this table or index
    27         -   pri_pages int,    -- Number of primary pages used
    28         -   ovfl_pages int,   -- Number of overflow pages used
    29         -   pri_unused int,   -- Number of unused bytes on primary pages
    30         -   ovfl_unused int   -- Number of unused bytes on overflow pages
    31         -);}
    32         -
    33         -# This query will be used to find the root page number for every index and
    34         -# table in the database.
    35         -#
    36         -set sql {
    37         -  SELECT name, type, rootpage FROM sqlite_master
    38         -  UNION ALL
    39         -  SELECT 'sqlite_master', 'table', 2
    40         -  ORDER BY 1
    41         -}
    42         -
    43         -# Initialize variables used for summary statistics.
    44         -#
    45         -set total_size 0
    46         -set total_primary 0
    47         -set total_overflow 0
    48         -set total_unused_primary 0
    49         -set total_unused_ovfl 0
    50         -
    51         -# Analyze every table in the database, one at a time.
    52         -#
    53         -foreach {name type rootpage} [db eval $sql] {
    54         -  set cursor [btree_cursor $DB $rootpage 0]
    55         -  set go [btree_first $cursor]
    56         -  set size 0
    57         -  catch {unset pg_used}
    58         -  set unused_ovfl 0
    59         -  set n_overflow 0
    60         -  while {$go==0} {
    61         -    set payload [btree_payload_size $cursor]
    62         -    incr size $payload
    63         -    set stat [btree_cursor_dump $cursor]
    64         -    set pgno [lindex $stat 0]
    65         -    set freebytes [lindex $stat 4]
    66         -    set pg_used($pgno) $freebytes
    67         -    if {$payload>238} {
    68         -      set n [expr {($payload-238+1019)/1020}]
    69         -      incr n_overflow $n
    70         -      incr unused_ovfl [expr {$n*1020+238-$payload}]
    71         -    }
    72         -    set go [btree_next $cursor]
    73         -  }
    74         -  btree_close_cursor $cursor
    75         -  set n_primary [llength [array names pg_used]]
    76         -  set unused_primary 0
    77         -  foreach x [array names pg_used] {incr unused_primary $pg_used($x)}
    78         -  regsub -all ' $name '' name
    79         -  puts -nonewline "INSERT INTO space_used VALUES('$name'"
    80         -  puts -nonewline ",[expr {$type=="index"}]"
    81         -  puts ",$size,$n_primary,$n_overflow,$unused_primary,$unused_ovfl);"
    82         -  incr total_size $size
    83         -  incr total_primary $n_primary
    84         -  incr total_overflow $n_overflow
    85         -  incr total_unused_primary $unused_primary
    86         -  incr total_unused_ovfl $unused_ovfl
    87         -}
    88         -
    89         -# Output summary statistics:
    90         -#
    91         -puts "-- Total payload size: $total_size"
    92         -puts "-- Total pages used: $total_primary primary and $total_overflow overflow"
    93         -set file_pgcnt [expr {[file size [lindex $argv 0]]/1024}]
    94         -puts -nonewline "-- Total unused bytes on primary pages: $total_unused_primary"
    95         -if {$total_primary>0} {
    96         -  set upp [expr {$total_unused_primary/$total_primary}]
    97         -  puts " (avg $upp bytes/page)"
    98         -} else {
    99         -  puts ""
   100         -}
   101         -puts -nonewline "-- Total unused bytes on overflow pages: $total_unused_ovfl"
   102         -if {$total_overflow>0} {
   103         -  set upp [expr {$total_unused_ovfl/$total_overflow}]
   104         -  puts " (avg $upp bytes/page)"
   105         -} else {
   106         -  puts ""
   107         -}
   108         -set n_free [expr {$file_pgcnt-$total_primary-$total_overflow}]
   109         -if {$n_free>0} {incr n_free -1}
   110         -puts "-- Total pages on freelist: $n_free"
   111         -puts "COMMIT;"