/ Check-in [6fbad957]
Login

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

Overview
Comment:Merge updates from trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | toTypeFuncs
Files: files | file ages | folders
SHA1: 6fbad957259eb8c15eaf7e5657240ae24aaf343e
User & Date: mistachkin 2013-05-15 08:00:44
Context
2013-06-21
18:32
Merge updates from trunk. check-in: fa2a91e6 user: mistachkin tags: toTypeFuncs
2013-05-15
08:00
Merge updates from trunk. check-in: 6fbad957 user: mistachkin tags: toTypeFuncs
2013-05-09
18:12
Add assert()s to the implementation of xRead() in the built-in VFSes to verify that the offset parameter is always non-negative. check-in: cf5c3642 user: drh tags: trunk
2013-03-13
20:52
Merge updates from trunk. check-in: d63fa039 user: mistachkin tags: toTypeFuncs
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Makefile.in.

   163    163   #
   164    164   LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
   165    165            backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
   166    166            callback.lo complete.lo ctime.lo date.lo delete.lo \
   167    167            expr.lo fault.lo fkey.lo \
   168    168            fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
   169    169            fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
          170  +         fts3_tokenize_vtab.lo \
   170    171            fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \
   171    172            func.lo global.lo hash.lo \
   172    173            icu.lo insert.lo journal.lo legacy.lo loadext.lo \
   173    174            main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
   174    175            memjournal.lo \
   175    176            mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
   176    177            notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
................................................................................
   312    313     $(TOP)/ext/fts3/fts3_hash.h \
   313    314     $(TOP)/ext/fts3/fts3_icu.c \
   314    315     $(TOP)/ext/fts3/fts3_porter.c \
   315    316     $(TOP)/ext/fts3/fts3_snippet.c \
   316    317     $(TOP)/ext/fts3/fts3_tokenizer.h \
   317    318     $(TOP)/ext/fts3/fts3_tokenizer.c \
   318    319     $(TOP)/ext/fts3/fts3_tokenizer1.c \
          320  +  $(TOP)/ext/fts3/fts3_tokenize_vtab.c \
   319    321     $(TOP)/ext/fts3/fts3_unicode.c \
   320    322     $(TOP)/ext/fts3/fts3_unicode2.c \
   321    323     $(TOP)/ext/fts3/fts3_write.c
   322    324   SRC += \
   323    325     $(TOP)/ext/icu/sqliteicu.h \
   324    326     $(TOP)/ext/icu/icu.c
   325    327   SRC += \
................................................................................
   355    357     $(TOP)/src/test_backup.c \
   356    358     $(TOP)/src/test_btree.c \
   357    359     $(TOP)/src/test_config.c \
   358    360     $(TOP)/src/test_demovfs.c \
   359    361     $(TOP)/src/test_devsym.c \
   360    362     $(TOP)/src/test_fs.c \
   361    363     $(TOP)/src/test_func.c \
   362         -  $(TOP)/src/test_fuzzer.c \
   363    364     $(TOP)/src/test_hexio.c \
   364    365     $(TOP)/src/test_init.c \
   365    366     $(TOP)/src/test_intarray.c \
   366    367     $(TOP)/src/test_journal.c \
   367    368     $(TOP)/src/test_malloc.c \
   368    369     $(TOP)/src/test_multiplex.c \
   369    370     $(TOP)/src/test_mutex.c \
   370    371     $(TOP)/src/test_onefile.c \
   371    372     $(TOP)/src/test_osinst.c \
   372    373     $(TOP)/src/test_pcache.c \
   373    374     $(TOP)/src/test_quota.c \
   374         -  $(TOP)/src/test_regexp.c \
   375    375     $(TOP)/src/test_rtree.c \
   376    376     $(TOP)/src/test_schema.c \
   377    377     $(TOP)/src/test_server.c \
   378    378     $(TOP)/src/test_superlock.c \
   379    379     $(TOP)/src/test_syscall.c \
   380    380     $(TOP)/src/test_stat.c \
   381    381     $(TOP)/src/test_tclvar.c \
   382    382     $(TOP)/src/test_thread.c \
   383    383     $(TOP)/src/test_vfs.c \
   384         -  $(TOP)/src/test_wholenumber.c \
   385    384     $(TOP)/src/test_wsd.c       \
   386    385     $(TOP)/ext/fts3/fts3_term.c \
   387    386     $(TOP)/ext/fts3/fts3_test.c 
   388    387   
          388  +# Statically linked extensions
          389  +#
          390  +TESTSRC += \
          391  +  $(TOP)/ext/misc/amatch.c \
          392  +  $(TOP)/ext/misc/closure.c \
          393  +  $(TOP)/ext/misc/fuzzer.c \
          394  +  $(TOP)/ext/misc/ieee754.c \
          395  +  $(TOP)/ext/misc/nextchar.c \
          396  +  $(TOP)/ext/misc/regexp.c \
          397  +  $(TOP)/ext/misc/spellfix.c \
          398  +  $(TOP)/ext/misc/wholenumber.c
          399  +
   389    400   # Source code to the library files needed by the test fixture
   390    401   #
   391    402   TESTSRC2 = \
   392    403     $(TOP)/src/attach.c \
   393    404     $(TOP)/src/backup.c \
   394    405     $(TOP)/src/bitvec.c \
   395    406     $(TOP)/src/btree.c \
................................................................................
   497    508   		-version-info "8:6:8" \
   498    509   		-avoid-version
   499    510   
   500    511   sqlite3$(TEXE):	$(TOP)/src/shell.c libsqlite3.la sqlite3.h
   501    512   	$(LTLINK) $(READLINE_FLAGS) \
   502    513   		-o $@ $(TOP)/src/shell.c libsqlite3.la \
   503    514   		$(LIBREADLINE) $(TLIBS) -rpath "$(libdir)"
          515  +
          516  +mptester$(EXE):	sqlite3.c $(TOP)/mptest/mptest.c
          517  +	$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
          518  +		$(TLIBS) -rpath "$(libdir)"
          519  +
   504    520   
   505    521   # This target creates a directory named "tsrc" and fills it with
   506    522   # copies of all of the C source code and header files needed to
   507    523   # build on the target system.  Some of the C source code and header
   508    524   # files are automatically generated.  This target takes care of
   509    525   # all that automatic generation.
   510    526   #
................................................................................
   515    531   	rm tsrc/sqlite.h.in tsrc/parse.y
   516    532   	$(TCLSH_CMD) $(TOP)/tool/vdbe-compress.tcl <tsrc/vdbe.c >vdbe.new
   517    533   	mv vdbe.new tsrc/vdbe.c
   518    534   	touch .target_source
   519    535   
   520    536   sqlite3.c:	.target_source $(TOP)/tool/mksqlite3c.tcl
   521    537   	$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl
          538  +	cp tsrc/shell.c tsrc/sqlite3ext.h .
   522    539   
   523    540   tclsqlite3.c:	sqlite3.c
   524    541   	echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c
   525    542   	cat sqlite3.c >>tclsqlite3.c
   526    543   	echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c
   527    544   	cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c
   528    545   
................................................................................
   848    865   
   849    866   fts3_tokenizer.lo:	$(TOP)/ext/fts3/fts3_tokenizer.c $(HDR) $(EXTHDR)
   850    867   	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer.c
   851    868   
   852    869   fts3_tokenizer1.lo:	$(TOP)/ext/fts3/fts3_tokenizer1.c $(HDR) $(EXTHDR)
   853    870   	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer1.c
   854    871   
          872  +fts3_tokenizer_vtab.lo:	$(TOP)/ext/fts3/fts3_tokenizer_vtab.c $(HDR) $(EXTHDR)
          873  +	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer_vtab.c
          874  +
   855    875   fts3_unicode.lo:	$(TOP)/ext/fts3/fts3_unicode.c $(HDR) $(EXTHDR)
   856    876   	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode.c
   857    877   
   858    878   fts3_unicode2.lo:	$(TOP)/ext/fts3/fts3_unicode2.c $(HDR) $(EXTHDR)
   859    879   	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode2.c
   860    880   
   861    881   fts3_write.lo:	$(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
................................................................................
   874    894   #
   875    895   TESTFIXTURE_FLAGS  = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
   876    896   TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE 
   877    897   TESTFIXTURE_FLAGS += -DBUILD_sqlite
   878    898   
   879    899   TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
   880    900   TESTFIXTURE_SRC1 = sqlite3.c
   881         -TESTFIXTURE_SRC = $(TESTSRC) $(TOP)/src/tclsqlite.c $(TESTFIXTURE_SRC$(USE_AMALGAMATION))
          901  +TESTFIXTURE_SRC = $(TESTSRC) $(TOP)/src/tclsqlite.c
          902  +TESTFIXTURE_SRC += $(TESTFIXTURE_SRC$(USE_AMALGAMATION))
   882    903   
   883    904   testfixture$(TEXE):	$(TESTFIXTURE_SRC)
   884    905   	$(LTLINK) -DSQLITE_NO_SYNC=1 $(TEMP_STORE) $(TESTFIXTURE_FLAGS) \
   885    906   		-o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS)
   886    907   
   887    908   
   888    909   fulltest:	testfixture$(TEXE) sqlite3$(TEXE)
................................................................................
   940    961   	rm -f *.da *.bb *.bbg gmon.out
   941    962   	rm -rf quota2a quota2b quota2c
   942    963   	rm -rf tsrc .target_source
   943    964   	rm -f tclsqlite3$(TEXE)
   944    965   	rm -f testfixture$(TEXE) test.db
   945    966   	rm -f sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def
   946    967   	rm -f sqlite3.c
          968  +	rm -f sqlite3rc.h
          969  +	rm -f shell.c sqlite3ext.h
   947    970   	rm -f sqlite3_analyzer$(TEXE) sqlite3_analyzer.c
   948    971   	rm -f sqlite-*-output.vsix
          972  +	rm -f mptester mptester.exe
   949    973   
   950    974   distclean:	clean
   951    975   	rm -f config.log config.status libtool Makefile sqlite3.pc
   952    976   
   953    977   #
   954    978   # Windows section
   955    979   #

Changes to Makefile.msc.

   474    474   #
   475    475   LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
   476    476            backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
   477    477            callback.lo complete.lo ctime.lo date.lo delete.lo \
   478    478            expr.lo fault.lo fkey.lo \
   479    479            fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
   480    480            fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
   481         -         fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \
          481  +         fts3_tokenize_vtab.lo fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \
   482    482            func.lo global.lo hash.lo \
   483    483            icu.lo insert.lo journal.lo legacy.lo loadext.lo \
   484    484            main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
   485    485            memjournal.lo \
   486    486            mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
   487    487            notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
   488    488            pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
................................................................................
   634    634     $(TOP)\ext\fts3\fts3_hash.h \
   635    635     $(TOP)\ext\fts3\fts3_icu.c \
   636    636     $(TOP)\ext\fts3\fts3_porter.c \
   637    637     $(TOP)\ext\fts3\fts3_snippet.c \
   638    638     $(TOP)\ext\fts3\fts3_tokenizer.h \
   639    639     $(TOP)\ext\fts3\fts3_tokenizer.c \
   640    640     $(TOP)\ext\fts3\fts3_tokenizer1.c \
          641  +  $(TOP)\ext\fts3\fts3_tokenize_vtab.c \
   641    642     $(TOP)\ext\fts3\fts3_unicode.c \
   642    643     $(TOP)\ext\fts3\fts3_unicode2.c \
   643    644     $(TOP)\ext\fts3\fts3_write.c
   644    645   SRC = $(SRC) \
   645    646     $(TOP)\ext\icu\sqliteicu.h \
   646    647     $(TOP)\ext\icu\icu.c
   647    648   SRC = $(SRC) \
................................................................................
   676    677     $(TOP)\src\test_backup.c \
   677    678     $(TOP)\src\test_btree.c \
   678    679     $(TOP)\src\test_config.c \
   679    680     $(TOP)\src\test_demovfs.c \
   680    681     $(TOP)\src\test_devsym.c \
   681    682     $(TOP)\src\test_fs.c \
   682    683     $(TOP)\src\test_func.c \
   683         -  $(TOP)\src\test_fuzzer.c \
   684    684     $(TOP)\src\test_hexio.c \
   685    685     $(TOP)\src\test_init.c \
   686    686     $(TOP)\src\test_intarray.c \
   687    687     $(TOP)\src\test_journal.c \
   688    688     $(TOP)\src\test_malloc.c \
   689    689     $(TOP)\src\test_multiplex.c \
   690    690     $(TOP)\src\test_mutex.c \
   691    691     $(TOP)\src\test_onefile.c \
   692    692     $(TOP)\src\test_osinst.c \
   693    693     $(TOP)\src\test_pcache.c \
   694    694     $(TOP)\src\test_quota.c \
   695         -  $(TOP)\src\test_regexp.c \
   696    695     $(TOP)\src\test_rtree.c \
   697    696     $(TOP)\src\test_schema.c \
   698    697     $(TOP)\src\test_server.c \
   699    698     $(TOP)\src\test_superlock.c \
   700    699     $(TOP)\src\test_syscall.c \
   701    700     $(TOP)\src\test_stat.c \
   702    701     $(TOP)\src\test_tclvar.c \
   703    702     $(TOP)\src\test_thread.c \
   704    703     $(TOP)\src\test_vfs.c \
   705         -  $(TOP)\src\test_wholenumber.c \
   706    704     $(TOP)\src\test_wsd.c \
   707    705     $(TOP)\ext\fts3\fts3_term.c \
   708    706     $(TOP)\ext\fts3\fts3_test.c
          707  +
          708  +# Statically linked extensions
          709  +#
          710  +TESTEXT = \
          711  +  $(TOP)\ext\misc\amatch.c \
          712  +  $(TOP)\ext\misc\closure.c \
          713  +  $(TOP)\ext\misc\fuzzer.c \
          714  +  $(TOP)\ext\misc\ieee754.c \
          715  +  $(TOP)\ext\misc\nextchar.c \
          716  +  $(TOP)\ext\misc\regexp.c \
          717  +  $(TOP)\ext\misc\spellfix.c \
          718  +  $(TOP)\ext\misc\wholenumber.c
          719  +
   709    720   
   710    721   # Source code to the library files needed by the test fixture
   711    722   #
   712    723   TESTSRC2 = \
   713    724     $(TOP)\src\attach.c \
   714    725     $(TOP)\src\backup.c \
   715    726     $(TOP)\src\bitvec.c \
................................................................................
   744    755     $(TOP)\src\vdbetrace.c \
   745    756     $(TOP)\src\where.c \
   746    757     parse.c \
   747    758     $(TOP)\ext\fts3\fts3.c \
   748    759     $(TOP)\ext\fts3\fts3_aux.c \
   749    760     $(TOP)\ext\fts3\fts3_expr.c \
   750    761     $(TOP)\ext\fts3\fts3_tokenizer.c \
          762  +  $(TOP)\ext\fts3\fts3_tokenize_vtab.c \
   751    763     $(TOP)\ext\fts3\fts3_unicode.c \
   752    764     $(TOP)\ext\fts3\fts3_unicode2.c \
   753    765     $(TOP)\ext\fts3\fts3_write.c \
   754    766     $(TOP)\ext\async\sqlite3async.c
   755    767   
   756    768   # Header files used by all library source files.
   757    769   #
................................................................................
   809    821   	$(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCL:tcl=tclstub) $(TLIBS)
   810    822   
   811    823   sqlite3.exe:	$(TOP)\src\shell.c libsqlite3.lib $(LIBRESOBJS) sqlite3.h
   812    824   	$(LTLINK) $(READLINE_FLAGS) \
   813    825   		$(TOP)\src\shell.c \
   814    826   		/link $(LTLINKOPTS) $(LTLIBPATHS) libsqlite3.lib $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
   815    827   
          828  +mptester.exe:	$(TOP)\mptest\mptest.c libsqlite3.lib $(LIBRESOBJS) sqlite3.h
          829  +	$(LTLINK) $(TOP)\mptest\mptest.c \
          830  +		/link $(LTLINKOPTS) $(LTLIBPATHS) libsqlite3.lib $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
          831  +
   816    832   # This target creates a directory named "tsrc" and fills it with
   817    833   # copies of all of the C source code and header files needed to
   818    834   # build on the target system.  Some of the C source code and header
   819    835   # files are automatically generated.  This target takes care of
   820    836   # all that automatic generation.
   821    837   #
   822    838   .target_source:	$(SRC) $(TOP)\tool\vdbe-compress.tcl
................................................................................
   826    842   	del /Q tsrc\sqlite.h.in tsrc\parse.y
   827    843   	$(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl < tsrc\vdbe.c > vdbe.new
   828    844   	move vdbe.new tsrc\vdbe.c
   829    845   	echo > .target_source
   830    846   
   831    847   sqlite3.c:	.target_source $(TOP)\tool\mksqlite3c.tcl
   832    848   	$(TCLSH_CMD) $(TOP)\tool\mksqlite3c.tcl
          849  +	copy tsrc\shell.c .
          850  +	copy tsrc\sqlite3ext.h .
   833    851   
   834    852   sqlite3-all.c:	sqlite3.c $(TOP)\tool\split-sqlite3c.tcl
   835    853   	$(TCLSH_CMD) $(TOP)\tool\split-sqlite3c.tcl
   836    854   
   837    855   # Rule to build the amalgamation
   838    856   #
   839    857   sqlite3.lo:	sqlite3.c
................................................................................
  1166   1184   
  1167   1185   fts3_tokenizer.lo:	$(TOP)\ext\fts3\fts3_tokenizer.c $(HDR) $(EXTHDR)
  1168   1186   	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenizer.c
  1169   1187   
  1170   1188   fts3_tokenizer1.lo:	$(TOP)\ext\fts3\fts3_tokenizer1.c $(HDR) $(EXTHDR)
  1171   1189   	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenizer1.c
  1172   1190   
         1191  +fts3_tokenize_vtab.lo:	$(TOP)\ext\fts3\fts3_tokenize_vtab.c $(HDR) $(EXTHDR)
         1192  +	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenize_vtab.c
         1193  +
  1173   1194   fts3_unicode.lo:	$(TOP)\ext\fts3\fts3_unicode.c $(HDR) $(EXTHDR)
  1174   1195   	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_unicode.c
  1175   1196   
  1176   1197   fts3_unicode2.lo:	$(TOP)\ext\fts3\fts3_unicode2.c $(HDR) $(EXTHDR)
  1177   1198   	$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_unicode2.c
  1178   1199   
  1179   1200   fts3_write.lo:	$(TOP)\ext\fts3\fts3_write.c $(HDR) $(EXTHDR)
................................................................................
  1189   1210   # fixture.  Otherwise link against libsqlite3.lib.  (This distinction is
  1190   1211   # necessary because the test fixture requires non-API symbols which are
  1191   1212   # hidden when the library is built via the amalgamation).
  1192   1213   #
  1193   1214   TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
  1194   1215   TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE
  1195   1216   
  1196         -TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.lib
  1197         -TESTFIXTURE_SRC1 = sqlite3.c
         1217  +TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2) libsqlite3.lib
         1218  +TESTFIXTURE_SRC1 = $(TESTEXT) sqlite3.c
  1198   1219   !IF $(USE_AMALGAMATION)==0
  1199   1220   TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC0)
  1200   1221   !ELSE
  1201   1222   TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC1)
  1202   1223   !ENDIF
  1203   1224   
  1204   1225   testfixture.exe:	$(TESTFIXTURE_SRC) $(LIBRESOBJS) $(HDR)
................................................................................
  1244   1265   	-rmdir /Q/S tsrc
  1245   1266   	del /Q .target_source
  1246   1267   	del /Q tclsqlite3.exe tclsqlite3.exp
  1247   1268   	del /Q testfixture.exe testfixture.exp test.db
  1248   1269   	del /Q sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def
  1249   1270   	del /Q sqlite3.c
  1250   1271   	del /Q sqlite3rc.h
         1272  +	del /Q shell.c sqlite3ext.h
  1251   1273   	del /Q sqlite3_analyzer.exe sqlite3_analyzer.exp sqlite3_analyzer.c
  1252   1274   	del /Q sqlite-*-output.vsix
         1275  +	del /Q mptester.exe
  1253   1276   
  1254   1277   # Dynamic link library section.
  1255   1278   #
  1256   1279   dll: sqlite3.dll
  1257   1280   
  1258   1281   sqlite3.def: libsqlite3.lib
  1259   1282   	echo EXPORTS > sqlite3.def
  1260   1283   	dumpbin /all libsqlite3.lib \
  1261   1284   		| $(NAWK) "/ 1 _?sqlite3_/ { sub(/^.* _?/,\"\");print }" \
  1262   1285   		| sort >> sqlite3.def
  1263   1286   
  1264   1287   sqlite3.dll: $(LIBOBJ) $(LIBRESOBJS) sqlite3.def
  1265   1288   	$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /DEF:sqlite3.def /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)

Changes to Makefile.vxworks.

   658    658   	rm -f lemon lempar.c parse.* sqlite*.tar.gz mkkeywordhash keywordhash.h
   659    659   	rm -f $(PUBLISH)
   660    660   	rm -f *.da *.bb *.bbg gmon.out
   661    661   	rm -rf quota2a quota2b quota2c
   662    662   	rm -rf tsrc target_source
   663    663   	rm -f testloadext.dll libtestloadext.so
   664    664   	rm -f sqlite3.c fts?amal.c tclsqlite3.c
          665  +	rm -f sqlite3rc.h
          666  +	rm -f shell.c sqlite3ext.h
   665    667   	rm -f $(SHPREFIX)sqlite3.$(SO)

Changes to VERSION.

     1         -3.7.16
            1  +3.7.17

Changes to configure.

     1      1   #! /bin/sh
     2      2   # Guess values for system-dependent variables and create Makefiles.
     3         -# Generated by GNU Autoconf 2.62 for sqlite 3.7.16.
            3  +# Generated by GNU Autoconf 2.62 for sqlite 3.7.17.
     4      4   #
     5      5   # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
     6      6   # 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
     7      7   # This configure script is free software; the Free Software Foundation
     8      8   # gives unlimited permission to copy, distribute and modify it.
     9      9   ## --------------------- ##
    10     10   ## M4sh Initialization.  ##
................................................................................
   739    739   MFLAGS=
   740    740   MAKEFLAGS=
   741    741   SHELL=${CONFIG_SHELL-/bin/sh}
   742    742   
   743    743   # Identity of this package.
   744    744   PACKAGE_NAME='sqlite'
   745    745   PACKAGE_TARNAME='sqlite'
   746         -PACKAGE_VERSION='3.7.16'
   747         -PACKAGE_STRING='sqlite 3.7.16'
          746  +PACKAGE_VERSION='3.7.17'
          747  +PACKAGE_STRING='sqlite 3.7.17'
   748    748   PACKAGE_BUGREPORT=''
   749    749   
   750    750   # Factoring default headers for most tests.
   751    751   ac_includes_default="\
   752    752   #include <stdio.h>
   753    753   #ifdef HAVE_SYS_TYPES_H
   754    754   # include <sys/types.h>
................................................................................
  1480   1480   #
  1481   1481   # Report the --help message.
  1482   1482   #
  1483   1483   if test "$ac_init_help" = "long"; then
  1484   1484     # Omit some internal or obsolete options to make the list less imposing.
  1485   1485     # This message is too long to be a string in the A/UX 3.1 sh.
  1486   1486     cat <<_ACEOF
  1487         -\`configure' configures sqlite 3.7.16 to adapt to many kinds of systems.
         1487  +\`configure' configures sqlite 3.7.17 to adapt to many kinds of systems.
  1488   1488   
  1489   1489   Usage: $0 [OPTION]... [VAR=VALUE]...
  1490   1490   
  1491   1491   To assign environment variables (e.g., CC, CFLAGS...), specify them as
  1492   1492   VAR=VALUE.  See below for descriptions of some of the useful variables.
  1493   1493   
  1494   1494   Defaults for the options are specified in brackets.
................................................................................
  1545   1545     --build=BUILD     configure for building on BUILD [guessed]
  1546   1546     --host=HOST       cross-compile to build programs to run on HOST [BUILD]
  1547   1547   _ACEOF
  1548   1548   fi
  1549   1549   
  1550   1550   if test -n "$ac_init_help"; then
  1551   1551     case $ac_init_help in
  1552         -     short | recursive ) echo "Configuration of sqlite 3.7.16:";;
         1552  +     short | recursive ) echo "Configuration of sqlite 3.7.17:";;
  1553   1553      esac
  1554   1554     cat <<\_ACEOF
  1555   1555   
  1556   1556   Optional Features:
  1557   1557     --disable-option-checking  ignore unrecognized --enable/--with options
  1558   1558     --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
  1559   1559     --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
................................................................................
  1661   1661       cd "$ac_pwd" || { ac_status=$?; break; }
  1662   1662     done
  1663   1663   fi
  1664   1664   
  1665   1665   test -n "$ac_init_help" && exit $ac_status
  1666   1666   if $ac_init_version; then
  1667   1667     cat <<\_ACEOF
  1668         -sqlite configure 3.7.16
         1668  +sqlite configure 3.7.17
  1669   1669   generated by GNU Autoconf 2.62
  1670   1670   
  1671   1671   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
  1672   1672   2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
  1673   1673   This configure script is free software; the Free Software Foundation
  1674   1674   gives unlimited permission to copy, distribute and modify it.
  1675   1675   _ACEOF
  1676   1676     exit
  1677   1677   fi
  1678   1678   cat >config.log <<_ACEOF
  1679   1679   This file contains any messages produced by compilers while
  1680   1680   running configure, to aid debugging if configure makes a mistake.
  1681   1681   
  1682         -It was created by sqlite $as_me 3.7.16, which was
         1682  +It was created by sqlite $as_me 3.7.17, which was
  1683   1683   generated by GNU Autoconf 2.62.  Invocation command line was
  1684   1684   
  1685   1685     $ $0 $@
  1686   1686   
  1687   1687   _ACEOF
  1688   1688   exec 5>>config.log
  1689   1689   {
................................................................................
 14028  14028   
 14029  14029   exec 6>&1
 14030  14030   
 14031  14031   # Save the log message, to keep $[0] and so on meaningful, and to
 14032  14032   # report actual input values of CONFIG_FILES etc. instead of their
 14033  14033   # values after options handling.
 14034  14034   ac_log="
 14035         -This file was extended by sqlite $as_me 3.7.16, which was
        14035  +This file was extended by sqlite $as_me 3.7.17, which was
 14036  14036   generated by GNU Autoconf 2.62.  Invocation command line was
 14037  14037   
 14038  14038     CONFIG_FILES    = $CONFIG_FILES
 14039  14039     CONFIG_HEADERS  = $CONFIG_HEADERS
 14040  14040     CONFIG_LINKS    = $CONFIG_LINKS
 14041  14041     CONFIG_COMMANDS = $CONFIG_COMMANDS
 14042  14042     $ $0 $@
................................................................................
 14081  14081   $config_commands
 14082  14082   
 14083  14083   Report bugs to <bug-autoconf@gnu.org>."
 14084  14084   
 14085  14085   _ACEOF
 14086  14086   cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 14087  14087   ac_cs_version="\\
 14088         -sqlite config.status 3.7.16
        14088  +sqlite config.status 3.7.17
 14089  14089   configured by $0, generated by GNU Autoconf 2.62,
 14090  14090     with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
 14091  14091   
 14092  14092   Copyright (C) 2008 Free Software Foundation, Inc.
 14093  14093   This config.status script is free software; the Free Software Foundation
 14094  14094   gives unlimited permission to copy, distribute and modify it."
 14095  14095   

Changes to ext/fts1/ft_hash.h.

     5      5   ** a legal notice, here is a blessing:
     6      6   **
     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12         -** This is the header file for the generic hash-table implemenation
           12  +** This is the header file for the generic hash-table implementation
    13     13   ** used in SQLite.  We've modified it slightly to serve as a standalone
    14     14   ** hash table implementation for the full-text indexing module.
    15     15   **
    16     16   */
    17     17   #ifndef _HASH_H_
    18     18   #define _HASH_H_
    19     19   

Changes to ext/fts1/fts1_hash.h.

     5      5   ** a legal notice, here is a blessing:
     6      6   **
     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12         -** This is the header file for the generic hash-table implemenation
           12  +** This is the header file for the generic hash-table implementation
    13     13   ** used in SQLite.  We've modified it slightly to serve as a standalone
    14     14   ** hash table implementation for the full-text indexing module.
    15     15   **
    16     16   */
    17     17   #ifndef _FTS1_HASH_H_
    18     18   #define _FTS1_HASH_H_
    19     19   

Changes to ext/fts2/fts2.c.

  6775   6775   void sqlite3Fts2SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule);
  6776   6776   void sqlite3Fts2PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule);
  6777   6777   void sqlite3Fts2IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule);
  6778   6778   
  6779   6779   int sqlite3Fts2InitHashTable(sqlite3 *, fts2Hash *, const char *);
  6780   6780   
  6781   6781   /*
  6782         -** Initialise the fts2 extension. If this extension is built as part
         6782  +** Initialize the fts2 extension. If this extension is built as part
  6783   6783   ** of the sqlite library, then this function is called directly by
  6784   6784   ** SQLite. If fts2 is built as a dynamically loadable extension, this
  6785   6785   ** function is called by the sqlite3_extension_init() entry point.
  6786   6786   */
  6787   6787   int sqlite3Fts2Init(sqlite3 *db){
  6788   6788     int rc = SQLITE_OK;
  6789   6789     fts2Hash *pHash = 0;
................................................................................
  6793   6793   
  6794   6794     sqlite3Fts2SimpleTokenizerModule(&pSimple);
  6795   6795     sqlite3Fts2PorterTokenizerModule(&pPorter);
  6796   6796   #ifdef SQLITE_ENABLE_ICU
  6797   6797     sqlite3Fts2IcuTokenizerModule(&pIcu);
  6798   6798   #endif
  6799   6799   
  6800         -  /* Allocate and initialise the hash-table used to store tokenizers. */
         6800  +  /* Allocate and initialize the hash-table used to store tokenizers. */
  6801   6801     pHash = sqlite3_malloc(sizeof(fts2Hash));
  6802   6802     if( !pHash ){
  6803   6803       rc = SQLITE_NOMEM;
  6804   6804     }else{
  6805   6805       sqlite3Fts2HashInit(pHash, FTS2_HASH_STRING, 1);
  6806   6806     }
  6807   6807   

Changes to ext/fts2/fts2_hash.h.

     5      5   ** a legal notice, here is a blessing:
     6      6   **
     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12         -** This is the header file for the generic hash-table implemenation
           12  +** This is the header file for the generic hash-table implementation
    13     13   ** used in SQLite.  We've modified it slightly to serve as a standalone
    14     14   ** hash table implementation for the full-text indexing module.
    15     15   **
    16     16   */
    17     17   #ifndef _FTS2_HASH_H_
    18     18   #define _FTS2_HASH_H_
    19     19   

Changes to ext/fts2/fts2_tokenizer.c.

   315    315   }
   316    316   
   317    317   #endif
   318    318   
   319    319   /*
   320    320   ** Set up SQL objects in database db used to access the contents of
   321    321   ** the hash table pointed to by argument pHash. The hash table must
   322         -** been initialised to use string keys, and to take a private copy 
          322  +** been initialized to use string keys, and to take a private copy 
   323    323   ** of the key when a value is inserted. i.e. by a call similar to:
   324    324   **
   325    325   **    sqlite3Fts2HashInit(pHash, FTS2_HASH_STRING, 1);
   326    326   **
   327    327   ** This function adds a scalar function (see header comment above
   328    328   ** scalarFunc() in this file for details) and, if ENABLE_TABLE is
   329    329   ** defined at compilation time, a temporary virtual table (see header 

Changes to ext/fts2/fts2_tokenizer.h.

    66     66     **
    67     67     ** then argc is set to 2, and the argv[] array contains pointers
    68     68     ** to the strings "arg1" and "arg2".
    69     69     **
    70     70     ** This method should return either SQLITE_OK (0), or an SQLite error 
    71     71     ** code. If SQLITE_OK is returned, then *ppTokenizer should be set
    72     72     ** to point at the newly created tokenizer structure. The generic
    73         -  ** sqlite3_tokenizer.pModule variable should not be initialised by
           73  +  ** sqlite3_tokenizer.pModule variable should not be initialized by
    74     74     ** this callback. The caller will do so.
    75     75     */
    76     76     int (*xCreate)(
    77     77       int argc,                           /* Size of argv array */
    78     78       const char *const*argv,             /* Tokenizer argument strings */
    79     79       sqlite3_tokenizer **ppTokenizer     /* OUT: Created tokenizer */
    80     80     );

Changes to ext/fts3/fts3.c.

  1567   1567         sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
  1568   1568         pCsr->isRequireSeek = 0;
  1569   1569         if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){
  1570   1570           return SQLITE_OK;
  1571   1571         }else{
  1572   1572           rc = sqlite3_reset(pCsr->pStmt);
  1573   1573           if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){
  1574         -          /* If no row was found and no error has occured, then the %_content
         1574  +          /* If no row was found and no error has occurred, then the %_content
  1575   1575             ** table is missing a row that is present in the full-text index.
  1576   1576             ** The data structures are corrupt.  */
  1577   1577             rc = FTS_CORRUPT_VTAB;
  1578   1578             pCsr->isEof = 1;
  1579   1579           }
  1580   1580         }
  1581   1581       }
................................................................................
  2807   2807   */
  2808   2808   static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
  2809   2809     sqlite3Fts3SegReaderFinish(pSegcsr);
  2810   2810     sqlite3_free(pSegcsr);
  2811   2811   }
  2812   2812   
  2813   2813   /*
  2814         -** This function retreives the doclist for the specified term (or term
         2814  +** This function retrieves the doclist for the specified term (or term
  2815   2815   ** prefix) from the database.
  2816   2816   */
  2817   2817   static int fts3TermSelect(
  2818   2818     Fts3Table *p,                   /* Virtual table handle */
  2819   2819     Fts3PhraseToken *pTok,          /* Token to query for */
  2820   2820     int iColumn,                    /* Column to query (or -ve for all columns) */
  2821   2821     int *pnOut,                     /* OUT: Size of buffer at *ppOut */
................................................................................
  2971   2971       if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
  2972   2972         return SQLITE_NOMEM;
  2973   2973       }
  2974   2974   
  2975   2975       pCsr->iLangid = 0;
  2976   2976       if( nVal==2 ) pCsr->iLangid = sqlite3_value_int(apVal[1]);
  2977   2977   
         2978  +    assert( p->base.zErrMsg==0 );
  2978   2979       rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid,
  2979         -        p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr
         2980  +        p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr, 
         2981  +        &p->base.zErrMsg
  2980   2982       );
  2981   2983       if( rc!=SQLITE_OK ){
  2982         -      if( rc==SQLITE_ERROR ){
  2983         -        static const char *zErr = "malformed MATCH expression: [%s]";
  2984         -        p->base.zErrMsg = sqlite3_mprintf(zErr, zQuery);
  2985         -      }
  2986   2984         return rc;
  2987   2985       }
  2988   2986   
  2989   2987       rc = sqlite3Fts3ReadLock(p);
  2990   2988       if( rc!=SQLITE_OK ) return rc;
  2991   2989   
  2992   2990       rc = fts3EvalStart(pCsr);
................................................................................
  3558   3556   void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const**ppModule);
  3559   3557   #endif
  3560   3558   #ifdef SQLITE_ENABLE_ICU
  3561   3559   void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule);
  3562   3560   #endif
  3563   3561   
  3564   3562   /*
  3565         -** Initialise the fts3 extension. If this extension is built as part
         3563  +** Initialize the fts3 extension. If this extension is built as part
  3566   3564   ** of the sqlite library, then this function is called directly by
  3567   3565   ** SQLite. If fts3 is built as a dynamically loadable extension, this
  3568   3566   ** function is called by the sqlite3_extension_init() entry point.
  3569   3567   */
  3570   3568   int sqlite3Fts3Init(sqlite3 *db){
  3571   3569     int rc = SQLITE_OK;
  3572   3570     Fts3Hash *pHash = 0;
................................................................................
  3592   3590   
  3593   3591     rc = sqlite3Fts3InitAux(db);
  3594   3592     if( rc!=SQLITE_OK ) return rc;
  3595   3593   
  3596   3594     sqlite3Fts3SimpleTokenizerModule(&pSimple);
  3597   3595     sqlite3Fts3PorterTokenizerModule(&pPorter);
  3598   3596   
  3599         -  /* Allocate and initialise the hash-table used to store tokenizers. */
         3597  +  /* Allocate and initialize the hash-table used to store tokenizers. */
  3600   3598     pHash = sqlite3_malloc(sizeof(Fts3Hash));
  3601   3599     if( !pHash ){
  3602   3600       rc = SQLITE_NOMEM;
  3603   3601     }else{
  3604   3602       sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1);
  3605   3603     }
  3606   3604   
................................................................................
  3642   3640           db, "fts3", &fts3Module, (void *)pHash, hashDestroy
  3643   3641       );
  3644   3642       if( rc==SQLITE_OK ){
  3645   3643         rc = sqlite3_create_module_v2(
  3646   3644             db, "fts4", &fts3Module, (void *)pHash, 0
  3647   3645         );
  3648   3646       }
         3647  +    if( rc==SQLITE_OK ){
         3648  +      rc = sqlite3Fts3InitTok(db, (void *)pHash);
         3649  +    }
  3649   3650       return rc;
  3650   3651     }
         3652  +
  3651   3653   
  3652   3654     /* An error has occurred. Delete the hash table and return the error code. */
  3653   3655     assert( rc!=SQLITE_OK );
  3654   3656     if( pHash ){
  3655   3657       sqlite3Fts3HashClear(pHash);
  3656   3658       sqlite3_free(pHash);
  3657   3659     }
................................................................................
  5191   5193   ** must be of type FTSQUERY_PHRASE. 
  5192   5194   **
  5193   5195   ** The returned value is either NULL or a pointer to a buffer containing
  5194   5196   ** a position-list indicating the occurrences of the phrase in column iCol
  5195   5197   ** of the current row. 
  5196   5198   **
  5197   5199   ** More specifically, the returned buffer contains 1 varint for each 
  5198         -** occurence of the phrase in the column, stored using the normal (delta+2) 
         5200  +** occurrence of the phrase in the column, stored using the normal (delta+2) 
  5199   5201   ** compression and is terminated by either an 0x01 or 0x00 byte. For example,
  5200   5202   ** if the requested column contains "a b X c d X X" and the position-list
  5201   5203   ** for 'X' is requested, the buffer returned may contain:
  5202   5204   **
  5203   5205   **     0x04 0x05 0x03 0x01   or   0x04 0x05 0x03 0x00
  5204   5206   **
  5205   5207   ** This function works regardless of whether or not the phrase is deferred,

Changes to ext/fts3/fts3Int.h.

   520    520   void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *,
   521    521     const char *, const char *, int, int
   522    522   );
   523    523   void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *);
   524    524   
   525    525   /* fts3_expr.c */
   526    526   int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int,
   527         -  char **, int, int, int, const char *, int, Fts3Expr **
          527  +  char **, int, int, int, const char *, int, Fts3Expr **, char **
   528    528   );
   529    529   void sqlite3Fts3ExprFree(Fts3Expr *);
   530    530   #ifdef SQLITE_TEST
   531    531   int sqlite3Fts3ExprInitTestInterface(sqlite3 *db);
   532    532   int sqlite3Fts3InitTerm(sqlite3 *db);
   533    533   #endif
   534    534   
................................................................................
   545    545       Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
   546    546   int sqlite3Fts3MsrIncrNext(
   547    547       Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *);
   548    548   int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **); 
   549    549   int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
   550    550   int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
   551    551   
          552  +/* fts3_tokenize_vtab.c */
          553  +int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *);
          554  +
   552    555   /* fts3_unicode2.c (functions generated by parsing unicode text files) */
   553    556   #ifdef SQLITE_ENABLE_FTS4_UNICODE61
   554    557   int sqlite3FtsUnicodeFold(int, int);
   555    558   int sqlite3FtsUnicodeIsalnum(int);
   556    559   int sqlite3FtsUnicodeIsdiacritic(int);
   557    560   #endif
   558    561   
   559    562   #endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */
   560    563   #endif /* _FTSINT_H */

Changes to ext/fts3/fts3_aux.c.

    66     66     int nFts3;                      /* Result of strlen(zFts3) */
    67     67     int nByte;                      /* Bytes of space to allocate here */
    68     68     int rc;                         /* value returned by declare_vtab() */
    69     69     Fts3auxTable *p;                /* Virtual table object to return */
    70     70   
    71     71     UNUSED_PARAMETER(pUnused);
    72     72   
    73         -  /* The user should specify a single argument - the name of an fts3 table. */
    74         -  if( argc!=4 ){
    75         -    *pzErr = sqlite3_mprintf(
    76         -        "wrong number of arguments to fts4aux constructor"
    77         -    );
    78         -    return SQLITE_ERROR;
    79         -  }
           73  +  /* The user should invoke this in one of two forms:
           74  +  **
           75  +  **     CREATE VIRTUAL TABLE xxx USING fts4aux(fts4-table);
           76  +  **     CREATE VIRTUAL TABLE xxx USING fts4aux(fts4-table-db, fts4-table);
           77  +  */
           78  +  if( argc!=4 && argc!=5 ) goto bad_args;
    80     79   
    81     80     zDb = argv[1]; 
    82     81     nDb = (int)strlen(zDb);
    83         -  zFts3 = argv[3];
           82  +  if( argc==5 ){
           83  +    if( nDb==4 && 0==sqlite3_strnicmp("temp", zDb, 4) ){
           84  +      zDb = argv[3]; 
           85  +      nDb = (int)strlen(zDb);
           86  +      zFts3 = argv[4];
           87  +    }else{
           88  +      goto bad_args;
           89  +    }
           90  +  }else{
           91  +    zFts3 = argv[3];
           92  +  }
    84     93     nFts3 = (int)strlen(zFts3);
    85     94   
    86     95     rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA);
    87     96     if( rc!=SQLITE_OK ) return rc;
    88     97   
    89     98     nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
    90     99     p = (Fts3auxTable *)sqlite3_malloc(nByte);
................................................................................
    99    108   
   100    109     memcpy((char *)p->pFts3Tab->zDb, zDb, nDb);
   101    110     memcpy((char *)p->pFts3Tab->zName, zFts3, nFts3);
   102    111     sqlite3Fts3Dequote((char *)p->pFts3Tab->zName);
   103    112   
   104    113     *ppVtab = (sqlite3_vtab *)p;
   105    114     return SQLITE_OK;
          115  +
          116  + bad_args:
          117  +  *pzErr = sqlite3_mprintf("invalid arguments to fts4aux constructor");
          118  +  return SQLITE_ERROR;
   106    119   }
   107    120   
   108    121   /*
   109    122   ** This function does the work for both the xDisconnect and xDestroy methods.
   110    123   ** These tables have no persistent representation of their own, so xDisconnect
   111    124   ** and xDestroy are identical operations.
   112    125   */

Changes to ext/fts3/fts3_expr.c.

   102    102     int nNest;                          /* Number of nested brackets */
   103    103   };
   104    104   
   105    105   /*
   106    106   ** This function is equivalent to the standard isspace() function. 
   107    107   **
   108    108   ** The standard isspace() can be awkward to use safely, because although it
   109         -** is defined to accept an argument of type int, its behaviour when passed
          109  +** is defined to accept an argument of type int, its behavior when passed
   110    110   ** an integer that falls outside of the range of the unsigned char type
   111    111   ** is undefined (and sometimes, "undefined" means segfault). This wrapper
   112    112   ** is defined to accept an argument of type char, and always returns 0 for
   113    113   ** any values that fall outside of the range of the unsigned char type (i.e.
   114    114   ** negative values).
   115    115   */
   116    116   static int fts3isspace(char c){
................................................................................
   636    636           if( !pNot ){
   637    637             sqlite3Fts3ExprFree(p);
   638    638             rc = SQLITE_NOMEM;
   639    639             goto exprparse_out;
   640    640           }
   641    641           pNot->eType = FTSQUERY_NOT;
   642    642           pNot->pRight = p;
          643  +        p->pParent = pNot;
   643    644           if( pNotBranch ){
   644    645             pNot->pLeft = pNotBranch;
          646  +          pNotBranch->pParent = pNot;
   645    647           }
   646    648           pNotBranch = pNot;
   647    649           p = pPrev;
   648    650         }else{
   649    651           int eType = p->eType;
   650    652           isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft);
   651    653   
................................................................................
   725    727           rc = SQLITE_ERROR;
   726    728         }else{
   727    729           Fts3Expr *pIter = pNotBranch;
   728    730           while( pIter->pLeft ){
   729    731             pIter = pIter->pLeft;
   730    732           }
   731    733           pIter->pLeft = pRet;
          734  +        pRet->pParent = pIter;
   732    735           pRet = pNotBranch;
   733    736         }
   734    737       }
   735    738     }
   736    739     *pnConsumed = n - nIn;
   737    740   
   738    741   exprparse_out:
................................................................................
   740    743       sqlite3Fts3ExprFree(pRet);
   741    744       sqlite3Fts3ExprFree(pNotBranch);
   742    745       pRet = 0;
   743    746     }
   744    747     *ppExpr = pRet;
   745    748     return rc;
   746    749   }
          750  +
          751  +/*
          752  +** Return SQLITE_ERROR if the maximum depth of the expression tree passed 
          753  +** as the only argument is more than nMaxDepth.
          754  +*/
          755  +static int fts3ExprCheckDepth(Fts3Expr *p, int nMaxDepth){
          756  +  int rc = SQLITE_OK;
          757  +  if( p ){
          758  +    if( nMaxDepth<0 ){ 
          759  +      rc = SQLITE_TOOBIG;
          760  +    }else{
          761  +      rc = fts3ExprCheckDepth(p->pLeft, nMaxDepth-1);
          762  +      if( rc==SQLITE_OK ){
          763  +        rc = fts3ExprCheckDepth(p->pRight, nMaxDepth-1);
          764  +      }
          765  +    }
          766  +  }
          767  +  return rc;
          768  +}
          769  +
          770  +/*
          771  +** This function attempts to transform the expression tree at (*pp) to
          772  +** an equivalent but more balanced form. The tree is modified in place.
          773  +** If successful, SQLITE_OK is returned and (*pp) set to point to the 
          774  +** new root expression node. 
          775  +**
          776  +** nMaxDepth is the maximum allowable depth of the balanced sub-tree.
          777  +**
          778  +** Otherwise, if an error occurs, an SQLite error code is returned and 
          779  +** expression (*pp) freed.
          780  +*/
          781  +static int fts3ExprBalance(Fts3Expr **pp, int nMaxDepth){
          782  +  int rc = SQLITE_OK;             /* Return code */
          783  +  Fts3Expr *pRoot = *pp;          /* Initial root node */
          784  +  Fts3Expr *pFree = 0;            /* List of free nodes. Linked by pParent. */
          785  +  int eType = pRoot->eType;       /* Type of node in this tree */
          786  +
          787  +  if( nMaxDepth==0 ){
          788  +    rc = SQLITE_ERROR;
          789  +  }
          790  +
          791  +  if( rc==SQLITE_OK && (eType==FTSQUERY_AND || eType==FTSQUERY_OR) ){
          792  +    Fts3Expr **apLeaf;
          793  +    apLeaf = (Fts3Expr **)sqlite3_malloc(sizeof(Fts3Expr *) * nMaxDepth);
          794  +    if( 0==apLeaf ){
          795  +      rc = SQLITE_NOMEM;
          796  +    }else{
          797  +      memset(apLeaf, 0, sizeof(Fts3Expr *) * nMaxDepth);
          798  +    }
          799  +
          800  +    if( rc==SQLITE_OK ){
          801  +      int i;
          802  +      Fts3Expr *p;
          803  +
          804  +      /* Set $p to point to the left-most leaf in the tree of eType nodes. */
          805  +      for(p=pRoot; p->eType==eType; p=p->pLeft){
          806  +        assert( p->pParent==0 || p->pParent->pLeft==p );
          807  +        assert( p->pLeft && p->pRight );
          808  +      }
          809  +
          810  +      /* This loop runs once for each leaf in the tree of eType nodes. */
          811  +      while( 1 ){
          812  +        int iLvl;
          813  +        Fts3Expr *pParent = p->pParent;     /* Current parent of p */
          814  +
          815  +        assert( pParent==0 || pParent->pLeft==p );
          816  +        p->pParent = 0;
          817  +        if( pParent ){
          818  +          pParent->pLeft = 0;
          819  +        }else{
          820  +          pRoot = 0;
          821  +        }
          822  +        rc = fts3ExprBalance(&p, nMaxDepth-1);
          823  +        if( rc!=SQLITE_OK ) break;
          824  +
          825  +        for(iLvl=0; p && iLvl<nMaxDepth; iLvl++){
          826  +          if( apLeaf[iLvl]==0 ){
          827  +            apLeaf[iLvl] = p;
          828  +            p = 0;
          829  +          }else{
          830  +            assert( pFree );
          831  +            pFree->pLeft = apLeaf[iLvl];
          832  +            pFree->pRight = p;
          833  +            pFree->pLeft->pParent = pFree;
          834  +            pFree->pRight->pParent = pFree;
          835  +
          836  +            p = pFree;
          837  +            pFree = pFree->pParent;
          838  +            p->pParent = 0;
          839  +            apLeaf[iLvl] = 0;
          840  +          }
          841  +        }
          842  +        if( p ){
          843  +          sqlite3Fts3ExprFree(p);
          844  +          rc = SQLITE_TOOBIG;
          845  +          break;
          846  +        }
          847  +
          848  +        /* If that was the last leaf node, break out of the loop */
          849  +        if( pParent==0 ) break;
          850  +
          851  +        /* Set $p to point to the next leaf in the tree of eType nodes */
          852  +        for(p=pParent->pRight; p->eType==eType; p=p->pLeft);
          853  +
          854  +        /* Remove pParent from the original tree. */
          855  +        assert( pParent->pParent==0 || pParent->pParent->pLeft==pParent );
          856  +        pParent->pRight->pParent = pParent->pParent;
          857  +        if( pParent->pParent ){
          858  +          pParent->pParent->pLeft = pParent->pRight;
          859  +        }else{
          860  +          assert( pParent==pRoot );
          861  +          pRoot = pParent->pRight;
          862  +        }
          863  +
          864  +        /* Link pParent into the free node list. It will be used as an
          865  +        ** internal node of the new tree.  */
          866  +        pParent->pParent = pFree;
          867  +        pFree = pParent;
          868  +      }
          869  +
          870  +      if( rc==SQLITE_OK ){
          871  +        p = 0;
          872  +        for(i=0; i<nMaxDepth; i++){
          873  +          if( apLeaf[i] ){
          874  +            if( p==0 ){
          875  +              p = apLeaf[i];
          876  +              p->pParent = 0;
          877  +            }else{
          878  +              assert( pFree!=0 );
          879  +              pFree->pRight = p;
          880  +              pFree->pLeft = apLeaf[i];
          881  +              pFree->pLeft->pParent = pFree;
          882  +              pFree->pRight->pParent = pFree;
          883  +
          884  +              p = pFree;
          885  +              pFree = pFree->pParent;
          886  +              p->pParent = 0;
          887  +            }
          888  +          }
          889  +        }
          890  +        pRoot = p;
          891  +      }else{
          892  +        /* An error occurred. Delete the contents of the apLeaf[] array 
          893  +        ** and pFree list. Everything else is cleaned up by the call to
          894  +        ** sqlite3Fts3ExprFree(pRoot) below.  */
          895  +        Fts3Expr *pDel;
          896  +        for(i=0; i<nMaxDepth; i++){
          897  +          sqlite3Fts3ExprFree(apLeaf[i]);
          898  +        }
          899  +        while( (pDel=pFree)!=0 ){
          900  +          pFree = pDel->pParent;
          901  +          sqlite3_free(pDel);
          902  +        }
          903  +      }
          904  +
          905  +      assert( pFree==0 );
          906  +      sqlite3_free( apLeaf );
          907  +    }
          908  +  }
          909  +
          910  +  if( rc!=SQLITE_OK ){
          911  +    sqlite3Fts3ExprFree(pRoot);
          912  +    pRoot = 0;
          913  +  }
          914  +  *pp = pRoot;
          915  +  return rc;
          916  +}
          917  +
          918  +/*
          919  +** This function is similar to sqlite3Fts3ExprParse(), with the following
          920  +** differences:
          921  +**
          922  +**   1. It does not do expression rebalancing.
          923  +**   2. It does not check that the expression does not exceed the 
          924  +**      maximum allowable depth.
          925  +**   3. Even if it fails, *ppExpr may still be set to point to an 
          926  +**      expression tree. It should be deleted using sqlite3Fts3ExprFree()
          927  +**      in this case.
          928  +*/
          929  +static int fts3ExprParseUnbalanced(
          930  +  sqlite3_tokenizer *pTokenizer,      /* Tokenizer module */
          931  +  int iLangid,                        /* Language id for tokenizer */
          932  +  char **azCol,                       /* Array of column names for fts3 table */
          933  +  int bFts4,                          /* True to allow FTS4-only syntax */
          934  +  int nCol,                           /* Number of entries in azCol[] */
          935  +  int iDefaultCol,                    /* Default column to query */
          936  +  const char *z, int n,               /* Text of MATCH query */
          937  +  Fts3Expr **ppExpr                   /* OUT: Parsed query structure */
          938  +){
          939  +  int nParsed;
          940  +  int rc;
          941  +  ParseContext sParse;
          942  +
          943  +  memset(&sParse, 0, sizeof(ParseContext));
          944  +  sParse.pTokenizer = pTokenizer;
          945  +  sParse.iLangid = iLangid;
          946  +  sParse.azCol = (const char **)azCol;
          947  +  sParse.nCol = nCol;
          948  +  sParse.iDefaultCol = iDefaultCol;
          949  +  sParse.bFts4 = bFts4;
          950  +  if( z==0 ){
          951  +    *ppExpr = 0;
          952  +    return SQLITE_OK;
          953  +  }
          954  +  if( n<0 ){
          955  +    n = (int)strlen(z);
          956  +  }
          957  +  rc = fts3ExprParse(&sParse, z, n, ppExpr, &nParsed);
          958  +  assert( rc==SQLITE_OK || *ppExpr==0 );
          959  +
          960  +  /* Check for mismatched parenthesis */
          961  +  if( rc==SQLITE_OK && sParse.nNest ){
          962  +    rc = SQLITE_ERROR;
          963  +  }
          964  +  
          965  +  return rc;
          966  +}
   747    967   
   748    968   /*
   749    969   ** Parameters z and n contain a pointer to and length of a buffer containing
   750    970   ** an fts3 query expression, respectively. This function attempts to parse the
   751    971   ** query expression and create a tree of Fts3Expr structures representing the
   752    972   ** parsed expression. If successful, *ppExpr is set to point to the head
   753    973   ** of the parsed expression tree and SQLITE_OK is returned. If an error
................................................................................
   773    993     sqlite3_tokenizer *pTokenizer,      /* Tokenizer module */
   774    994     int iLangid,                        /* Language id for tokenizer */
   775    995     char **azCol,                       /* Array of column names for fts3 table */
   776    996     int bFts4,                          /* True to allow FTS4-only syntax */
   777    997     int nCol,                           /* Number of entries in azCol[] */
   778    998     int iDefaultCol,                    /* Default column to query */
   779    999     const char *z, int n,               /* Text of MATCH query */
   780         -  Fts3Expr **ppExpr                   /* OUT: Parsed query structure */
         1000  +  Fts3Expr **ppExpr,                  /* OUT: Parsed query structure */
         1001  +  char **pzErr                        /* OUT: Error message (sqlite3_malloc) */
   781   1002   ){
   782         -  int nParsed;
   783         -  int rc;
   784         -  ParseContext sParse;
         1003  +  static const int MAX_EXPR_DEPTH = 12;
         1004  +  int rc = fts3ExprParseUnbalanced(
         1005  +      pTokenizer, iLangid, azCol, bFts4, nCol, iDefaultCol, z, n, ppExpr
         1006  +  );
         1007  +  
         1008  +  /* Rebalance the expression. And check that its depth does not exceed
         1009  +  ** MAX_EXPR_DEPTH.  */
         1010  +  if( rc==SQLITE_OK && *ppExpr ){
         1011  +    rc = fts3ExprBalance(ppExpr, MAX_EXPR_DEPTH);
         1012  +    if( rc==SQLITE_OK ){
         1013  +      rc = fts3ExprCheckDepth(*ppExpr, MAX_EXPR_DEPTH);
         1014  +    }
         1015  +  }
   785   1016   
   786         -  memset(&sParse, 0, sizeof(ParseContext));
   787         -  sParse.pTokenizer = pTokenizer;
   788         -  sParse.iLangid = iLangid;
   789         -  sParse.azCol = (const char **)azCol;
   790         -  sParse.nCol = nCol;
   791         -  sParse.iDefaultCol = iDefaultCol;
   792         -  sParse.bFts4 = bFts4;
   793         -  if( z==0 ){
   794         -    *ppExpr = 0;
   795         -    return SQLITE_OK;
   796         -  }
   797         -  if( n<0 ){
   798         -    n = (int)strlen(z);
   799         -  }
   800         -  rc = fts3ExprParse(&sParse, z, n, ppExpr, &nParsed);
   801         -
   802         -  /* Check for mismatched parenthesis */
   803         -  if( rc==SQLITE_OK && sParse.nNest ){
   804         -    rc = SQLITE_ERROR;
         1017  +  if( rc!=SQLITE_OK ){
   805   1018       sqlite3Fts3ExprFree(*ppExpr);
   806   1019       *ppExpr = 0;
         1020  +    if( rc==SQLITE_TOOBIG ){
         1021  +      *pzErr = sqlite3_mprintf(
         1022  +          "FTS expression tree is too large (maximum depth %d)", MAX_EXPR_DEPTH
         1023  +      );
         1024  +      rc = SQLITE_ERROR;
         1025  +    }else if( rc==SQLITE_ERROR ){
         1026  +      *pzErr = sqlite3_mprintf("malformed MATCH expression: [%s]", z);
         1027  +    }
   807   1028     }
   808   1029   
   809   1030     return rc;
   810   1031   }
         1032  +
         1033  +/*
         1034  +** Free a single node of an expression tree.
         1035  +*/
         1036  +static void fts3FreeExprNode(Fts3Expr *p){
         1037  +  assert( p->eType==FTSQUERY_PHRASE || p->pPhrase==0 );
         1038  +  sqlite3Fts3EvalPhraseCleanup(p->pPhrase);
         1039  +  sqlite3_free(p->aMI);
         1040  +  sqlite3_free(p);
         1041  +}
   811   1042   
   812   1043   /*
   813   1044   ** Free a parsed fts3 query expression allocated by sqlite3Fts3ExprParse().
         1045  +**
         1046  +** This function would be simpler if it recursively called itself. But
         1047  +** that would mean passing a sufficiently large expression to ExprParse()
         1048  +** could cause a stack overflow.
   814   1049   */
   815         -void sqlite3Fts3ExprFree(Fts3Expr *p){
   816         -  if( p ){
   817         -    assert( p->eType==FTSQUERY_PHRASE || p->pPhrase==0 );
   818         -    sqlite3Fts3ExprFree(p->pLeft);
   819         -    sqlite3Fts3ExprFree(p->pRight);
   820         -    sqlite3Fts3EvalPhraseCleanup(p->pPhrase);
   821         -    sqlite3_free(p->aMI);
   822         -    sqlite3_free(p);
         1050  +void sqlite3Fts3ExprFree(Fts3Expr *pDel){
         1051  +  Fts3Expr *p;
         1052  +  assert( pDel==0 || pDel->pParent==0 );
         1053  +  for(p=pDel; p && (p->pLeft||p->pRight); p=(p->pLeft ? p->pLeft : p->pRight)){
         1054  +    assert( p->pParent==0 || p==p->pParent->pRight || p==p->pParent->pLeft );
         1055  +  }
         1056  +  while( p ){
         1057  +    Fts3Expr *pParent = p->pParent;
         1058  +    fts3FreeExprNode(p);
         1059  +    if( pParent && p==pParent->pLeft && pParent->pRight ){
         1060  +      p = pParent->pRight;
         1061  +      while( p && (p->pLeft || p->pRight) ){
         1062  +        assert( p==p->pParent->pRight || p==p->pParent->pLeft );
         1063  +        p = (p->pLeft ? p->pLeft : p->pRight);
         1064  +      }
         1065  +    }else{
         1066  +      p = pParent;
         1067  +    }
   823   1068     }
   824   1069   }
   825   1070   
   826   1071   /****************************************************************************
   827   1072   *****************************************************************************
   828   1073   ** Everything after this point is just test code.
   829   1074   */
................................................................................
   867   1112   ** sqlite3_free() to release the memory. If an OOM condition is encountered,
   868   1113   ** NULL is returned.
   869   1114   **
   870   1115   ** If the second argument is not NULL, then its contents are prepended to 
   871   1116   ** the returned expression text and then freed using sqlite3_free().
   872   1117   */
   873   1118   static char *exprToString(Fts3Expr *pExpr, char *zBuf){
         1119  +  if( pExpr==0 ){
         1120  +    return sqlite3_mprintf("");
         1121  +  }
   874   1122     switch( pExpr->eType ){
   875   1123       case FTSQUERY_PHRASE: {
   876   1124         Fts3Phrase *pPhrase = pExpr->pPhrase;
   877   1125         int i;
   878   1126         zBuf = sqlite3_mprintf(
   879   1127             "%zPHRASE %d 0", zBuf, pPhrase->iColumn);
   880   1128         for(i=0; zBuf && i<pPhrase->nToken; i++){
................................................................................
   974   1222       sqlite3_result_error_nomem(context);
   975   1223       goto exprtest_out;
   976   1224     }
   977   1225     for(ii=0; ii<nCol; ii++){
   978   1226       azCol[ii] = (char *)sqlite3_value_text(argv[ii+2]);
   979   1227     }
   980   1228   
   981         -  rc = sqlite3Fts3ExprParse(
   982         -      pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr
   983         -  );
         1229  +  if( sqlite3_user_data(context) ){
         1230  +    char *zDummy = 0;
         1231  +    rc = sqlite3Fts3ExprParse(
         1232  +        pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr, &zDummy
         1233  +    );
         1234  +    assert( rc==SQLITE_OK || pExpr==0 );
         1235  +    sqlite3_free(zDummy);
         1236  +  }else{
         1237  +    rc = fts3ExprParseUnbalanced(
         1238  +        pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr
         1239  +    );
         1240  +  }
         1241  +
   984   1242     if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){
         1243  +    sqlite3Fts3ExprFree(pExpr);
   985   1244       sqlite3_result_error(context, "Error parsing expression", -1);
   986   1245     }else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){
   987   1246       sqlite3_result_error_nomem(context);
   988   1247     }else{
   989   1248       sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
   990   1249       sqlite3_free(zBuf);
   991   1250     }
................................................................................
  1000   1259   }
  1001   1260   
  1002   1261   /*
  1003   1262   ** Register the query expression parser test function fts3_exprtest() 
  1004   1263   ** with database connection db. 
  1005   1264   */
  1006   1265   int sqlite3Fts3ExprInitTestInterface(sqlite3* db){
  1007         -  return sqlite3_create_function(
         1266  +  int rc = sqlite3_create_function(
  1008   1267         db, "fts3_exprtest", -1, SQLITE_UTF8, 0, fts3ExprTest, 0, 0
  1009   1268     );
         1269  +  if( rc==SQLITE_OK ){
         1270  +    rc = sqlite3_create_function(db, "fts3_exprtest_rebalance", 
         1271  +        -1, SQLITE_UTF8, (void *)1, fts3ExprTest, 0, 0
         1272  +    );
         1273  +  }
         1274  +  return rc;
  1010   1275   }
  1011   1276   
  1012   1277   #endif
  1013   1278   #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */

Changes to ext/fts3/fts3_hash.h.

     5      5   ** a legal notice, here is a blessing:
     6      6   **
     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12         -** This is the header file for the generic hash-table implemenation
           12  +** This is the header file for the generic hash-table implementation
    13     13   ** used in SQLite.  We've modified it slightly to serve as a standalone
    14     14   ** hash table implementation for the full-text indexing module.
    15     15   **
    16     16   */
    17     17   #ifndef _FTS3_HASH_H_
    18     18   #define _FTS3_HASH_H_
    19     19   

Changes to ext/fts3/fts3_snippet.c.

   385    385   
   386    386   /*
   387    387   ** Select the fragment of text consisting of nFragment contiguous tokens 
   388    388   ** from column iCol that represent the "best" snippet. The best snippet
   389    389   ** is the snippet with the highest score, where scores are calculated
   390    390   ** by adding:
   391    391   **
   392         -**   (a) +1 point for each occurence of a matchable phrase in the snippet.
          392  +**   (a) +1 point for each occurrence of a matchable phrase in the snippet.
   393    393   **
   394         -**   (b) +1000 points for the first occurence of each matchable phrase in 
          394  +**   (b) +1000 points for the first occurrence of each matchable phrase in 
   395    395   **       the snippet for which the corresponding mCovered bit is not set.
   396    396   **
   397    397   ** The selected snippet parameters are stored in structure *pFragment before
   398    398   ** returning. The score of the selected snippet is stored in *piScore
   399    399   ** before returning.
   400    400   */
   401    401   static int fts3BestSnippet(

Changes to ext/fts3/fts3_test.c.

   263    263   **
   264    264   ** If present, the first argument is the chunksize in bytes to load doclists
   265    265   ** in. The second argument is the minimum doclist size in bytes to use
   266    266   ** incremental loading with.
   267    267   **
   268    268   ** Whether or not the arguments are present, this command returns a list of
   269    269   ** two integers - the initial chunksize and threshold when the command is
   270         -** invoked. This can be used to restore the default behaviour after running
          270  +** invoked. This can be used to restore the default behavior after running
   271    271   ** tests. For example:
   272    272   **
   273    273   **    # Override incr-load settings for testing:
   274    274   **    set cfg [fts3_configure_incr_load $new_chunksize $new_threshold]
   275    275   **
   276    276   **    .... run tests ....
   277    277   **

Added ext/fts3/fts3_tokenize_vtab.c.

            1  +/*
            2  +** 2013 Apr 22
            3  +**
            4  +** The author disclaims copyright to this source code.  In place of
            5  +** a legal notice, here is a blessing:
            6  +**
            7  +**    May you do good and not evil.
            8  +**    May you find forgiveness for yourself and forgive others.
            9  +**    May you share freely, never taking more than you give.
           10  +**
           11  +******************************************************************************
           12  +**
           13  +** This file contains code for the "fts3tokenize" virtual table module.
           14  +** An fts3tokenize virtual table is created as follows:
           15  +**
           16  +**   CREATE VIRTUAL TABLE <tbl> USING fts3tokenize(
           17  +**       <tokenizer-name>, <arg-1>, ...
           18  +**   );
           19  +**
           20  +** The table created has the following schema:
           21  +**
           22  +**   CREATE TABLE <tbl>(input, token, start, end, position)
           23  +**
           24  +** When queried, the query must include a WHERE clause of type:
           25  +**
           26  +**   input = <string>
           27  +**
           28  +** The virtual table module tokenizes this <string>, using the FTS3 
           29  +** tokenizer specified by the arguments to the CREATE VIRTUAL TABLE 
           30  +** statement and returns one row for each token in the result. With
           31  +** fields set as follows:
           32  +**
           33  +**   input:   Always set to a copy of <string>
           34  +**   token:   A token from the input.
           35  +**   start:   Byte offset of the token within the input <string>.
           36  +**   end:     Byte offset of the byte immediately following the end of the
           37  +**            token within the input string.
           38  +**   pos:     Token offset of token within input.
           39  +**
           40  +*/
           41  +#include "fts3Int.h"
           42  +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
           43  +
           44  +#include <string.h>
           45  +#include <assert.h>
           46  +
           47  +typedef struct Fts3tokTable Fts3tokTable;
           48  +typedef struct Fts3tokCursor Fts3tokCursor;
           49  +
           50  +/*
           51  +** Virtual table structure.
           52  +*/
           53  +struct Fts3tokTable {
           54  +  sqlite3_vtab base;              /* Base class used by SQLite core */
           55  +  const sqlite3_tokenizer_module *pMod;
           56  +  sqlite3_tokenizer *pTok;
           57  +};
           58  +
           59  +/*
           60  +** Virtual table cursor structure.
           61  +*/
           62  +struct Fts3tokCursor {
           63  +  sqlite3_vtab_cursor base;       /* Base class used by SQLite core */
           64  +  char *zInput;                   /* Input string */
           65  +  sqlite3_tokenizer_cursor *pCsr; /* Cursor to iterate through zInput */
           66  +  int iRowid;                     /* Current 'rowid' value */
           67  +  const char *zToken;             /* Current 'token' value */
           68  +  int nToken;                     /* Size of zToken in bytes */
           69  +  int iStart;                     /* Current 'start' value */
           70  +  int iEnd;                       /* Current 'end' value */
           71  +  int iPos;                       /* Current 'pos' value */
           72  +};
           73  +
           74  +/*
           75  +** Query FTS for the tokenizer implementation named zName.
           76  +*/
           77  +static int fts3tokQueryTokenizer(
           78  +  Fts3Hash *pHash,
           79  +  const char *zName,
           80  +  const sqlite3_tokenizer_module **pp,
           81  +  char **pzErr
           82  +){
           83  +  sqlite3_tokenizer_module *p;
           84  +  int nName = (int)strlen(zName);
           85  +
           86  +  p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1);
           87  +  if( !p ){
           88  +    *pzErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
           89  +    return SQLITE_ERROR;
           90  +  }
           91  +
           92  +  *pp = p;
           93  +  return SQLITE_OK;
           94  +}
           95  +
           96  +/*
           97  +** The second argument, argv[], is an array of pointers to nul-terminated
           98  +** strings. This function makes a copy of the array and strings into a 
           99  +** single block of memory. It then dequotes any of the strings that appear
          100  +** to be quoted.
          101  +**
          102  +** If successful, output parameter *pazDequote is set to point at the
          103  +** array of dequoted strings and SQLITE_OK is returned. The caller is
          104  +** responsible for eventually calling sqlite3_free() to free the array
          105  +** in this case. Or, if an error occurs, an SQLite error code is returned.
          106  +** The final value of *pazDequote is undefined in this case.
          107  +*/
          108  +static int fts3tokDequoteArray(
          109  +  int argc,                       /* Number of elements in argv[] */
          110  +  const char * const *argv,       /* Input array */
          111  +  char ***pazDequote              /* Output array */
          112  +){
          113  +  int rc = SQLITE_OK;             /* Return code */
          114  +  if( argc==0 ){
          115  +    *pazDequote = 0;
          116  +  }else{
          117  +    int i;
          118  +    int nByte = 0;
          119  +    char **azDequote;
          120  +
          121  +    for(i=0; i<argc; i++){
          122  +      nByte += (int)(strlen(argv[i]) + 1);
          123  +    }
          124  +
          125  +    *pazDequote = azDequote = sqlite3_malloc(sizeof(char *)*argc + nByte);
          126  +    if( azDequote==0 ){
          127  +      rc = SQLITE_NOMEM;
          128  +    }else{
          129  +      char *pSpace = (char *)&azDequote[argc];
          130  +      for(i=0; i<argc; i++){
          131  +        int n = (int)strlen(argv[i]);
          132  +        azDequote[i] = pSpace;
          133  +        memcpy(pSpace, argv[i], n+1);
          134  +        sqlite3Fts3Dequote(pSpace);
          135  +        pSpace += (n+1);
          136  +      }
          137  +    }
          138  +  }
          139  +
          140  +  return rc;
          141  +}
          142  +
          143  +/*
          144  +** Schema of the tokenizer table.
          145  +*/
          146  +#define FTS3_TOK_SCHEMA "CREATE TABLE x(input, token, start, end, position)"
          147  +
          148  +/*
          149  +** This function does all the work for both the xConnect and xCreate methods.
          150  +** These tables have no persistent representation of their own, so xConnect
          151  +** and xCreate are identical operations.
          152  +**
          153  +**   argv[0]: module name
          154  +**   argv[1]: database name 
          155  +**   argv[2]: table name
          156  +**   argv[3]: first argument (tokenizer name)
          157  +*/
          158  +static int fts3tokConnectMethod(
          159  +  sqlite3 *db,                    /* Database connection */
          160  +  void *pHash,                    /* Hash table of tokenizers */
          161  +  int argc,                       /* Number of elements in argv array */
          162  +  const char * const *argv,       /* xCreate/xConnect argument array */
          163  +  sqlite3_vtab **ppVtab,          /* OUT: New sqlite3_vtab object */
          164  +  char **pzErr                    /* OUT: sqlite3_malloc'd error message */
          165  +){
          166  +  Fts3tokTable *pTab;
          167  +  const sqlite3_tokenizer_module *pMod = 0;
          168  +  sqlite3_tokenizer *pTok = 0;
          169  +  int rc;
          170  +  char **azDequote = 0;
          171  +  int nDequote;
          172  +
          173  +  rc = sqlite3_declare_vtab(db, FTS3_TOK_SCHEMA);
          174  +  if( rc!=SQLITE_OK ) return rc;
          175  +
          176  +  nDequote = argc-3;
          177  +  rc = fts3tokDequoteArray(nDequote, &argv[3], &azDequote);
          178  +
          179  +  if( rc==SQLITE_OK ){
          180  +    const char *zModule;
          181  +    if( nDequote<1 ){
          182  +      zModule = "simple";
          183  +    }else{
          184  +      zModule = azDequote[0];
          185  +    }
          186  +    rc = fts3tokQueryTokenizer((Fts3Hash*)pHash, zModule, &pMod, pzErr);
          187  +  }
          188  +
          189  +  assert( (rc==SQLITE_OK)==(pMod!=0) );
          190  +  if( rc==SQLITE_OK ){
          191  +    const char * const *azArg = (const char * const *)&azDequote[1];
          192  +    rc = pMod->xCreate((nDequote>1 ? nDequote-1 : 0), azArg, &pTok);
          193  +  }
          194  +
          195  +  if( rc==SQLITE_OK ){
          196  +    pTab = (Fts3tokTable *)sqlite3_malloc(sizeof(Fts3tokTable));
          197  +    if( pTab==0 ){
          198  +      rc = SQLITE_NOMEM;
          199  +    }
          200  +  }
          201  +
          202  +  if( rc==SQLITE_OK ){
          203  +    memset(pTab, 0, sizeof(Fts3tokTable));
          204  +    pTab->pMod = pMod;
          205  +    pTab->pTok = pTok;
          206  +    *ppVtab = &pTab->base;
          207  +  }else{
          208  +    if( pTok ){
          209  +      pMod->xDestroy(pTok);
          210  +    }
          211  +  }
          212  +
          213  +  sqlite3_free(azDequote);
          214  +  return rc;
          215  +}
          216  +
          217  +/*
          218  +** This function does the work for both the xDisconnect and xDestroy methods.
          219  +** These tables have no persistent representation of their own, so xDisconnect
          220  +** and xDestroy are identical operations.
          221  +*/
          222  +static int fts3tokDisconnectMethod(sqlite3_vtab *pVtab){
          223  +  Fts3tokTable *pTab = (Fts3tokTable *)pVtab;
          224  +
          225  +  pTab->pMod->xDestroy(pTab->pTok);
          226  +  sqlite3_free(pTab);
          227  +  return SQLITE_OK;
          228  +}
          229  +
          230  +/*
          231  +** xBestIndex - Analyze a WHERE and ORDER BY clause.
          232  +*/
          233  +static int fts3tokBestIndexMethod(
          234  +  sqlite3_vtab *pVTab, 
          235  +  sqlite3_index_info *pInfo
          236  +){
          237  +  int i;
          238  +  UNUSED_PARAMETER(pVTab);
          239  +
          240  +  for(i=0; i<pInfo->nConstraint; i++){
          241  +    if( pInfo->aConstraint[i].usable 
          242  +     && pInfo->aConstraint[i].iColumn==0 
          243  +     && pInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ 
          244  +    ){
          245  +      pInfo->idxNum = 1;
          246  +      pInfo->aConstraintUsage[i].argvIndex = 1;
          247  +      pInfo->aConstraintUsage[i].omit = 1;
          248  +      pInfo->estimatedCost = 1;
          249  +      return SQLITE_OK;
          250  +    }
          251  +  }
          252  +
          253  +  pInfo->idxNum = 0;
          254  +  assert( pInfo->estimatedCost>1000000.0 );
          255  +
          256  +  return SQLITE_OK;
          257  +}
          258  +
          259  +/*
          260  +** xOpen - Open a cursor.
          261  +*/
          262  +static int fts3tokOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
          263  +  Fts3tokCursor *pCsr;
          264  +  UNUSED_PARAMETER(pVTab);
          265  +
          266  +  pCsr = (Fts3tokCursor *)sqlite3_malloc(sizeof(Fts3tokCursor));
          267  +  if( pCsr==0 ){
          268  +    return SQLITE_NOMEM;
          269  +  }
          270  +  memset(pCsr, 0, sizeof(Fts3tokCursor));
          271  +
          272  +  *ppCsr = (sqlite3_vtab_cursor *)pCsr;
          273  +  return SQLITE_OK;
          274  +}
          275  +
          276  +/*
          277  +** Reset the tokenizer cursor passed as the only argument. As if it had
          278  +** just been returned by fts3tokOpenMethod().
          279  +*/
          280  +static void fts3tokResetCursor(Fts3tokCursor *pCsr){
          281  +  if( pCsr->pCsr ){
          282  +    Fts3tokTable *pTab = (Fts3tokTable *)(pCsr->base.pVtab);
          283  +    pTab->pMod->xClose(pCsr->pCsr);
          284  +    pCsr->pCsr = 0;
          285  +  }
          286  +  sqlite3_free(pCsr->zInput);
          287  +  pCsr->zInput = 0;
          288  +  pCsr->zToken = 0;
          289  +  pCsr->nToken = 0;
          290  +  pCsr->iStart = 0;
          291  +  pCsr->iEnd = 0;
          292  +  pCsr->iPos = 0;
          293  +  pCsr->iRowid = 0;
          294  +}
          295  +
          296  +/*
          297  +** xClose - Close a cursor.
          298  +*/
          299  +static int fts3tokCloseMethod(sqlite3_vtab_cursor *pCursor){
          300  +  Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
          301  +
          302  +  fts3tokResetCursor(pCsr);
          303  +  sqlite3_free(pCsr);
          304  +  return SQLITE_OK;
          305  +}
          306  +
          307  +/*
          308  +** xNext - Advance the cursor to the next row, if any.
          309  +*/
          310  +static int fts3tokNextMethod(sqlite3_vtab_cursor *pCursor){
          311  +  Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
          312  +  Fts3tokTable *pTab = (Fts3tokTable *)(pCursor->pVtab);
          313  +  int rc;                         /* Return code */
          314  +
          315  +  pCsr->iRowid++;
          316  +  rc = pTab->pMod->xNext(pCsr->pCsr,
          317  +      &pCsr->zToken, &pCsr->nToken,
          318  +      &pCsr->iStart, &pCsr->iEnd, &pCsr->iPos
          319  +  );
          320  +
          321  +  if( rc!=SQLITE_OK ){
          322  +    fts3tokResetCursor(pCsr);
          323  +    if( rc==SQLITE_DONE ) rc = SQLITE_OK;
          324  +  }
          325  +
          326  +  return rc;
          327  +}
          328  +
          329  +/*
          330  +** xFilter - Initialize a cursor to point at the start of its data.
          331  +*/
          332  +static int fts3tokFilterMethod(
          333  +  sqlite3_vtab_cursor *pCursor,   /* The cursor used for this query */
          334  +  int idxNum,                     /* Strategy index */
          335  +  const char *idxStr,             /* Unused */
          336  +  int nVal,                       /* Number of elements in apVal */
          337  +  sqlite3_value **apVal           /* Arguments for the indexing scheme */
          338  +){
          339  +  int rc = SQLITE_ERROR;
          340  +  Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
          341  +  Fts3tokTable *pTab = (Fts3tokTable *)(pCursor->pVtab);
          342  +  UNUSED_PARAMETER(idxStr);
          343  +  UNUSED_PARAMETER(nVal);
          344  +
          345  +  fts3tokResetCursor(pCsr);
          346  +  if( idxNum==1 ){
          347  +    const char *zByte = (const char *)sqlite3_value_text(apVal[0]);
          348  +    int nByte = sqlite3_value_bytes(apVal[0]);
          349  +    pCsr->zInput = sqlite3_malloc(nByte+1);
          350  +    if( pCsr->zInput==0 ){
          351  +      rc = SQLITE_NOMEM;
          352  +    }else{
          353  +      memcpy(pCsr->zInput, zByte, nByte);
          354  +      pCsr->zInput[nByte] = 0;
          355  +      rc = pTab->pMod->xOpen(pTab->pTok, pCsr->zInput, nByte, &pCsr->pCsr);
          356  +      if( rc==SQLITE_OK ){
          357  +        pCsr->pCsr->pTokenizer = pTab->pTok;
          358  +      }
          359  +    }
          360  +  }
          361  +
          362  +  if( rc!=SQLITE_OK ) return rc;
          363  +  return fts3tokNextMethod(pCursor);
          364  +}
          365  +
          366  +/*
          367  +** xEof - Return true if the cursor is at EOF, or false otherwise.
          368  +*/
          369  +static int fts3tokEofMethod(sqlite3_vtab_cursor *pCursor){
          370  +  Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
          371  +  return (pCsr->zToken==0);
          372  +}
          373  +
          374  +/*
          375  +** xColumn - Return a column value.
          376  +*/
          377  +static int fts3tokColumnMethod(
          378  +  sqlite3_vtab_cursor *pCursor,   /* Cursor to retrieve value from */
          379  +  sqlite3_context *pCtx,          /* Context for sqlite3_result_xxx() calls */
          380  +  int iCol                        /* Index of column to read value from */
          381  +){
          382  +  Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
          383  +
          384  +  /* CREATE TABLE x(input, token, start, end, position) */
          385  +  switch( iCol ){
          386  +    case 0:
          387  +      sqlite3_result_text(pCtx, pCsr->zInput, -1, SQLITE_TRANSIENT);
          388  +      break;
          389  +    case 1:
          390  +      sqlite3_result_text(pCtx, pCsr->zToken, pCsr->nToken, SQLITE_TRANSIENT);
          391  +      break;
          392  +    case 2:
          393  +      sqlite3_result_int(pCtx, pCsr->iStart);
          394  +      break;
          395  +    case 3:
          396  +      sqlite3_result_int(pCtx, pCsr->iEnd);
          397  +      break;
          398  +    default:
          399  +      assert( iCol==4 );
          400  +      sqlite3_result_int(pCtx, pCsr->iPos);
          401  +      break;
          402  +  }
          403  +  return SQLITE_OK;
          404  +}
          405  +
          406  +/*
          407  +** xRowid - Return the current rowid for the cursor.
          408  +*/
          409  +static int fts3tokRowidMethod(
          410  +  sqlite3_vtab_cursor *pCursor,   /* Cursor to retrieve value from */
          411  +  sqlite_int64 *pRowid            /* OUT: Rowid value */
          412  +){
          413  +  Fts3tokCursor *pCsr = (Fts3tokCursor *)pCursor;
          414  +  *pRowid = (sqlite3_int64)pCsr->iRowid;
          415  +  return SQLITE_OK;
          416  +}
          417  +
          418  +/*
          419  +** Register the fts3tok module with database connection db. Return SQLITE_OK
          420  +** if successful or an error code if sqlite3_create_module() fails.
          421  +*/
          422  +int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){
          423  +  static const sqlite3_module fts3tok_module = {
          424  +     0,                           /* iVersion      */
          425  +     fts3tokConnectMethod,        /* xCreate       */
          426  +     fts3tokConnectMethod,        /* xConnect      */
          427  +     fts3tokBestIndexMethod,      /* xBestIndex    */
          428  +     fts3tokDisconnectMethod,     /* xDisconnect   */
          429  +     fts3tokDisconnectMethod,     /* xDestroy      */
          430  +     fts3tokOpenMethod,           /* xOpen         */
          431  +     fts3tokCloseMethod,          /* xClose        */
          432  +     fts3tokFilterMethod,         /* xFilter       */
          433  +     fts3tokNextMethod,           /* xNext         */
          434  +     fts3tokEofMethod,            /* xEof          */
          435  +     fts3tokColumnMethod,         /* xColumn       */
          436  +     fts3tokRowidMethod,          /* xRowid        */
          437  +     0,                           /* xUpdate       */
          438  +     0,                           /* xBegin        */
          439  +     0,                           /* xSync         */
          440  +     0,                           /* xCommit       */
          441  +     0,                           /* xRollback     */
          442  +     0,                           /* xFindFunction */
          443  +     0,                           /* xRename       */
          444  +     0,                           /* xSavepoint    */
          445  +     0,                           /* xRelease      */
          446  +     0                            /* xRollbackTo   */
          447  +  };
          448  +  int rc;                         /* Return code */
          449  +
          450  +  rc = sqlite3_create_module(db, "fts3tokenize", &fts3tok_module, (void*)pHash);
          451  +  return rc;
          452  +}
          453  +
          454  +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */

Changes to ext/fts3/fts3_tokenizer.c.

   424    424   }
   425    425   
   426    426   #endif
   427    427   
   428    428   /*
   429    429   ** Set up SQL objects in database db used to access the contents of
   430    430   ** the hash table pointed to by argument pHash. The hash table must
   431         -** been initialised to use string keys, and to take a private copy 
          431  +** been initialized to use string keys, and to take a private copy 
   432    432   ** of the key when a value is inserted. i.e. by a call similar to:
   433    433   **
   434    434   **    sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1);
   435    435   **
   436    436   ** This function adds a scalar function (see header comment above
   437    437   ** scalarFunc() in this file for details) and, if ENABLE_TABLE is
   438    438   ** defined at compilation time, a temporary virtual table (see header 

Changes to ext/fts3/fts3_tokenizer.h.

    66     66     **
    67     67     ** then argc is set to 2, and the argv[] array contains pointers
    68     68     ** to the strings "arg1" and "arg2".
    69     69     **
    70     70     ** This method should return either SQLITE_OK (0), or an SQLite error 
    71     71     ** code. If SQLITE_OK is returned, then *ppTokenizer should be set
    72     72     ** to point at the newly created tokenizer structure. The generic
    73         -  ** sqlite3_tokenizer.pModule variable should not be initialised by
           73  +  ** sqlite3_tokenizer.pModule variable should not be initialized by
    74     74     ** this callback. The caller will do so.
    75     75     */
    76     76     int (*xCreate)(
    77     77       int argc,                           /* Size of argv array */
    78     78       const char *const*argv,             /* Tokenizer argument strings */
    79     79       sqlite3_tokenizer **ppTokenizer     /* OUT: Created tokenizer */
    80     80     );

Changes to ext/fts3/fts3_unicode.c.

   121    121   ** If so, no action is taken. Otherwise, the codepoint is added to the 
   122    122   ** unicode_tokenizer.aiException[] array. For the purposes of tokenization,
   123    123   ** the return value of sqlite3FtsUnicodeIsalnum() is inverted for all
   124    124   ** codepoints in the aiException[] array.
   125    125   **
   126    126   ** If a standalone diacritic mark (one that sqlite3FtsUnicodeIsdiacritic()
   127    127   ** identifies as a diacritic) occurs in the zIn/nIn string it is ignored.
   128         -** It is not possible to change the behaviour of the tokenizer with respect
          128  +** It is not possible to change the behavior of the tokenizer with respect
   129    129   ** to these codepoints.
   130    130   */
   131    131   static int unicodeAddExceptions(
   132    132     unicode_tokenizer *p,           /* Tokenizer to add exceptions to */
   133    133     int bAlnum,                     /* Replace Isalnum() return value with this */
   134    134     const char *zIn,                /* Array of characters to make exceptions */
   135    135     int nIn                         /* Length of z in bytes */

Changes to ext/fts3/fts3_write.c.

  1478   1478       ** size of the previous offset-list.
  1479   1479       */
  1480   1480       if( ppOffsetList ){
  1481   1481         *ppOffsetList = pReader->pOffsetList;
  1482   1482         *pnOffsetList = (int)(p - pReader->pOffsetList - 1);
  1483   1483       }
  1484   1484   
         1485  +    /* List may have been edited in place by fts3EvalNearTrim() */
  1485   1486       while( p<pEnd && *p==0 ) p++;
  1486   1487     
  1487   1488       /* If there are no more entries in the doclist, set pOffsetList to
  1488   1489       ** NULL. Otherwise, set Fts3SegReader.iDocid to the next docid and
  1489   1490       ** Fts3SegReader.pOffsetList to point to the next offset list before
  1490   1491       ** returning.
  1491   1492       */
................................................................................
  2493   2494   ** When this function is called, buffer *ppList (size *pnList bytes) contains 
  2494   2495   ** a position list that may (or may not) feature multiple columns. This
  2495   2496   ** function adjusts the pointer *ppList and the length *pnList so that they
  2496   2497   ** identify the subset of the position list that corresponds to column iCol.
  2497   2498   **
  2498   2499   ** If there are no entries in the input position list for column iCol, then
  2499   2500   ** *pnList is set to zero before returning.
         2501  +**
         2502  +** If parameter bZero is non-zero, then any part of the input list following
         2503  +** the end of the output list is zeroed before returning.
  2500   2504   */
  2501   2505   static void fts3ColumnFilter(
  2502   2506     int iCol,                       /* Column to filter on */
         2507  +  int bZero,                      /* Zero out anything following *ppList */
  2503   2508     char **ppList,                  /* IN/OUT: Pointer to position list */
  2504   2509     int *pnList                     /* IN/OUT: Size of buffer *ppList in bytes */
  2505   2510   ){
  2506   2511     char *pList = *ppList;
  2507   2512     int nList = *pnList;
  2508   2513     char *pEnd = &pList[nList];
  2509   2514     int iCurrent = 0;
................................................................................
  2524   2529       if( nList==0 ){
  2525   2530         break;
  2526   2531       }
  2527   2532       p = &pList[1];
  2528   2533       p += sqlite3Fts3GetVarint32(p, &iCurrent);
  2529   2534     }
  2530   2535   
         2536  +  if( bZero && &pList[nList]!=pEnd ){
         2537  +    memset(&pList[nList], 0, pEnd - &pList[nList]);
         2538  +  }
  2531   2539     *ppList = pList;
  2532   2540     *pnList = nList;
  2533   2541   }
  2534   2542   
  2535   2543   /*
  2536   2544   ** Cache data in the Fts3MultiSegReader.aBuffer[] buffer (overwriting any
  2537   2545   ** existing data). Grow the buffer if required.
................................................................................
  2596   2604           && apSegment[j]->iDocid==iDocid
  2597   2605         ){
  2598   2606           rc = fts3SegReaderNextDocid(p, apSegment[j], 0, 0);
  2599   2607           j++;
  2600   2608         }
  2601   2609         if( rc!=SQLITE_OK ) return rc;
  2602   2610         fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp);
         2611  +
         2612  +      if( nList>0 && fts3SegReaderIsPending(apSegment[0]) ){
         2613  +        rc = fts3MsrBufferData(pMsr, pList, nList+1);
         2614  +        if( rc!=SQLITE_OK ) return rc;
         2615  +        assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 );
         2616  +        pList = pMsr->aBuffer;
         2617  +      }
  2603   2618   
  2604   2619         if( pMsr->iColFilter>=0 ){
  2605         -        fts3ColumnFilter(pMsr->iColFilter, &pList, &nList);
         2620  +        fts3ColumnFilter(pMsr->iColFilter, 1, &pList, &nList);
  2606   2621         }
  2607   2622   
  2608   2623         if( nList>0 ){
  2609         -        if( fts3SegReaderIsPending(apSegment[0]) ){
  2610         -          rc = fts3MsrBufferData(pMsr, pList, nList+1);
  2611         -          if( rc!=SQLITE_OK ) return rc;
  2612         -          *paPoslist = pMsr->aBuffer;
  2613         -          assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 );
  2614         -        }else{
  2615         -          *paPoslist = pList;
  2616         -        }
         2624  +        *paPoslist = pList;
  2617   2625           *piDocid = iDocid;
  2618   2626           *pnPoslist = nList;
  2619   2627           break;
  2620   2628         }
  2621   2629       }
  2622   2630     }
  2623   2631   
................................................................................
  2852   2860               && apSegment[j]->iDocid==iDocid
  2853   2861           ){
  2854   2862             fts3SegReaderNextDocid(p, apSegment[j], 0, 0);
  2855   2863             j++;
  2856   2864           }
  2857   2865   
  2858   2866           if( isColFilter ){
  2859         -          fts3ColumnFilter(pFilter->iCol, &pList, &nList);
         2867  +          fts3ColumnFilter(pFilter->iCol, 0, &pList, &nList);
  2860   2868           }
  2861   2869   
  2862   2870           if( !isIgnoreEmpty || nList>0 ){
  2863   2871   
  2864   2872             /* Calculate the 'docid' delta value to write into the merged 
  2865   2873             ** doclist. */
  2866   2874             sqlite3_int64 iDelta;

Changes to ext/icu/README.txt.

    94     94       comparision operator "REGEXP", based on the regular expression functions
    95     95       provided by the ICU library. The syntax of the operator is as described
    96     96       in SQLite documentation:
    97     97   
    98     98           <string> REGEXP <re-pattern>
    99     99   
   100    100       This extension uses the ICU defaults for regular expression matching
   101         -    behaviour. Specifically, this means that:
          101  +    behavior. Specifically, this means that:
   102    102   
   103    103           * Matching is case-sensitive,
   104    104           * Regular expression comments are not allowed within patterns, and
   105    105           * The '^' and '$' characters match the beginning and end of the
   106    106             <string> argument, not the beginning and end of lines within
   107    107             the <string> argument.
   108    108   

Added ext/misc/amatch.c.

            1  +/*
            2  +** 2013-03-14
            3  +**
            4  +** The author disclaims copyright to this source code.  In place of
            5  +** a legal notice, here is a blessing:
            6  +**
            7  +**    May you do good and not evil.
            8  +**    May you find forgiveness for yourself and forgive others.
            9  +**    May you share freely, never taking more than you give.
           10  +**
           11  +*************************************************************************
           12  +**
           13  +** This file contains code for a demonstration virtual table that finds
           14  +** "approximate matches" - strings from a finite set that are nearly the
           15  +** same as a single input string.  The virtual table is called "amatch".
           16  +**
           17  +** A amatch virtual table is created like this:
           18  +**
           19  +**     CREATE VIRTUAL TABLE f USING approximate_match(
           20  +**        vocabulary_table=<tablename>,      -- V
           21  +**        vocabulary_word=<columnname>,      -- W
           22  +**        vocabulary_language=<columnname>,  -- L
           23  +**        edit_distances=<edit-cost-table>
           24  +**     );
           25  +**
           26  +** When it is created, the new amatch table must be supplied with the
           27  +** the name of a table V and columns V.W and V.L such that 
           28  +**
           29  +**     SELECT W FROM V WHERE L=$language
           30  +**
           31  +** returns the allowed vocabulary for the match.  If the "vocabulary_language"
           32  +** or L columnname is left unspecified or is an empty string, then no
           33  +** filtering of the vocabulary by language is performed. 
           34  +**
           35  +** For efficiency, it is essential that the vocabulary table be indexed:
           36  +**
           37  +**     CREATE vocab_index ON V(W)
           38  +**
           39  +** A separate edit-cost-table provides scoring information that defines 
           40  +** what it means for one string to be "close" to another.
           41  +**
           42  +** The edit-cost-table must contain exactly four columns (more precisely,
           43  +** the statement "SELECT * FROM <edit-cost-table>" must return records
           44  +** that consist of four columns). It does not matter what the columns are
           45  +** named. 
           46  +**
           47  +** Each row in the edit-cost-table represents a single character
           48  +** transformation going from user input to the vocabulary. The leftmost 
           49  +** column of the row (column 0) contains an integer identifier of the
           50  +** language to which the transformation rule belongs (see "MULTIPLE LANGUAGES"
           51  +** below). The second column of the row (column 1) contains the input
           52  +** character or characters - the characters of user input. The third 
           53  +** column contains characters as they appear in the vocabulary table.
           54  +** And the fourth column contains the integer cost of making the
           55  +** transformation. For example:
           56  +**
           57  +**    CREATE TABLE f_data(iLang, cFrom, cTo, Cost);
           58  +**    INSERT INTO f_data(iLang, cFrom, cTo, Cost) VALUES(0, '', 'a', 100);
           59  +**    INSERT INTO f_data(iLang, cFrom, cTo, Cost) VALUES(0, 'b', '', 87);
           60  +**    INSERT INTO f_data(iLang, cFrom, cTo, Cost) VALUES(0, 'o', 'oe', 38);
           61  +**    INSERT INTO f_data(iLang, cFrom, cTo, Cost) VALUES(0, 'oe', 'o', 40);
           62  +**
           63  +** The first row inserted into the edit-cost-table by the SQL script
           64  +** above indicates that the cost of having an extra 'a' in the vocabulary
           65  +** table that is missing in the user input 100.  (All costs are integers.
           66  +** Overall cost must not exceed 16777216.)  The second INSERT statement 
           67  +** creates a rule saying that the cost of having a single letter 'b' in
           68  +** user input which is missing in the vocabulary table is 87.  The third
           69  +** INSERT statement mean that the cost of matching an 'o' in user input 
           70  +** against an 'oe' in the vocabulary table is 38.  And so forth.
           71  +**
           72  +** The following rules are special:
           73  +**
           74  +**    INSERT INTO f_data(iLang, cFrom, cTo, Cost) VALUES(0, '?', '', 97);
           75  +**    INSERT INTO f_data(iLang, cFrom, cTo, Cost) VALUES(0, '', '?', 98);
           76  +**    INSERT INTO f_data(iLang, cFrom, cTo, Cost) VALUES(0, '?', '?', 99);
           77  +**
           78  +** The '?' to '' rule is the cost of having any single character in the input
           79  +** that is not found in the vocabular.  The '' to '?' rule is the cost of
           80  +** having a character in the vocabulary table that is missing from input.
           81  +** And the '?' to '?' rule is the cost of doing an arbitrary character
           82  +** substitution.  These three generic rules apply across all languages.
           83  +** In other words, the iLang field is ignored for the generic substitution
           84  +** rules.  If more than one cost is given for a generic substitution rule,
           85  +** then the lowest cost is used.
           86  +**
           87  +** Once it has been created, the amatch virtual table can be queried
           88  +** as follows:
           89  +**
           90  +**    SELECT word, distance FROM f
           91  +**     WHERE word MATCH 'abcdefg'
           92  +**       AND distance<200;
           93  +**
           94  +** This query outputs the strings contained in the T(F) field that
           95  +** are close to "abcdefg" and in order of increasing distance.  No string
           96  +** is output more than once.  If there are multiple ways to transform the
           97  +** target string ("abcdefg") into a string in the vocabulary table then
           98  +** the lowest cost transform is the one that is returned.  In this example,
           99  +** the search is limited to strings with a total distance of less than 200.
          100  +**
          101  +** For efficiency, it is important to put tight bounds on the distance.
          102  +** The time and memory space needed to perform this query is exponential
          103  +** in the maximum distance.  A good rule of thumb is to limit the distance
          104  +** to no more than 1.5 or 2 times the maximum cost of any rule in the
          105  +** edit-cost-table.
          106  +**
          107  +** The amatch is a read-only table.  Any attempt to DELETE, INSERT, or
          108  +** UPDATE on a amatch table will throw an error.
          109  +**
          110  +** It is important to put some kind of a limit on the amatch output.  This
          111  +** can be either in the form of a LIMIT clause at the end of the query,
          112  +** or better, a "distance<NNN" constraint where NNN is some number.  The
          113  +** running time and memory requirement is exponential in the value of NNN 
          114  +** so you want to make sure that NNN is not too big.  A value of NNN that
          115  +** is about twice the average transformation cost seems to give good results.
          116  +**
          117  +** The amatch table can be useful for tasks such as spelling correction.
          118  +** Suppose all allowed words are in table vocabulary(w).  Then one would create
          119  +** an amatch virtual table like this:
          120  +**
          121  +**   CREATE VIRTUAL TABLE ex1 USING amatch(
          122  +**       vocabtable=vocabulary,
          123  +**       vocabcolumn=w,
          124  +**       edit_distances=ec1
          125  +**   );
          126  +**
          127  +** Then given an input word $word, look up close spellings this way:
          128  +**
          129  +**   SELECT word, distance FROM ex1
          130  +**    WHERE word MATCH $word AND distance<200;
          131  +**
          132  +** MULTIPLE LANGUAGES
          133  +**
          134  +** Normally, the "iLang" value associated with all character transformations
          135  +** in the edit-cost-table is zero. However, if required, the amatch 
          136  +** virtual table allows multiple languages to be defined. Each query uses 
          137  +** only a single iLang value.   This allows, for example, a single 
          138  +** amatch table to support multiple languages.
          139  +**
          140  +** By default, only the rules with iLang=0 are used. To specify an 
          141  +** alternative language, a "language = ?" expression must be added to the
          142  +** WHERE clause of a SELECT, where ? is the integer identifier of the desired 
          143  +** language. For example:
          144  +**
          145  +**   SELECT word, distance FROM ex1
          146  +**    WHERE word MATCH $word
          147  +**      AND distance<=200
          148  +**      AND language=1 -- Specify use language 1 instead of 0
          149  +**
          150  +** If no "language = ?" constraint is specified in the WHERE clause, language
          151  +** 0 is used.
          152  +**
          153  +** LIMITS
          154  +**
          155  +** The maximum language number is 2147483647.  The maximum length of either
          156  +** of the strings in the second or third column of the amatch data table
          157  +** is 50 bytes.  The maximum cost on a rule is 1000.
          158  +*/
          159  +#include "sqlite3ext.h"
          160  +SQLITE_EXTENSION_INIT1
          161  +#include <stdlib.h>
          162  +#include <string.h>
          163  +#include <assert.h>
          164  +#include <stdio.h>
          165  +#include <ctype.h>
          166  +
          167  +/*
          168  +** Forward declaration of objects used by this implementation
          169  +*/
          170  +typedef struct amatch_vtab amatch_vtab;
          171  +typedef struct amatch_cursor amatch_cursor;
          172  +typedef struct amatch_rule amatch_rule;
          173  +typedef struct amatch_word amatch_word;
          174  +typedef struct amatch_avl amatch_avl;
          175  +
          176  +
          177  +/*****************************************************************************
          178  +** AVL Tree implementation
          179  +*/
          180  +/*
          181  +** Objects that want to be members of the AVL tree should embedded an
          182  +** instance of this structure.
          183  +*/
          184  +struct amatch_avl {
          185  +  amatch_word *pWord;   /* Points to the object being stored in the tree */
          186  +  char *zKey;           /* Key.  zero-terminated string.  Must be unique */
          187  +  amatch_avl *pBefore;  /* Other elements less than zKey */
          188  +  amatch_avl *pAfter;   /* Other elements greater than zKey */
          189  +  amatch_avl *pUp;      /* Parent element */
          190  +  short int height;     /* Height of this node.  Leaf==1 */
          191  +  short int imbalance;  /* Height difference between pBefore and pAfter */
          192  +};
          193  +
          194  +/* Recompute the amatch_avl.height and amatch_avl.imbalance fields for p.
          195  +** Assume that the children of p have correct heights.
          196  +*/
          197  +static void amatchAvlRecomputeHeight(amatch_avl *p){
          198  +  short int hBefore = p->pBefore ? p->pBefore->height : 0;
          199  +  short int hAfter = p->pAfter ? p->pAfter->height : 0;
          200  +  p->imbalance = hBefore - hAfter;  /* -: pAfter higher.  +: pBefore higher */
          201  +  p->height = (hBefore>hAfter ? hBefore : hAfter)+1;
          202  +}
          203  +
          204  +/*
          205  +**     P                B
          206  +**    / \              / \
          207  +**   B   Z    ==>     X   P
          208  +**  / \                  / \
          209  +** X   Y                Y   Z
          210  +**
          211  +*/
          212  +static amatch_avl *amatchAvlRotateBefore(amatch_avl *pP){
          213  +  amatch_avl *pB = pP->pBefore;
          214  +  amatch_avl *pY = pB->pAfter;
          215  +  pB->pUp = pP->pUp;
          216  +  pB->pAfter = pP;
          217  +  pP->pUp = pB;
          218  +  pP->pBefore = pY;
          219  +  if( pY ) pY->pUp = pP;
          220  +  amatchAvlRecomputeHeight(pP);
          221  +  amatchAvlRecomputeHeight(pB);
          222  +  return pB;
          223  +}
          224  +
          225  +/*
          226  +**     P                A
          227  +**    / \              / \
          228  +**   X   A    ==>     P   Z
          229  +**      / \          / \
          230  +**     Y   Z        X   Y
          231  +**
          232  +*/
          233  +static amatch_avl *amatchAvlRotateAfter(amatch_avl *pP){
          234  +  amatch_avl *pA = pP->pAfter;
          235  +  amatch_avl *pY = pA->pBefore;
          236  +  pA->pUp = pP->pUp;
          237  +  pA->pBefore = pP;
          238  +  pP->pUp = pA;
          239  +  pP->pAfter = pY;
          240  +  if( pY ) pY->pUp = pP;
          241  +  amatchAvlRecomputeHeight(pP);
          242  +  amatchAvlRecomputeHeight(pA);
          243  +  return pA;
          244  +}
          245  +
          246  +/*
          247  +** Return a pointer to the pBefore or pAfter pointer in the parent
          248  +** of p that points to p.  Or if p is the root node, return pp.
          249  +*/
          250  +static amatch_avl **amatchAvlFromPtr(amatch_avl *p, amatch_avl **pp){
          251  +  amatch_avl *pUp = p->pUp;
          252  +  if( pUp==0 ) return pp;
          253  +  if( pUp->pAfter==p ) return &pUp->pAfter;
          254  +  return &pUp->pBefore;
          255  +}
          256  +
          257  +/*
          258  +** Rebalance all nodes starting with p and working up to the root.
          259  +** Return the new root.
          260  +*/
          261  +static amatch_avl *amatchAvlBalance(amatch_avl *p){
          262  +  amatch_avl *pTop = p;
          263  +  amatch_avl **pp;
          264  +  while( p ){
          265  +    amatchAvlRecomputeHeight(p);
          266  +    if( p->imbalance>=2 ){
          267  +      amatch_avl *pB = p->pBefore;
          268  +      if( pB->imbalance<0 ) p->pBefore = amatchAvlRotateAfter(pB);
          269  +      pp = amatchAvlFromPtr(p,&p);
          270  +      p = *pp = amatchAvlRotateBefore(p);
          271  +    }else if( p->imbalance<=(-2) ){
          272  +      amatch_avl *pA = p->pAfter;
          273  +      if( pA->imbalance>0 ) p->pAfter = amatchAvlRotateBefore(pA);
          274  +      pp = amatchAvlFromPtr(p,&p);
          275  +      p = *pp = amatchAvlRotateAfter(p);
          276  +    }
          277  +    pTop = p;
          278  +    p = p->pUp;
          279  +  }
          280  +  return pTop;
          281  +}
          282  +
          283  +/* Search the tree rooted at p for an entry with zKey.  Return a pointer
          284  +** to the entry or return NULL.
          285  +*/
          286  +static amatch_avl *amatchAvlSearch(amatch_avl *p, const char *zKey){
          287  +  int c;
          288  +  while( p && (c = strcmp(zKey, p->zKey))!=0 ){
          289  +    p = (c<0) ? p->pBefore : p->pAfter;
          290  +  }
          291  +  return p;
          292  +}
          293  +
          294  +/* Find the first node (the one with the smallest key).
          295  +*/
          296  +static amatch_avl *amatchAvlFirst(amatch_avl *p){
          297  +  if( p ) while( p->pBefore ) p = p->pBefore;
          298  +  return p;
          299  +}
          300  +
          301  +#if 0 /* NOT USED */
          302  +/* Return the node with the next larger key after p.
          303  +*/
          304  +static amatch_avl *amatchAvlNext(amatch_avl *p){
          305  +  amatch_avl *pPrev = 0;
          306  +  while( p && p->pAfter==pPrev ){
          307  +    pPrev = p;
          308  +    p = p->pUp;
          309  +  }
          310  +  if( p && pPrev==0 ){
          311  +    p = amatchAvlFirst(p->pAfter);
          312  +  }
          313  +  return p;
          314  +}
          315  +#endif
          316  +
          317  +#if 0 /* NOT USED */
          318  +/* Verify AVL tree integrity
          319  +*/
          320  +static int amatchAvlIntegrity(amatch_avl *pHead){
          321  +  amatch_avl *p;
          322  +  if( pHead==0 ) return 1;
          323  +  if( (p = pHead->pBefore)!=0 ){
          324  +    assert( p->pUp==pHead );
          325  +    assert( amatchAvlIntegrity(p) );
          326  +    assert( strcmp(p->zKey, pHead->zKey)<0 );
          327  +    while( p->pAfter ) p = p->pAfter;
          328  +    assert( strcmp(p->zKey, pHead->zKey)<0 );
          329  +  }
          330  +  if( (p = pHead->pAfter)!=0 ){
          331  +    assert( p->pUp==pHead );
          332  +    assert( amatchAvlIntegrity(p) );
          333  +    assert( strcmp(p->zKey, pHead->zKey)>0 );
          334  +    p = amatchAvlFirst(p);
          335  +    assert( strcmp(p->zKey, pHead->zKey)>0 );
          336  +  }
          337  +  return 1;
          338  +}
          339  +static int amatchAvlIntegrity2(amatch_avl *pHead){
          340  +  amatch_avl *p, *pNext;
          341  +  for(p=amatchAvlFirst(pHead); p; p=pNext){
          342  +    pNext = amatchAvlNext(p);
          343  +    if( pNext==0 ) break;
          344  +    assert( strcmp(p->zKey, pNext->zKey)<0 );
          345  +  }
          346  +  return 1;
          347  +}
          348  +#endif
          349  +
          350  +/* Insert a new node pNew.  Return NULL on success.  If the key is not
          351  +** unique, then do not perform the insert but instead leave pNew unchanged
          352  +** and return a pointer to an existing node with the same key.
          353  +*/
          354  +static amatch_avl *amatchAvlInsert(amatch_avl **ppHead, amatch_avl *pNew){
          355  +  int c;
          356  +  amatch_avl *p = *ppHead;
          357  +  if( p==0 ){
          358  +    p = pNew;
          359  +    pNew->pUp = 0;
          360  +  }else{
          361  +    while( p ){
          362  +      c = strcmp(pNew->zKey, p->zKey);
          363  +      if( c<0 ){
          364  +        if( p->pBefore ){
          365  +          p = p->pBefore;
          366  +        }else{
          367  +          p->pBefore = pNew;
          368  +          pNew->pUp = p;
          369  +          break;
          370  +        }
          371  +      }else if( c>0 ){
          372  +        if( p->pAfter ){
          373  +          p = p->pAfter;
          374  +        }else{
          375  +          p->pAfter = pNew;
          376  +          pNew->pUp = p;
          377  +          break;
          378  +        }
          379  +      }else{
          380  +        return p;
          381  +      }
          382  +    }
          383  +  }
          384  +  pNew->pBefore = 0;
          385  +  pNew->pAfter = 0;
          386  +  pNew->height = 1;
          387  +  pNew->imbalance = 0;
          388  +  *ppHead = amatchAvlBalance(p);
          389  +  /* assert( amatchAvlIntegrity(*ppHead) ); */
          390  +  /* assert( amatchAvlIntegrity2(*ppHead) ); */
          391  +  return 0;
          392  +}
          393  +
          394  +/* Remove node pOld from the tree.  pOld must be an element of the tree or
          395  +** the AVL tree will become corrupt.
          396  +*/
          397  +static void amatchAvlRemove(amatch_avl **ppHead, amatch_avl *pOld){
          398  +  amatch_avl **ppParent;
          399  +  amatch_avl *pBalance;
          400  +  /* assert( amatchAvlSearch(*ppHead, pOld->zKey)==pOld ); */
          401  +  ppParent = amatchAvlFromPtr(pOld, ppHead);
          402  +  if( pOld->pBefore==0 && pOld->pAfter==0 ){
          403  +    *ppParent = 0;
          404  +    pBalance = pOld->pUp;
          405  +  }else if( pOld->pBefore && pOld->pAfter ){
          406  +    amatch_avl *pX, *pY;
          407  +    pX = amatchAvlFirst(pOld->pAfter);
          408  +    *amatchAvlFromPtr(pX, 0) = pX->pAfter;
          409  +    if( pX->pAfter ) pX->pAfter->pUp = pX->pUp;
          410  +    pBalance = pX->pUp;
          411  +    pX->pAfter = pOld->pAfter;
          412  +    if( pX->pAfter ){
          413  +      pX->pAfter->pUp = pX;
          414  +    }else{
          415  +      assert( pBalance==pOld );
          416  +      pBalance = pX;
          417  +    }
          418  +    pX->pBefore = pY = pOld->pBefore;
          419  +    if( pY ) pY->pUp = pX;
          420  +    pX->pUp = pOld->pUp;
          421  +    *ppParent = pX;
          422  +  }else if( pOld->pBefore==0 ){
          423  +    *ppParent = pBalance = pOld->pAfter;
          424  +    pBalance->pUp = pOld->pUp;
          425  +  }else if( pOld->pAfter==0 ){
          426  +    *ppParent = pBalance = pOld->pBefore;
          427  +    pBalance->pUp = pOld->pUp;
          428  +  }
          429  +  *ppHead = amatchAvlBalance(pBalance);
          430  +  pOld->pUp = 0;
          431  +  pOld->pBefore = 0;
          432  +  pOld->pAfter = 0;
          433  +  /* assert( amatchAvlIntegrity(*ppHead) ); */
          434  +  /* assert( amatchAvlIntegrity2(*ppHead) ); */
          435  +}
          436  +/*
          437  +** End of the AVL Tree implementation
          438  +******************************************************************************/
          439  +
          440  +
          441  +/*
          442  +** Various types.
          443  +**
          444  +** amatch_cost is the "cost" of an edit operation.
          445  +**
          446  +** amatch_len is the length of a matching string.  
          447  +**
          448  +** amatch_langid is an ruleset identifier.
          449  +*/
          450  +typedef int amatch_cost;
          451  +typedef signed char amatch_len;
          452  +typedef int amatch_langid;
          453  +
          454  +/*
          455  +** Limits
          456  +*/
          457  +#define AMATCH_MX_LENGTH          50  /* Maximum length of a rule string */
          458  +#define AMATCH_MX_LANGID  2147483647  /* Maximum rule ID */
          459  +#define AMATCH_MX_COST          1000  /* Maximum single-rule cost */
          460  +
          461  +/*
          462  +** A match or partial match
          463  +*/
          464  +struct amatch_word {
          465  +  amatch_word *pNext;   /* Next on a list of all amatch_words */
          466  +  amatch_avl sCost;     /* Linkage of this node into the cost tree */
          467  +  amatch_avl sWord;     /* Linkage of this node into the word tree */
          468  +  amatch_cost rCost;    /* Cost of the match so far */
          469  +  int iSeq;             /* Sequence number */
          470  +  char zCost[10];       /* Cost key (text rendering of rCost) */
          471  +  short int nMatch;     /* Input characters matched */
          472  +  char zWord[4];        /* Text of the word.  Extra space appended as needed */
          473  +};
          474  +
          475  +/*
          476  +** Each transformation rule is stored as an instance of this object.
          477  +** All rules are kept on a linked list sorted by rCost.
          478  +*/
          479  +struct amatch_rule {
          480  +  amatch_rule *pNext;      /* Next rule in order of increasing rCost */
          481  +  char *zFrom;             /* Transform from (a string from user input) */
          482  +  amatch_cost rCost;       /* Cost of this transformation */
          483  +  amatch_langid iLang;     /* The langauge to which this rule belongs */
          484  +  amatch_len nFrom, nTo;   /* Length of the zFrom and zTo strings */
          485  +  char zTo[4];             /* Tranform to V.W value (extra space appended) */
          486  +};
          487  +
          488  +/* 
          489  +** A amatch virtual-table object 
          490  +*/
          491  +struct amatch_vtab {
          492  +  sqlite3_vtab base;         /* Base class - must be first */
          493  +  char *zClassName;          /* Name of this class.  Default: "amatch" */
          494  +  char *zDb;                 /* Name of database.  (ex: "main") */
          495  +  char *zSelf;               /* Name of this virtual table */
          496  +  char *zCostTab;            /* Name of edit-cost-table */
          497  +  char *zVocabTab;           /* Name of vocabulary table */
          498  +  char *zVocabWord;          /* Name of vocabulary table word column */
          499  +  char *zVocabLang;          /* Name of vocabulary table language column */
          500  +  amatch_rule *pRule;        /* All active rules in this amatch */
          501  +  amatch_cost rIns;          /* Generic insertion cost  '' -> ? */
          502  +  amatch_cost rDel;          /* Generic deletion cost  ? -> '' */
          503  +  amatch_cost rSub;          /* Generic substitution cost ? -> ? */
          504  +  sqlite3 *db;               /* The database connection */
          505  +  sqlite3_stmt *pVCheck;     /* Query to check zVocabTab */
          506  +  int nCursor;               /* Number of active cursors */
          507  +};
          508  +
          509  +/* A amatch cursor object */
          510  +struct amatch_cursor {
          511  +  sqlite3_vtab_cursor base;  /* Base class - must be first */
          512  +  sqlite3_int64 iRowid;      /* The rowid of the current word */
          513  +  amatch_langid iLang;       /* Use this language ID */
          514  +  amatch_cost rLimit;        /* Maximum cost of any term */
          515  +  int nBuf;                  /* Space allocated for zBuf */
          516  +  int oomErr;                /* True following an OOM error */
          517  +  int nWord;                 /* Number of amatch_word objects */
          518  +  char *zBuf;                /* Temp-use buffer space */
          519  +  char *zInput;              /* Input word to match against */
          520  +  amatch_vtab *pVtab;        /* The virtual table this cursor belongs to */
          521  +  amatch_word *pAllWords;    /* List of all amatch_word objects */
          522  +  amatch_word *pCurrent;     /* Most recent solution */
          523  +  amatch_avl *pCost;         /* amatch_word objects keyed by iCost */
          524  +  amatch_avl *pWord;         /* amatch_word objects keyed by zWord */
          525  +};
          526  +
          527  +/*
          528  +** The two input rule lists are both sorted in order of increasing
          529  +** cost.  Merge them together into a single list, sorted by cost, and
          530  +** return a pointer to the head of that list.
          531  +*/
          532  +static amatch_rule *amatchMergeRules(amatch_rule *pA, amatch_rule *pB){
          533  +  amatch_rule head;
          534  +  amatch_rule *pTail;
          535  +
          536  +  pTail =  &head;
          537  +  while( pA && pB ){
          538  +    if( pA->rCost<=pB->rCost ){
          539  +      pTail->pNext = pA;
          540  +      pTail = pA;
          541  +      pA = pA->pNext;
          542  +    }else{
          543  +      pTail->pNext = pB;
          544  +      pTail = pB;
          545  +      pB = pB->pNext;
          546  +    }
          547  +  }
          548  +  if( pA==0 ){
          549  +    pTail->pNext = pB;
          550  +  }else{
          551  +    pTail->pNext = pA;
          552  +  }
          553  +  return head.pNext;
          554  +}
          555  +
          556  +/*
          557  +** Statement pStmt currently points to a row in the amatch data table. This
          558  +** function allocates and populates a amatch_rule structure according to
          559  +** the content of the row.
          560  +**
          561  +** If successful, *ppRule is set to point to the new object and SQLITE_OK
          562  +** is returned. Otherwise, *ppRule is zeroed, *pzErr may be set to point
          563  +** to an error message and an SQLite error code returned.
          564  +*/
          565  +static int amatchLoadOneRule(
          566  +  amatch_vtab *p,                 /* Fuzzer virtual table handle */
          567  +  sqlite3_stmt *pStmt,            /* Base rule on statements current row */
          568  +  amatch_rule **ppRule,           /* OUT: New rule object */
          569  +  char **pzErr                    /* OUT: Error message */
          570  +){
          571  +  sqlite3_int64 iLang = sqlite3_column_int64(pStmt, 0);
          572  +  const char *zFrom = (const char *)sqlite3_column_text(pStmt, 1);
          573  +  const char *zTo = (const char *)sqlite3_column_text(pStmt, 2);
          574  +  amatch_cost rCost = sqlite3_column_int(pStmt, 3);
          575  +
          576  +  int rc = SQLITE_OK;             /* Return code */
          577  +  int nFrom;                      /* Size of string zFrom, in bytes */
          578  +  int nTo;                        /* Size of string zTo, in bytes */
          579  +  amatch_rule *pRule = 0;         /* New rule object to return */
          580  +
          581  +  if( zFrom==0 ) zFrom = "";
          582  +  if( zTo==0 ) zTo = "";
          583  +  nFrom = (int)strlen(zFrom);
          584  +  nTo = (int)strlen(zTo);
          585  +
          586  +  /* Silently ignore null transformations */
          587  +  if( strcmp(zFrom, zTo)==0 ){
          588  +    if( zFrom[0]=='?' && zFrom[1]==0 ){
          589  +      if( p->rSub==0 || p->rSub>rCost ) p->rSub = rCost;
          590  +    }
          591  +    *ppRule = 0;
          592  +    return SQLITE_OK;
          593  +  }
          594  +
          595  +  if( rCost<=0 || rCost>AMATCH_MX_COST ){
          596  +    *pzErr = sqlite3_mprintf("%s: cost must be between 1 and %d", 
          597  +        p->zClassName, AMATCH_MX_COST
          598  +    );
          599  +    rc = SQLITE_ERROR;
          600  +  }else
          601  +  if( nFrom>AMATCH_MX_LENGTH || nTo>AMATCH_MX_LENGTH ){
          602  +    *pzErr = sqlite3_mprintf("%s: maximum string length is %d", 
          603  +        p->zClassName, AMATCH_MX_LENGTH
          604  +    );
          605  +    rc = SQLITE_ERROR;    
          606  +  }else
          607  +  if( iLang<0 || iLang>AMATCH_MX_LANGID ){
          608  +    *pzErr = sqlite3_mprintf("%s: iLang must be between 0 and %d", 
          609  +        p->zClassName, AMATCH_MX_LANGID
          610  +    );
          611  +    rc = SQLITE_ERROR;    
          612  +  }else
          613  +  if( strcmp(zFrom,"")==0 && strcmp(zTo,"?")==0 ){
          614  +    if( p->rIns==0 || p->rIns>rCost ) p->rIns = rCost;
          615  +  }else
          616  +  if( strcmp(zFrom,"?")==0 && strcmp(zTo,"")==0 ){
          617  +    if( p->rDel==0 || p->rDel>rCost ) p->rDel = rCost;
          618  +  }else
          619  +  {
          620  +    pRule = sqlite3_malloc( sizeof(*pRule) + nFrom + nTo );
          621  +    if( pRule==0 ){
          622  +      rc = SQLITE_NOMEM;
          623  +    }else{
          624  +      memset(pRule, 0, sizeof(*pRule));
          625  +      pRule->zFrom = &pRule->zTo[nTo+1];
          626  +      pRule->nFrom = nFrom;
          627  +      memcpy(pRule->zFrom, zFrom, nFrom+1);
          628  +      memcpy(pRule->zTo, zTo, nTo+1);
          629  +      pRule->nTo = nTo;
          630  +      pRule->rCost = rCost;
          631  +      pRule->iLang = (int)iLang;
          632  +    }
          633  +  }
          634  +
          635  +  *ppRule = pRule;
          636  +  return rc;
          637  +}
          638  +
          639  +/*
          640  +** Free all the content in the edit-cost-table
          641  +*/
          642  +static void amatchFreeRules(amatch_vtab *p){
          643  +  while( p->pRule ){
          644  +    amatch_rule *pRule = p->pRule;
          645  +    p->pRule = pRule->pNext;
          646  +    sqlite3_free(pRule);
          647  +  }
          648  +  p->pRule = 0;
          649  +}
          650  +
          651  +/*
          652  +** Load the content of the amatch data table into memory.
          653  +*/
          654  +static int amatchLoadRules(
          655  +  sqlite3 *db,                    /* Database handle */
          656  +  amatch_vtab *p,                 /* Virtual amatch table to configure */
          657  +  char **pzErr                    /* OUT: Error message */
          658  +){
          659  +  int rc = SQLITE_OK;             /* Return code */
          660  +  char *zSql;                     /* SELECT used to read from rules table */
          661  +  amatch_rule *pHead = 0;
          662  +
          663  +  zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", p->zDb, p->zCostTab);
          664  +  if( zSql==0 ){
          665  +    rc = SQLITE_NOMEM;
          666  +  }else{
          667  +    int rc2;                      /* finalize() return code */
          668  +    sqlite3_stmt *pStmt = 0;
          669  +    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
          670  +    if( rc!=SQLITE_OK ){
          671  +      *pzErr = sqlite3_mprintf("%s: %s", p->zClassName, sqlite3_errmsg(db));
          672  +    }else if( sqlite3_column_count(pStmt)!=4 ){
          673  +      *pzErr = sqlite3_mprintf("%s: %s has %d columns, expected 4",
          674  +          p->zClassName, p->zCostTab, sqlite3_column_count(pStmt)
          675  +      );
          676  +      rc = SQLITE_ERROR;
          677  +    }else{
          678  +      while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
          679  +        amatch_rule *pRule = 0;
          680  +        rc = amatchLoadOneRule(p, pStmt, &pRule, pzErr);
          681  +        if( pRule ){
          682  +          pRule->pNext = pHead;
          683  +          pHead = pRule;
          684  +        }
          685  +      }
          686  +    }
          687  +    rc2 = sqlite3_finalize(pStmt);
          688  +    if( rc==SQLITE_OK ) rc = rc2;
          689  +  }
          690  +  sqlite3_free(zSql);
          691  +
          692  +  /* All rules are now in a singly linked list starting at pHead. This
          693  +  ** block sorts them by cost and then sets amatch_vtab.pRule to point to 
          694  +  ** point to the head of the sorted list.
          695  +  */
          696  +  if( rc==SQLITE_OK ){
          697  +    unsigned int i;
          698  +    amatch_rule *pX;
          699  +    amatch_rule *a[15];
          700  +    for(i=0; i<sizeof(a)/sizeof(a[0]); i++) a[i] = 0;
          701  +    while( (pX = pHead)!=0 ){
          702  +      pHead = pX->pNext;
          703  +      pX->pNext = 0;
          704  +      for(i=0; a[i] && i<sizeof(a)/sizeof(a[0])-1; i++){
          705  +        pX = amatchMergeRules(a[i], pX);
          706  +        a[i] = 0;
          707  +      }
          708  +      a[i] = amatchMergeRules(a[i], pX);
          709  +    }
          710  +    for(pX=a[0], i=1; i<sizeof(a)/sizeof(a[0]); i++){
          711  +      pX = amatchMergeRules(a[i], pX);
          712  +    }
          713  +    p->pRule = amatchMergeRules(p->pRule, pX);
          714  +  }else{
          715  +    /* An error has occurred. Setting p->pRule to point to the head of the
          716  +    ** allocated list ensures that the list will be cleaned up in this case.
          717  +    */
          718  +    assert( p->pRule==0 );
          719  +    p->pRule = pHead;
          720  +  }
          721  +
          722  +  return rc;
          723  +}
          724  +
          725  +/*
          726  +** This function converts an SQL quoted string into an unquoted string
          727  +** and returns a pointer to a buffer allocated using sqlite3_malloc() 
          728  +** containing the result. The caller should eventually free this buffer
          729  +** using sqlite3_free.
          730  +**
          731  +** Examples:
          732  +**
          733  +**     "abc"   becomes   abc
          734  +**     'xyz'   becomes   xyz
          735  +**     [pqr]   becomes   pqr
          736  +**     `mno`   becomes   mno
          737  +*/
          738  +static char *amatchDequote(const char *zIn){
          739  +  int nIn;                        /* Size of input string, in bytes */
          740  +  char *zOut;                     /* Output (dequoted) string */
          741  +
          742  +  nIn = (int)strlen(zIn);
          743  +  zOut = sqlite3_malloc(nIn+1);
          744  +  if( zOut ){
          745  +    char q = zIn[0];              /* Quote character (if any ) */
          746  +
          747  +    if( q!='[' && q!= '\'' && q!='"' && q!='`' ){
          748  +      memcpy(zOut, zIn, nIn+1);
          749  +    }else{
          750  +      int iOut = 0;               /* Index of next byte to write to output */
          751  +      int iIn;                    /* Index of next byte to read from input */
          752  +
          753  +      if( q=='[' ) q = ']';
          754  +      for(iIn=1; iIn<nIn; iIn++){
          755  +        if( zIn[iIn]==q ) iIn++;
          756  +        zOut[iOut++] = zIn[iIn];
          757  +      }
          758  +    }
          759  +    assert( (int)strlen(zOut)<=nIn );
          760  +  }
          761  +  return zOut;
          762  +}
          763  +
          764  +/*
          765  +** Deallocate the pVCheck prepared statement.
          766  +*/
          767  +static void amatchVCheckClear(amatch_vtab *p){
          768  +  if( p->pVCheck ){
          769  +    sqlite3_finalize(p->pVCheck);
          770  +    p->pVCheck = 0;
          771  +  }
          772  +}
          773  +
          774  +/*
          775  +** Deallocate an amatch_vtab object
          776  +*/
          777  +static void amatchFree(amatch_vtab *p){
          778  +  if( p ){
          779  +    amatchFreeRules(p);
          780  +    amatchVCheckClear(p);
          781  +    sqlite3_free(p->zClassName);
          782  +    sqlite3_free(p->zDb);
          783  +    sqlite3_free(p->zCostTab);
          784  +    sqlite3_free(p->zVocabTab);
          785  +    sqlite3_free(p->zVocabWord);
          786  +    sqlite3_free(p->zVocabLang);
          787  +    memset(p, 0, sizeof(*p));
          788  +    sqlite3_free(p);
          789  +  }
          790  +}
          791  +
          792  +/*
          793  +** xDisconnect/xDestroy method for the amatch module.
          794  +*/
          795  +static int amatchDisconnect(sqlite3_vtab *pVtab){
          796  +  amatch_vtab *p = (amatch_vtab*)pVtab;
          797  +  assert( p->nCursor==0 );
          798  +  amatchFree(p);
          799  +  return SQLITE_OK;
          800  +}
          801  +
          802  +/*
          803  +** Check to see if the argument is of the form:
          804  +**
          805  +**       KEY = VALUE
          806  +**
          807  +** If it is, return a pointer to the first character of VALUE.
          808  +** If not, return NULL.  Spaces around the = are ignored.
          809  +*/
          810  +static const char *amatchValueOfKey(const char *zKey, const char *zStr){
          811  +  int nKey = (int)strlen(zKey);
          812  +  int nStr = (int)strlen(zStr);
          813  +  int i;
          814  +  if( nStr<nKey+1 ) return 0;
          815  +  if( memcmp(zStr, zKey, nKey)!=0 ) return 0;
          816  +  for(i=nKey; isspace(zStr[i]); i++){}
          817  +  if( zStr[i]!='=' ) return 0;
          818  +  i++;
          819  +  while( isspace(zStr[i]) ){ i++; }
          820  +  return zStr+i;
          821  +}
          822  +
          823  +/*
          824  +** xConnect/xCreate method for the amatch module. Arguments are:
          825  +**
          826  +**   argv[0]    -> module name  ("approximate_match")
          827  +**   argv[1]    -> database name
          828  +**   argv[2]    -> table name
          829  +**   argv[3...] -> arguments
          830  +*/
          831  +static int amatchConnect(
          832  +  sqlite3 *db,
          833  +  void *pAux,
          834  +  int argc, const char *const*argv,
          835  +  sqlite3_vtab **ppVtab,
          836  +  char **pzErr
          837  +){
          838  +  int rc = SQLITE_OK;             /* Return code */
          839  +  amatch_vtab *pNew = 0;          /* New virtual table */
          840  +  const char *zModule = argv[0];
          841  +  const char *zDb = argv[1];
          842  +  const char *zVal;
          843  +  int i;
          844  +
          845  +  (void)pAux;
          846  +  *ppVtab = 0;
          847  +  pNew = sqlite3_malloc( sizeof(*pNew) );
          848  +  if( pNew==0 ) return SQLITE_NOMEM;
          849  +  rc = SQLITE_NOMEM;
          850  +  memset(pNew, 0, sizeof(*pNew));
          851  +  pNew->db = db;
          852  +  pNew->zClassName = sqlite3_mprintf("%s", zModule);
          853  +  if( pNew->zClassName==0 ) goto amatchConnectError;
          854  +  pNew->zDb = sqlite3_mprintf("%s", zDb);
          855  +  if( pNew->zDb==0 ) goto amatchConnectError;
          856  +  pNew->zSelf = sqlite3_mprintf("%s", argv[2]);
          857  +  if( pNew->zSelf==0 ) goto amatchConnectError;
          858  +  for(i=3; i<argc; i++){
          859  +    zVal = amatchValueOfKey("vocabulary_table", argv[i]);
          860  +    if( zVal ){
          861  +      sqlite3_free(pNew->zVocabTab);
          862  +      pNew->zVocabTab = amatchDequote(zVal);
          863  +      if( pNew->zVocabTab==0 ) goto amatchConnectError;
          864  +      continue;
          865  +    }
          866  +    zVal = amatchValueOfKey("vocabulary_word", argv[i]);
          867  +    if( zVal ){
          868  +      sqlite3_free(pNew->zVocabWord);
          869  +      pNew->zVocabWord = amatchDequote(zVal);
          870  +      if( pNew->zVocabWord==0 ) goto amatchConnectError;
          871  +      continue;
          872  +    }
          873  +    zVal = amatchValueOfKey("vocabulary_language", argv[i]);
          874  +    if( zVal ){
          875  +      sqlite3_free(pNew->zVocabLang);
          876  +      pNew->zVocabLang = amatchDequote(zVal);
          877  +      if( pNew->zVocabLang==0 ) goto amatchConnectError;
          878  +      continue;
          879  +    }
          880  +    zVal = amatchValueOfKey("edit_distances", argv[i]);
          881  +    if( zVal ){
          882  +      sqlite3_free(pNew->zCostTab);
          883  +      pNew->zCostTab = amatchDequote(zVal);
          884  +      if( pNew->zCostTab==0 ) goto amatchConnectError;
          885  +      continue;
          886  +    }
          887  +    *pzErr = sqlite3_mprintf("unrecognized argument: [%s]\n", argv[i]);
          888  +    amatchFree(pNew);
          889  +    *ppVtab = 0;
          890  +    return SQLITE_ERROR;
          891  +  }
          892  +  rc = SQLITE_OK;
          893  +  if( pNew->zCostTab==0 ){
          894  +    *pzErr = sqlite3_mprintf("no edit_distances table specified");
          895  +    rc = SQLITE_ERROR;
          896  +  }else{
          897  +    rc = amatchLoadRules(db, pNew, pzErr);
          898  +  }
          899  +  if( rc==SQLITE_OK ){
          900  +    rc = sqlite3_declare_vtab(db,
          901  +           "CREATE TABLE x(word,distance,language,"
          902  +           "command HIDDEN,nword HIDDEN)"
          903  +         );
          904  +#define AMATCH_COL_WORD       0
          905  +#define AMATCH_COL_DISTANCE   1
          906  +#define AMATCH_COL_LANGUAGE   2
          907  +#define AMATCH_COL_COMMAND    3
          908  +#define AMATCH_COL_NWORD      4
          909  +  }
          910  +  if( rc!=SQLITE_OK ){
          911  +    amatchFree(pNew);
          912  +  }
          913  +  *ppVtab = &pNew->base;
          914  +  return rc;
          915  +
          916  +amatchConnectError:
          917  +  amatchFree(pNew);
          918  +  return rc;
          919  +}
          920  +
          921  +/*
          922  +** Open a new amatch cursor.
          923  +*/
          924  +static int amatchOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
          925  +  amatch_vtab *p = (amatch_vtab*)pVTab;
          926  +  amatch_cursor *pCur;
          927  +  pCur = sqlite3_malloc( sizeof(*pCur) );
          928  +  if( pCur==0 ) return SQLITE_NOMEM;
          929  +  memset(pCur, 0, sizeof(*pCur));
          930  +  pCur->pVtab = p;
          931  +  *ppCursor = &pCur->base;
          932  +  p->nCursor++;
          933  +  return SQLITE_OK;
          934  +}
          935  +
          936  +/*
          937  +** Free up all the memory allocated by a cursor.  Set it rLimit to 0
          938  +** to indicate that it is at EOF.
          939  +*/
          940  +static void amatchClearCursor(amatch_cursor *pCur){
          941  +  amatch_word *pWord, *pNextWord;
          942  +  for(pWord=pCur->pAllWords; pWord; pWord=pNextWord){
          943  +    pNextWord = pWord->pNext;
          944  +    sqlite3_free(pWord);
          945  +  }
          946  +  pCur->pAllWords = 0;
          947  +  sqlite3_free(pCur->zInput);
          948  +  pCur->zInput = 0;
          949  +  pCur->pCost = 0;
          950  +  pCur->pWord = 0;
          951  +  pCur->pCurrent = 0;
          952  +  pCur->rLimit = 1000000;
          953  +  pCur->iLang = 0;
          954  +  pCur->nWord = 0;
          955  +}
          956  +
          957  +/*
          958  +** Close a amatch cursor.
          959  +*/
          960  +static int amatchClose(sqlite3_vtab_cursor *cur){
          961  +  amatch_cursor *pCur = (amatch_cursor *)cur;
          962  +  amatchClearCursor(pCur);
          963  +  pCur->pVtab->nCursor--;
          964  +  sqlite3_free(pCur);
          965  +  return SQLITE_OK;
          966  +}
          967  +
          968  +/*
          969  +** Render a 24-bit unsigned integer as a 4-byte base-64 number.
          970  +*/
          971  +static void amatchEncodeInt(int x, char *z){
          972  +  static const char a[] = 
          973  +    "0123456789"
          974  +    "ABCDEFGHIJ"
          975  +    "KLMNOPQRST"
          976  +    "UVWXYZ^abc"
          977  +    "defghijklm"
          978  +    "nopqrstuvw"
          979  +    "xyz~";
          980  +  z[0] = a[(x>>18)&0x3f];
          981  +  z[1] = a[(x>>12)&0x3f];
          982  +  z[2] = a[(x>>6)&0x3f];
          983  +  z[3] = a[x&0x3f];
          984  +}
          985  +
          986  +/*
          987  +** Write the zCost[] field for a amatch_word object
          988  +*/
          989  +static void amatchWriteCost(amatch_word *pWord){
          990  +  amatchEncodeInt(pWord->rCost, pWord->zCost);
          991  +  amatchEncodeInt(pWord->iSeq, pWord->zCost+4);
          992  +  pWord->zCost[8] = 0;
          993  +}
          994  +
          995  +/*
          996  +** Add a new amatch_word object to the queue.
          997  +**
          998  +** If a prior amatch_word object with the same zWord, and nMatch
          999  +** already exists, update its rCost (if the new rCost is less) but
         1000  +** otherwise leave it unchanged.  Do not add a duplicate.
         1001  +**
         1002  +** Do nothing if the cost exceeds threshold.
         1003  +*/
         1004  +static void amatchAddWord(
         1005  +  amatch_cursor *pCur,
         1006  +  amatch_cost rCost,
         1007  +  int nMatch,
         1008  +  const char *zWordBase,
         1009  +  const char *zWordTail
         1010  +){
         1011  +  amatch_word *pWord;
         1012  +  amatch_avl *pNode;
         1013  +  amatch_avl *pOther;
         1014  +  int nBase, nTail;
         1015  +  char zBuf[4];
         1016  +  
         1017  +  if( rCost>pCur->rLimit ){
         1018  +    return;
         1019  +  }
         1020  +  nBase = (int)strlen(zWordBase);
         1021  +  nTail = (int)strlen(zWordTail);
         1022  +  if( nBase+nTail+3>pCur->nBuf ){
         1023  +    pCur->nBuf = nBase+nTail+100;
         1024  +    pCur->zBuf = sqlite3_realloc(pCur->zBuf, pCur->nBuf);
         1025  +    if( pCur->zBuf==0 ){
         1026  +      pCur->nBuf = 0;
         1027  +      return;
         1028  +    }
         1029  +  }
         1030  +  amatchEncodeInt(nMatch, zBuf);
         1031  +  memcpy(pCur->zBuf, zBuf+2, 2);
         1032  +  memcpy(pCur->zBuf+2, zWordBase, nBase);
         1033  +  memcpy(pCur->zBuf+2+nBase, zWordTail, nTail+1);
         1034  +  pNode = amatchAvlSearch(pCur->pWord, pCur->zBuf);
         1035  +  if( pNode ){
         1036  +    pWord = pNode->pWord;
         1037  +    if( pWord->rCost>rCost ){
         1038  +#ifdef AMATCH_TRACE_1
         1039  +      printf("UPDATE [%s][%.*s^%s] %d (\"%s\" \"%s\")\n",
         1040  +             pWord->zWord+2, pWord->nMatch, pCur->zInput, pCur->zInput,
         1041  +             pWord->rCost, pWord->zWord, pWord->zCost);
         1042  +#endif
         1043  +      amatchAvlRemove(&pCur->pCost, &pWord->sCost);
         1044  +      pWord->rCost = rCost;
         1045  +      amatchWriteCost(pWord);
         1046  +#ifdef AMATCH_TRACE_1
         1047  +      printf("  ---> %d (\"%s\" \"%s\")\n",
         1048  +             pWord->rCost, pWord->zWord, pWord->zCost);
         1049  +#endif
         1050  +      pOther = amatchAvlInsert(&pCur->pCost, &pWord->sCost);
         1051  +      assert( pOther==0 ); (void)pOther;
         1052  +    }
         1053  +    return;
         1054  +  }
         1055  +  pWord = sqlite3_malloc( sizeof(*pWord) + nBase + nTail - 1 );
         1056  +  if( pWord==0 ) return;
         1057  +  memset(pWord, 0, sizeof(*pWord));
         1058  +  pWord->rCost = rCost;
         1059  +  pWord->iSeq = pCur->nWord++;
         1060  +  amatchWriteCost(pWord);
         1061  +  pWord->nMatch = nMatch;
         1062  +  pWord->pNext = pCur->pAllWords;
         1063  +  pCur->pAllWords = pWord;
         1064  +  pWord->sCost.zKey = pWord->zCost;
         1065  +  pWord->sCost.pWord = pWord;
         1066  +  pOther = amatchAvlInsert(&pCur->pCost, &pWord->sCost);
         1067  +  assert( pOther==0 ); (void)pOther;
         1068  +  pWord->sWord.zKey = pWord->zWord;
         1069  +  pWord->sWord.pWord = pWord;
         1070  +  strcpy(pWord->zWord, pCur->zBuf);
         1071  +  pOther = amatchAvlInsert(&pCur->pWord, &pWord->sWord);
         1072  +  assert( pOther==0 ); (void)pOther;
         1073  +#ifdef AMATCH_TRACE_1
         1074  +  printf("INSERT [%s][%.*s^%s] %d (\"%s\" \"%s\")\n", pWord->zWord+2,
         1075  +       pWord->nMatch, pCur->zInput, pCur->zInput+pWord->nMatch, rCost,
         1076  +       pWord->zWord, pWord->zCost);
         1077  +#endif
         1078  +}
         1079  +
         1080  +/*
         1081  +** Advance a cursor to its next row of output
         1082  +*/
         1083  +static int amatchNext(sqlite3_vtab_cursor *cur){
         1084  +  amatch_cursor *pCur = (amatch_cursor*)cur;
         1085  +  amatch_word *pWord = 0;
         1086  +  amatch_avl *pNode;
         1087  +  int isMatch = 0;
         1088  +  amatch_vtab *p = pCur->pVtab;
         1089  +  int nWord;
         1090  +  int rc;
         1091  +  int i;
         1092  +  const char *zW;
         1093  +  amatch_rule *pRule;
         1094  +  char *zBuf = 0;
         1095  +  char nBuf = 0;
         1096  +  char zNext[8];
         1097  +  char zNextIn[8];
         1098  +  int nNextIn;
         1099  +
         1100  +  if( p->pVCheck==0 ){
         1101  +    char *zSql;
         1102  +    if( p->zVocabLang && p->zVocabLang[0] ){
         1103  +      zSql = sqlite3_mprintf(
         1104  +          "SELECT \"%s\" FROM \"%s\"",
         1105  +          " WHERE \"%w\">=?1 AND \"%w\"=?2"
         1106  +          " ORDER BY 1",
         1107  +          p->zVocabWord, p->zVocabTab,
         1108  +          p->zVocabWord, p->zVocabLang
         1109  +      );
         1110  +    }else{
         1111  +      zSql = sqlite3_mprintf(
         1112  +          "SELECT \"%s\" FROM \"%s\""
         1113  +          " WHERE \"%w\">=?1"
         1114  +          " ORDER BY 1",
         1115  +          p->zVocabWord, p->zVocabTab,
         1116  +          p->zVocabWord
         1117  +      );
         1118  +    }
         1119  +    rc = sqlite3_prepare_v2(p->db, zSql, -1, &p->pVCheck, 0);
         1120  +    sqlite3_free(zSql);
         1121  +    if( rc ) return rc;
         1122  +  }
         1123  +  sqlite3_bind_int(p->pVCheck, 2, pCur->iLang);
         1124  +
         1125  +  do{
         1126  +    pNode = amatchAvlFirst(pCur->pCost);
         1127  +    if( pNode==0 ){
         1128  +      pWord = 0;
         1129  +      break;
         1130  +    }
         1131  +    pWord = pNode->pWord;
         1132  +    amatchAvlRemove(&pCur->pCost, &pWord->sCost);
         1133  +
         1134  +#ifdef AMATCH_TRACE_1
         1135  +    printf("PROCESS [%s][%.*s^%s] %d (\"%s\" \"%s\")\n",
         1136  +       pWord->zWord+2, pWord->nMatch, pCur->zInput, pCur->zInput+pWord->nMatch,
         1137  +       pWord->rCost, pWord->zWord, pWord->zCost);
         1138  +#endif
         1139  +    nWord = (int)strlen(pWord->zWord+2);
         1140  +    if( nWord+20>nBuf ){
         1141  +      nBuf = nWord+100;
         1142  +      zBuf = sqlite3_realloc(zBuf, nBuf);
         1143  +      if( zBuf==0 ) return SQLITE_NOMEM;
         1144  +    }
         1145  +    strcpy(zBuf, pWord->zWord+2);
         1146  +    zNext[0] = 0;
         1147  +    zNextIn[0] = pCur->zInput[pWord->nMatch];
         1148  +    if( zNextIn[0] ){
         1149  +      for(i=1; i<=4 && (pCur->zInput[pWord->nMatch+i]&0xc0)==0x80; i++){
         1150  +        zNextIn[i] = pCur->zInput[pWord->nMatch+i];
         1151  +      }
         1152  +      zNextIn[i] = 0;
         1153  +      nNextIn = i;
         1154  +    }else{
         1155  +      nNextIn = 0;
         1156  +    }
         1157  +
         1158  +    if( zNextIn[0] && zNextIn[0]!='*' ){
         1159  +      sqlite3_reset(p->pVCheck);
         1160  +      strcat(zBuf, zNextIn);
         1161  +      sqlite3_bind_text(p->pVCheck, 1, zBuf, nWord+nNextIn, SQLITE_STATIC);
         1162  +      rc = sqlite3_step(p->pVCheck);
         1163  +      if( rc==SQLITE_ROW ){
         1164  +        zW = (const char*)sqlite3_column_text(p->pVCheck, 0);
         1165  +        if( strncmp(zBuf, zW, nWord+nNextIn)==0 ){
         1166  +          amatchAddWord(pCur, pWord->rCost, pWord->nMatch+nNextIn, zBuf, "");
         1167  +        }
         1168  +      }
         1169  +      zBuf[nWord] = 0;
         1170  +    }
         1171  +
         1172  +    while( 1 ){
         1173  +      strcpy(zBuf+nWord, zNext);
         1174  +      sqlite3_reset(p->pVCheck);
         1175  +      sqlite3_bind_text(p->pVCheck, 1, zBuf, -1, SQLITE_TRANSIENT);
         1176  +      rc = sqlite3_step(p->pVCheck);
         1177  +      if( rc!=SQLITE_ROW ) break;
         1178  +      zW = (const char*)sqlite3_column_text(p->pVCheck, 0);
         1179  +      strcpy(zBuf+nWord, zNext);
         1180  +      if( strncmp(zW, zBuf, nWord)!=0 ) break;
         1181  +      if( (zNextIn[0]=='*' && zNextIn[1]==0)
         1182  +       || (zNextIn[0]==0 && zW[nWord]==0)
         1183  +      ){
         1184  +        isMatch = 1;
         1185  +        zNextIn[0] = 0;
         1186  +        nNextIn = 0;
         1187  +        break;
         1188  +      }
         1189  +      zNext[0] = zW[nWord];
         1190  +      for(i=1; i<=4 && (zW[nWord+i]&0xc0)==0x80; i++){
         1191  +        zNext[i] = zW[nWord+i];
         1192  +      }
         1193  +      zNext[i] = 0;
         1194  +      zBuf[nWord] = 0;
         1195  +      if( p->rIns>0 ){
         1196  +        amatchAddWord(pCur, pWord->rCost+p->rIns, pWord->nMatch, 
         1197  +                      zBuf, zNext);
         1198  +      }
         1199  +      if( p->rSub>0 ){
         1200  +        amatchAddWord(pCur, pWord->rCost+p->rSub, pWord->nMatch+nNextIn, 
         1201  +                      zBuf, zNext);
         1202  +      }
         1203  +      if( p->rIns<0 && p->rSub<0 ) break;
         1204  +      zNext[i-1]++;  /* FIX ME */
         1205  +    }
         1206  +    sqlite3_reset(p->pVCheck);
         1207  +
         1208  +    if( p->rDel>0 ){
         1209  +      zBuf[nWord] = 0;
         1210  +      amatchAddWord(pCur, pWord->rCost+p->rDel, pWord->nMatch+nNextIn,
         1211  +                    zBuf, "");
         1212  +    }
         1213  +
         1214  +    for(pRule=p->pRule; pRule; pRule=pRule->pNext){
         1215  +      if( pRule->iLang!=pCur->iLang ) continue;
         1216  +      if( strncmp(pRule->zFrom, pCur->zInput+pWord->nMatch, pRule->nFrom)==0 ){
         1217  +        amatchAddWord(pCur, pWord->rCost+pRule->rCost,
         1218  +                      pWord->nMatch+pRule->nFrom, pWord->zWord+2, pRule->zTo);
         1219  +      }
         1220  +    }
         1221  +  }while( !isMatch );
         1222  +  pCur->pCurrent = pWord;
         1223  +  sqlite3_free(zBuf);
         1224  +  return SQLITE_OK;
         1225  +}
         1226  +
         1227  +/*
         1228  +** Called to "rewind" a cursor back to the beginning so that
         1229  +** it starts its output over again.  Always called at least once
         1230  +** prior to any amatchColumn, amatchRowid, or amatchEof call.
         1231  +*/
         1232  +static int amatchFilter(
         1233  +  sqlite3_vtab_cursor *pVtabCursor, 
         1234  +  int idxNum, const char *idxStr,
         1235  +  int argc, sqlite3_value **argv
         1236  +){
         1237  +  amatch_cursor *pCur = (amatch_cursor *)pVtabCursor;
         1238  +  const char *zWord = "*";
         1239  +  int idx;
         1240  +
         1241  +  amatchClearCursor(pCur);
         1242  +  idx = 0;
         1243  +  if( idxNum & 1 ){
         1244  +    zWord = (const char*)sqlite3_value_text(argv[0]);
         1245  +    idx++;
         1246  +  }
         1247  +  if( idxNum & 2 ){
         1248  +    pCur->rLimit = (amatch_cost)sqlite3_value_int(argv[idx]);
         1249  +    idx++;
         1250  +  }
         1251  +  if( idxNum & 4 ){
         1252  +    pCur->iLang = (amatch_cost)sqlite3_value_int(argv[idx]);
         1253  +    idx++;
         1254  +  }
         1255  +  pCur->zInput = sqlite3_mprintf("%s", zWord);
         1256  +  if( pCur->zInput==0 ) return SQLITE_NOMEM;
         1257  +  amatchAddWord(pCur, 0, 0, "", "");
         1258  +  amatchNext(pVtabCursor);
         1259  +
         1260  +  return SQLITE_OK;
         1261  +}
         1262  +
         1263  +/*
         1264  +** Only the word and distance columns have values.  All other columns
         1265  +** return NULL
         1266  +*/
         1267  +static int amatchColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
         1268  +  amatch_cursor *pCur = (amatch_cursor*)cur;
         1269  +  switch( i ){
         1270  +    case AMATCH_COL_WORD: {
         1271  +      sqlite3_result_text(ctx, pCur->pCurrent->zWord+2, -1, SQLITE_STATIC);
         1272  +      break;
         1273  +    }
         1274  +    case AMATCH_COL_DISTANCE: {
         1275  +      sqlite3_result_int(ctx, pCur->pCurrent->rCost);
         1276  +      break;
         1277  +    }
         1278  +    case AMATCH_COL_LANGUAGE: {
         1279  +      sqlite3_result_int(ctx, pCur->iLang);
         1280  +      break;
         1281  +    }
         1282  +    case AMATCH_COL_NWORD: {
         1283  +      sqlite3_result_int(ctx, pCur->nWord);
         1284  +      break;
         1285  +    }
         1286  +    default: {
         1287  +      sqlite3_result_null(ctx);
         1288  +      break;
         1289  +    }
         1290  +  }
         1291  +  return SQLITE_OK;
         1292  +}
         1293  +
         1294  +/*
         1295  +** The rowid.
         1296  +*/
         1297  +static int amatchRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
         1298  +  amatch_cursor *pCur = (amatch_cursor*)cur;
         1299  +  *pRowid = pCur->iRowid;
         1300  +  return SQLITE_OK;
         1301  +}
         1302  +
         1303  +/*
         1304  +** EOF indicator
         1305  +*/
         1306  +static int amatchEof(sqlite3_vtab_cursor *cur){
         1307  +  amatch_cursor *pCur = (amatch_cursor*)cur;
         1308  +  return pCur->pCurrent==0;
         1309  +}
         1310  +
         1311  +/*
         1312  +** Search for terms of these forms:
         1313  +**
         1314  +**   (A)    word MATCH $str
         1315  +**   (B1)   distance < $value
         1316  +**   (B2)   distance <= $value
         1317  +**   (C)    language == $language
         1318  +**
         1319  +** The distance< and distance<= are both treated as distance<=.
         1320  +** The query plan number is a bit vector:
         1321  +**
         1322  +**   bit 1:   Term of the form (A) found
         1323  +**   bit 2:   Term like (B1) or (B2) found
         1324  +**   bit 3:   Term like (C) found
         1325  +**
         1326  +** If bit-1 is set, $str is always in filter.argv[0].  If bit-2 is set
         1327  +** then $value is in filter.argv[0] if bit-1 is clear and is in 
         1328  +** filter.argv[1] if bit-1 is set.  If bit-3 is set, then $ruleid is
         1329  +** in filter.argv[0] if bit-1 and bit-2 are both zero, is in
         1330  +** filter.argv[1] if exactly one of bit-1 and bit-2 are set, and is in
         1331  +** filter.argv[2] if both bit-1 and bit-2 are set.
         1332  +*/
         1333  +static int amatchBestIndex(
         1334  +  sqlite3_vtab *tab,
         1335  +  sqlite3_index_info *pIdxInfo
         1336  +){
         1337  +  int iPlan = 0;
         1338  +  int iDistTerm = -1;
         1339  +  int iLangTerm = -1;
         1340  +  int i;
         1341  +  const struct sqlite3_index_constraint *pConstraint;
         1342  +
         1343  +  (void)tab;
         1344  +  pConstraint = pIdxInfo->aConstraint;
         1345  +  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
         1346  +    if( pConstraint->usable==0 ) continue;
         1347  +    if( (iPlan & 1)==0 
         1348  +     && pConstraint->iColumn==0
         1349  +     && pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH
         1350  +    ){
         1351  +      iPlan |= 1;
         1352  +      pIdxInfo->aConstraintUsage[i].argvIndex = 1;
         1353  +      pIdxInfo->aConstraintUsage[i].omit = 1;
         1354  +    }
         1355  +    if( (iPlan & 2)==0
         1356  +     && pConstraint->iColumn==1
         1357  +     && (pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT
         1358  +           || pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE)
         1359  +    ){
         1360  +      iPlan |= 2;
         1361  +      iDistTerm = i;
         1362  +    }
         1363  +    if( (iPlan & 4)==0
         1364  +     && pConstraint->iColumn==2
         1365  +     && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
         1366  +    ){
         1367  +      iPlan |= 4;
         1368  +      pIdxInfo->aConstraintUsage[i].omit = 1;
         1369  +      iLangTerm = i;
         1370  +    }
         1371  +  }
         1372  +  if( iPlan & 2 ){
         1373  +    pIdxInfo->aConstraintUsage[iDistTerm].argvIndex = 1+((iPlan&1)!=0);
         1374  +  }
         1375  +  if( iPlan & 4 ){
         1376  +    int idx = 1;
         1377  +    if( iPlan & 1 ) idx++;
         1378  +    if( iPlan & 2 ) idx++;
         1379  +    pIdxInfo->aConstraintUsage[iLangTerm].argvIndex = idx;
         1380  +  }
         1381  +  pIdxInfo->idxNum = iPlan;
         1382  +  if( pIdxInfo->nOrderBy==1
         1383  +   && pIdxInfo->aOrderBy[0].iColumn==1
         1384  +   && pIdxInfo->aOrderBy[0].desc==0
         1385  +  ){
         1386  +    pIdxInfo->orderByConsumed = 1;
         1387  +  }
         1388  +  pIdxInfo->estimatedCost = (double)10000;
         1389  +   
         1390  +  return SQLITE_OK;
         1391  +}
         1392  +
         1393  +/*
         1394  +** The xUpdate() method.  
         1395  +**
         1396  +** This implementation disallows DELETE and UPDATE.  The only thing
         1397  +** allowed is INSERT into the "command" column.
         1398  +*/
         1399  +static int amatchUpdate(
         1400  +  sqlite3_vtab *pVTab,
         1401  +  int argc,
         1402  +  sqlite3_value **argv,
         1403  +  sqlite_int64 *pRowid
         1404  +){
         1405  +  amatch_vtab *p = (amatch_vtab*)pVTab;
         1406  +  const unsigned char *zCmd;
         1407  +  (void)pRowid;
         1408  +  if( argc==1 ){
         1409  +    pVTab->zErrMsg = sqlite3_mprintf("DELETE from %s is not allowed", 
         1410  +                                      p->zSelf);
         1411  +    return SQLITE_ERROR;
         1412  +  }
         1413  +  if( sqlite3_value_type(argv[0])!=SQLITE_NULL ){
         1414  +    pVTab->zErrMsg = sqlite3_mprintf("UPDATE of %s is not allowed", 
         1415  +                                      p->zSelf);
         1416  +    return SQLITE_ERROR;
         1417  +  }
         1418  +  if( sqlite3_value_type(argv[2+AMATCH_COL_WORD])!=SQLITE_NULL
         1419  +   || sqlite3_value_type(argv[2+AMATCH_COL_DISTANCE])!=SQLITE_NULL
         1420  +   || sqlite3_value_type(argv[2+AMATCH_COL_LANGUAGE])!=SQLITE_NULL
         1421  +  ){
         1422  +    pVTab->zErrMsg = sqlite3_mprintf(
         1423  +            "INSERT INTO %s allowed for column [command] only", p->zSelf);
         1424  +    return SQLITE_ERROR;
         1425  +  }
         1426  +  zCmd = sqlite3_value_text(argv[2+AMATCH_COL_COMMAND]);
         1427  +  if( zCmd==0 ) return SQLITE_OK;
         1428  +  
         1429  +  return SQLITE_OK;
         1430  +}
         1431  +
         1432  +/*
         1433  +** A virtual table module that implements the "approximate_match".
         1434  +*/
         1435  +static sqlite3_module amatchModule = {
         1436  +  0,                      /* iVersion */
         1437  +  amatchConnect,          /* xCreate */
         1438  +  amatchConnect,          /* xConnect */
         1439  +  amatchBestIndex,        /* xBestIndex */
         1440  +  amatchDisconnect,       /* xDisconnect */
         1441  +  amatchDisconnect,       /* xDestroy */
         1442  +  amatchOpen,             /* xOpen - open a cursor */
         1443  +  amatchClose,            /* xClose - close a cursor */
         1444  +  amatchFilter,           /* xFilter - configure scan constraints */
         1445  +  amatchNext,             /* xNext - advance a cursor */
         1446  +  amatchEof,              /* xEof - check for end of scan */
         1447  +  amatchColumn,           /* xColumn - read data */
         1448  +  amatchRowid,            /* xRowid - read data */
         1449  +  amatchUpdate,           /* xUpdate */
         1450  +  0,                      /* xBegin */
         1451  +  0,                      /* xSync */
         1452  +  0,                      /* xCommit */
         1453  +  0,                      /* xRollback */
         1454  +  0,                      /* xFindMethod */
         1455  +  0,                      /* xRename */
         1456  +  0,                      /* xSavepoint */
         1457  +  0,                      /* xRelease */
         1458  +  0                       /* xRollbackTo */
         1459  +};
         1460  +
         1461  +/*
         1462  +** Register the amatch virtual table
         1463  +*/
         1464  +#ifdef _WIN32
         1465  +__declspec(dllexport)
         1466  +#endif
         1467  +int sqlite3_amatch_init(
         1468  +  sqlite3 *db, 
         1469  +  char **pzErrMsg, 
         1470  +  const sqlite3_api_routines *pApi
         1471  +){
         1472  +  int rc = SQLITE_OK;
         1473  +  SQLITE_EXTENSION_INIT2(pApi);
         1474  +  (void)pzErrMsg;  /* Not used */
         1475  +  rc = sqlite3_create_module(db, "approximate_match", &amatchModule, 0);
         1476  +  return rc;
         1477  +}

Added ext/misc/closure.c.

            1  +/*
            2  +** 2013-04-16
            3  +**
            4  +** The author disclaims copyright to this source code.  In place of
            5  +** a legal notice, here is a blessing:
            6  +**
            7  +**    May you do good and not evil.
            8  +**    May you find forgiveness for yourself and forgive others.
            9  +**    May you share freely, never taking more than you give.
           10  +**
           11  +*************************************************************************
           12  +**
           13  +** This file contains code for a virtual table that finds the transitive
           14  +** closure of a parent/child relationship in a real table.  The virtual 
           15  +** table is called "transitive_closure".
           16  +**
           17  +** A transitive_closure virtual table is created like this:
           18  +**
           19  +**     CREATE VIRTUAL TABLE x USING transitive_closure(
           20  +**        tablename=<tablename>,      -- T
           21  +**        idcolumn=<columnname>,      -- X
           22  +**        parentcolumn=<columnname>   -- P
           23  +**     );
           24  +**
           25  +** When it is created, the new transitive_closure table may be supplied 
           26  +** with default values for the name of a table T and columns T.X and T.P.
           27  +** The T.X and T.P columns must contain integers.  The ideal case is for 
           28  +** T.X to be the INTEGER PRIMARY KEY.  The T.P column should reference
           29  +** the T.X column. The row referenced by T.P is the parent of the current row.
           30  +**
           31  +** The tablename, idcolumn, and parentcolumn supplied by the CREATE VIRTUAL
           32  +** TABLE statement may be overridden in individual queries by including
           33  +** terms like tablename='newtable', idcolumn='id2', or 
           34  +** parentcolumn='parent3' in the WHERE clause of the query.
           35  +**
           36  +** For efficiency, it is essential that there be an index on the P column:
           37  +**
           38  +**    CREATE Tidx1 ON T(P)
           39  +**
           40  +** Suppose a specific instance of the closure table is as follows:
           41  +**
           42  +**    CREATE VIRTUAL TABLE ct1 USING transitive_closure(
           43  +**       tablename='group',
           44  +**       idcolumn='groupId',
           45  +**       parentcolumn='parentId'
           46  +**    );
           47  +**
           48  +** Such an instance of the transitive_closure virtual table would be
           49  +** appropriate for walking a tree defined using a table like this, for example:
           50  +**
           51  +**    CREATE TABLE group(
           52  +**      groupId INTEGER PRIMARY KEY,
           53  +**      parentId INTEGER REFERENCES group
           54  +**    );
           55  +**    CREATE INDEX group_idx1 ON group(parentId);
           56  +**
           57  +** The group table above would presumably have other application-specific
           58  +** fields.  The key point here is that rows of the group table form a
           59  +** tree.  The purpose of the ct1 virtual table is to easily extract
           60  +** branches of that tree.
           61  +**
           62  +** Once it has been created, the ct1 virtual table can be queried
           63  +** as follows:
           64  +**
           65  +**    SELECT * FROM element
           66  +**     WHERE element.groupId IN (SELECT id FROM ct1 WHERE root=?1);
           67  +**
           68  +** The above query will return all elements that are part of group ?1
           69  +** or children of group ?1 or grand-children of ?1 and so forth for all
           70  +** descendents of group ?1.  The same query can be formulated as a join:
           71  +**
           72  +**    SELECT element.* FROM element, ct1
           73  +**     WHERE element.groupid=ct1.id
           74  +**       AND ct1.root=?1;
           75  +**
           76  +** The depth of the transitive_closure (the number of generations of
           77  +** parent/child relations to follow) can be limited by setting "depth"
           78  +** column in the WHERE clause.  So, for example, the following query
           79  +** finds only children and grandchildren but no further descendents:
           80  +**
           81  +**    SELECT element.* FROM element, ct1
           82  +**     WHERE element.groupid=ct1.id
           83  +**       AND ct1.root=?1
           84  +**       AND ct1.depth<=2;
           85  +**
           86  +** The "ct1.depth<=2" term could be a strict equality "ct1.depth=2" in
           87  +** order to find only the grandchildren of ?1, not ?1 itself or the
           88  +** children of ?1.
           89  +** 
           90  +** The root=?1 term must be supplied in WHERE clause or else the query
           91  +** of the ct1 virtual table will return an empty set.  The tablename,
           92  +** idcolumn, and parentcolumn attributes can be overridden in the WHERE
           93  +** clause if desired.  So, for example, the ct1 table could be repurposed
           94  +** to find ancestors rather than descendents by inverting the roles of
           95  +** the idcolumn and parentcolumn:
           96  +**
           97  +**    SELECT element.* FROM element, ct1
           98  +**     WHERE element.groupid=ct1.id
           99  +**       AND ct1.root=?1
          100  +**       AND ct1.idcolumn='parentId'
          101  +**       AND ct1.parentcolumn='groupId';
          102  +**
          103  +** Multiple calls to ct1 could be combined.  For example, the following
          104  +** query finds all elements that "cousins" of groupId ?1.  That is to say
          105  +** elements where the groupId is a grandchild of the grandparent of ?1.
          106  +** (This definition of "cousins" also includes siblings and self.)
          107  +**
          108  +**    SELECT element.* FROM element, ct1
          109  +**     WHERE element.groupId=ct1.id
          110  +**       AND ct1.depth=2
          111  +**       AND ct1.root IN (SELECT id FROM ct1
          112  +**                         WHERE root=?1
          113  +**                           AND depth=2
          114  +**                           AND idcolumn='parentId'
          115  +**                           AND parentcolumn='groupId');
          116  +**
          117  +** In our example, the group.groupId column is unique and thus the
          118  +** subquery will return exactly one row.  For that reason, the IN
          119  +** operator could be replaced by "=" to get the same result.  But
          120  +** in the general case where the idcolumn is not unique, an IN operator
          121  +** would be required for this kind of query.
          122  +**
          123  +** Note that because the tablename, idcolumn, and parentcolumn can
          124  +** all be specified in the query, it is possible for an application
          125  +** to define a single transitive_closure virtual table for use on lots
          126  +** of different hierarchy tables.  One might say:
          127  +**
          128  +**     CREATE VIRTUAL TABLE temp.closure USING transitive_closure;
          129  +**
          130  +** As each database connection is being opened.  Then the application
          131  +** would always have a "closure" virtual table handy to use for querying.
          132  +**
          133  +**    SELECT element.* FROM element, closure
          134  +**     WHERE element.groupid=ct1.id
          135  +**       AND closure.root=?1
          136  +**       AND closure.tablename='group'
          137  +**       AND closure.idname='groupId'
          138  +**       AND closure.parentname='parentId';
          139  +**
          140  +** See the documentation at http://www.sqlite.org/loadext.html for information
          141  +** on how to compile and use loadable extensions such as this one.
          142  +*/
          143  +#include "sqlite3ext.h"
          144  +SQLITE_EXTENSION_INIT1
          145  +#include <stdlib.h>
          146  +#include <string.h>
          147  +#include <assert.h>
          148  +#include <stdio.h>
          149  +#include <ctype.h>
          150  +
          151  +/*
          152  +** Forward declaration of objects used by this implementation
          153  +*/
          154  +typedef struct closure_vtab closure_vtab;
          155  +typedef struct closure_cursor closure_cursor;
          156  +typedef struct closure_queue closure_queue;
          157  +typedef struct closure_avl closure_avl;
          158  +
          159  +/*****************************************************************************
          160  +** AVL Tree implementation
          161  +*/
          162  +/*
          163  +** Objects that want to be members of the AVL tree should embedded an
          164  +** instance of this structure.
          165  +*/
          166  +struct closure_avl {
          167  +  sqlite3_int64 id;     /* Id of this entry in the table */
          168  +  int iGeneration;      /* Which generation is this entry part of */
          169  +  closure_avl *pList;   /* A linked list of nodes */
          170  +  closure_avl *pBefore; /* Other elements less than id */
          171  +  closure_avl *pAfter;  /* Other elements greater than id */
          172  +  closure_avl *pUp;     /* Parent element */
          173  +  short int height;     /* Height of this node.  Leaf==1 */
          174  +  short int imbalance;  /* Height difference between pBefore and pAfter */
          175  +};
          176  +
          177  +/* Recompute the closure_avl.height and closure_avl.imbalance fields for p.
          178  +** Assume that the children of p have correct heights.
          179  +*/
          180  +static void closureAvlRecomputeHeight(closure_avl *p){
          181  +  short int hBefore = p->pBefore ? p->pBefore->height : 0;
          182  +  short int hAfter = p->pAfter ? p->pAfter->height : 0;
          183  +  p->imbalance = hBefore - hAfter;  /* -: pAfter higher.  +: pBefore higher */
          184  +  p->height = (hBefore>hAfter ? hBefore : hAfter)+1;
          185  +}
          186  +
          187  +/*
          188  +**     P                B
          189  +**    / \              / \
          190  +**   B   Z    ==>     X   P
          191  +**  / \                  / \
          192  +** X   Y                Y   Z
          193  +**
          194  +*/
          195  +static closure_avl *closureAvlRotateBefore(closure_avl *pP){
          196  +  closure_avl *pB = pP->pBefore;
          197  +  closure_avl *pY = pB->pAfter;
          198  +  pB->pUp = pP->pUp;
          199  +  pB->pAfter = pP;
          200  +  pP->pUp = pB;
          201  +  pP->pBefore = pY;
          202  +  if( pY ) pY->pUp = pP;
          203  +  closureAvlRecomputeHeight(pP);
          204  +  closureAvlRecomputeHeight(pB);
          205  +  return pB;
          206  +}
          207  +
          208  +/*
          209  +**     P                A
          210  +**    / \              / \
          211  +**   X   A    ==>     P   Z
          212  +**      / \          / \
          213  +**     Y   Z        X   Y
          214  +**
          215  +*/
          216  +static closure_avl *closureAvlRotateAfter(closure_avl *pP){
          217  +  closure_avl *pA = pP->pAfter;
          218  +  closure_avl *pY = pA->pBefore;
          219  +  pA->pUp = pP->pUp;
          220  +  pA->pBefore = pP;
          221  +  pP->pUp = pA;
          222  +  pP->pAfter = pY;
          223  +  if( pY ) pY->pUp = pP;
          224  +  closureAvlRecomputeHeight(pP);
          225  +  closureAvlRecomputeHeight(pA);
          226  +  return pA;
          227  +}
          228  +
          229  +/*
          230  +** Return a pointer to the pBefore or pAfter pointer in the parent
          231  +** of p that points to p.  Or if p is the root node, return pp.
          232  +*/
          233  +static closure_avl **closureAvlFromPtr(closure_avl *p, closure_avl **pp){
          234  +  closure_avl *pUp = p->pUp;
          235  +  if( pUp==0 ) return pp;
          236  +  if( pUp->pAfter==p ) return &pUp->pAfter;
          237  +  return &pUp->pBefore;
          238  +}
          239  +
          240  +/*
          241  +** Rebalance all nodes starting with p and working up to the root.
          242  +** Return the new root.
          243  +*/
          244  +static closure_avl *closureAvlBalance(closure_avl *p){
          245  +  closure_avl *pTop = p;
          246  +  closure_avl **pp;
          247  +  while( p ){
          248  +    closureAvlRecomputeHeight(p);
          249  +    if( p->imbalance>=2 ){
          250  +      closure_avl *pB = p->pBefore;
          251  +      if( pB->imbalance<0 ) p->pBefore = closureAvlRotateAfter(pB);
          252  +      pp = closureAvlFromPtr(p,&p);
          253  +      p = *pp = closureAvlRotateBefore(p);
          254  +    }else if( p->imbalance<=(-2) ){
          255  +      closure_avl *pA = p->pAfter;
          256  +      if( pA->imbalance>0 ) p->pAfter = closureAvlRotateBefore(pA);
          257  +      pp = closureAvlFromPtr(p,&p);
          258  +      p = *pp = closureAvlRotateAfter(p);
          259  +    }
          260  +    pTop = p;
          261  +    p = p->pUp;
          262  +  }
          263  +  return pTop;
          264  +}
          265  +
          266  +/* Search the tree rooted at p for an entry with id.  Return a pointer
          267  +** to the entry or return NULL.
          268  +*/
          269  +static closure_avl *closureAvlSearch(closure_avl *p, sqlite3_int64 id){
          270  +  while( p && id!=p->id ){
          271  +    p = (id<p->id) ? p->pBefore : p->pAfter;
          272  +  }
          273  +  return p;
          274  +}
          275  +
          276  +/* Find the first node (the one with the smallest key).
          277  +*/
          278  +static closure_avl *closureAvlFirst(closure_avl *p){
          279  +  if( p ) while( p->pBefore ) p = p->pBefore;
          280  +  return p;
          281  +}
          282  +
          283  +/* Return the node with the next larger key after p.
          284  +*/
          285  +closure_avl *closureAvlNext(closure_avl *p){
          286  +  closure_avl *pPrev = 0;
          287  +  while( p && p->pAfter==pPrev ){
          288  +    pPrev = p;
          289  +    p = p->pUp;
          290  +  }
          291  +  if( p && pPrev==0 ){
          292  +    p = closureAvlFirst(p->pAfter);
          293  +  }
          294  +  return p;
          295  +}
          296  +	
          297  +/* Insert a new node pNew.  Return NULL on success.  If the key is not
          298  +** unique, then do not perform the insert but instead leave pNew unchanged
          299  +** and return a pointer to an existing node with the same key.
          300  +*/
          301  +static closure_avl *closureAvlInsert(
          302  +  closure_avl **ppHead,  /* Head of the tree */
          303  +  closure_avl *pNew      /* New node to be inserted */
          304  +){
          305  +  closure_avl *p = *ppHead;
          306  +  if( p==0 ){
          307  +    p = pNew;
          308  +    pNew->pUp = 0;
          309  +  }else{
          310  +    while( p ){
          311  +      if( pNew->id<p->id ){
          312  +        if( p->pBefore ){
          313  +          p = p->pBefore;
          314  +        }else{
          315  +          p->pBefore = pNew;
          316  +          pNew->pUp = p;
          317  +          break;
          318  +        }
          319  +      }else if( pNew->id>p->id ){
          320  +        if( p->pAfter ){
          321  +          p = p->pAfter;
          322  +        }else{
          323  +          p->pAfter = pNew;
          324  +          pNew->pUp = p;
          325  +          break;
          326  +        }
          327  +      }else{
          328  +        return p;
          329  +      }
          330  +    }
          331  +  }
          332  +  pNew->pBefore = 0;
          333  +  pNew->pAfter = 0;
          334  +  pNew->height = 1;
          335  +  pNew->imbalance = 0;
          336  +  *ppHead = closureAvlBalance(p);
          337  +  return 0;
          338  +}
          339  +
          340  +/* Walk the tree can call xDestroy on each node
          341  +*/
          342  +static void closureAvlDestroy(closure_avl *p, void (*xDestroy)(closure_avl*)){
          343  +  if( p ){
          344  +    closureAvlDestroy(p->pBefore, xDestroy);
          345  +    closureAvlDestroy(p->pAfter, xDestroy);
          346  +    xDestroy(p);
          347  +  }
          348  +}
          349  +/*
          350  +** End of the AVL Tree implementation
          351  +******************************************************************************/
          352  +
          353  +/* 
          354  +** A closure virtual-table object 
          355  +*/
          356  +struct closure_vtab {
          357  +  sqlite3_vtab base;         /* Base class - must be first */
          358  +  char *zDb;                 /* Name of database.  (ex: "main") */
          359  +  char *zSelf;               /* Name of this virtual table */
          360  +  char *zTableName;          /* Name of table holding parent/child relation */
          361  +  char *zIdColumn;           /* Name of ID column of zTableName */
          362  +  char *zParentColumn;       /* Name of PARENT column in zTableName */
          363  +  sqlite3 *db;               /* The database connection */
          364  +  int nCursor;               /* Number of pending cursors */
          365  +};
          366  +
          367  +/* A closure cursor object */
          368  +struct closure_cursor {
          369  +  sqlite3_vtab_cursor base;  /* Base class - must be first */
          370  +  closure_vtab *pVtab;       /* The virtual table this cursor belongs to */
          371  +  char *zTableName;          /* Name of table holding parent/child relation */
          372  +  char *zIdColumn;           /* Name of ID column of zTableName */
          373  +  char *zParentColumn;       /* Name of PARENT column in zTableName */
          374  +  closure_avl *pCurrent;     /* Current element of output */
          375  +  closure_avl *pClosure;     /* The complete closure tree */
          376  +};
          377  +
          378  +/* A queue of AVL nodes */
          379  +struct closure_queue {
          380  +  closure_avl *pFirst;       /* Oldest node on the queue */
          381  +  closure_avl *pLast;        /* Youngest node on the queue */
          382  +};
          383  +
          384  +/*
          385  +** Add a node to the end of the queue
          386  +*/
          387  +static void queuePush(closure_queue *pQueue, closure_avl *pNode){
          388  +  pNode->pList = 0;
          389  +  if( pQueue->pLast ){
          390  +    pQueue->pLast->pList = pNode;
          391  +  }else{
          392  +    pQueue->pFirst = pNode;
          393  +  }
          394  +  pQueue->pLast = pNode;
          395  +}
          396  +
          397  +/*
          398  +** Extract the oldest element (the front element) from the queue.
          399  +*/
          400  +static closure_avl *queuePull(closure_queue *pQueue){
          401  +  closure_avl *p = pQueue->pFirst;
          402  +  if( p ){
          403  +    pQueue->pFirst = p->pList;
          404  +    if( pQueue->pFirst==0 ) pQueue->pLast = 0;
          405  +  }
          406  +  return p;
          407  +}
          408  +
          409  +/*
          410  +** This function converts an SQL quoted string into an unquoted string
          411  +** and returns a pointer to a buffer allocated using sqlite3_malloc() 
          412  +** containing the result. The caller should eventually free this buffer
          413  +** using sqlite3_free.
          414  +**
          415  +** Examples:
          416  +**
          417  +**     "abc"   becomes   abc
          418  +**     'xyz'   becomes   xyz
          419  +**     [pqr]   becomes   pqr
          420  +**     `mno`   becomes   mno
          421  +*/
          422  +static char *closureDequote(const char *zIn){
          423  +  int nIn;                        /* Size of input string, in bytes */
          424  +  char *zOut;                     /* Output (dequoted) string */
          425  +
          426  +  nIn = (int)strlen(zIn);
          427  +  zOut = sqlite3_malloc(nIn+1);
          428  +  if( zOut ){
          429  +    char q = zIn[0];              /* Quote character (if any ) */
          430  +
          431  +    if( q!='[' && q!= '\'' && q!='"' && q!='`' ){
          432  +      memcpy(zOut, zIn, nIn+1);
          433  +    }else{
          434  +      int iOut = 0;               /* Index of next byte to write to output */
          435  +      int iIn;                    /* Index of next byte to read from input */
          436  +
          437  +      if( q=='[' ) q = ']';
          438  +      for(iIn=1; iIn<nIn; iIn++){
          439  +        if( zIn[iIn]==q ) iIn++;
          440  +        zOut[iOut++] = zIn[iIn];
          441  +      }
          442  +    }
          443  +    assert( (int)strlen(zOut)<=nIn );
          444  +  }
          445  +  return zOut;
          446  +}
          447  +
          448  +/*
          449  +** Deallocate an closure_vtab object
          450  +*/
          451  +static void closureFree(closure_vtab *p){
          452  +  if( p ){
          453  +    sqlite3_free(p->zDb);
          454  +    sqlite3_free(p->zSelf);
          455  +    sqlite3_free(p->zTableName);
          456  +    sqlite3_free(p->zIdColumn);
          457  +    sqlite3_free(p->zParentColumn);
          458  +    memset(p, 0, sizeof(*p));
          459  +    sqlite3_free(p);
          460  +  }
          461  +}
          462  +
          463  +/*
          464  +** xDisconnect/xDestroy method for the closure module.
          465  +*/
          466  +static int closureDisconnect(sqlite3_vtab *pVtab){
          467  +  closure_vtab *p = (closure_vtab*)pVtab;
          468  +  assert( p->nCursor==0 );
          469  +  closureFree(p);
          470  +  return SQLITE_OK;
          471  +}
          472  +
          473  +/*
          474  +** Check to see if the argument is of the form:
          475  +**
          476  +**       KEY = VALUE
          477  +**
          478  +** If it is, return a pointer to the first character of VALUE.
          479  +** If not, return NULL.  Spaces around the = are ignored.
          480  +*/
          481  +static const char *closureValueOfKey(const char *zKey, const char *zStr){
          482  +  int nKey = (int)strlen(zKey);
          483  +  int nStr = (int)strlen(zStr);
          484  +  int i;
          485  +  if( nStr<nKey+1 ) return 0;
          486  +  if( memcmp(zStr, zKey, nKey)!=0 ) return 0;
          487  +  for(i=nKey; isspace(zStr[i]); i++){}
          488  +  if( zStr[i]!='=' ) return 0;
          489  +  i++;
          490  +  while( isspace(zStr[i]) ){ i++; }
          491  +  return zStr+i;
          492  +}
          493  +
          494  +/*
          495  +** xConnect/xCreate method for the closure module. Arguments are:
          496  +**
          497  +**   argv[0]    -> module name  ("approximate_match")
          498  +**   argv[1]    -> database name
          499  +**   argv[2]    -> table name
          500  +**   argv[3...] -> arguments
          501  +*/
          502  +static int closureConnect(
          503  +  sqlite3 *db,
          504  +  void *pAux,
          505  +  int argc, const char *const*argv,
          506  +  sqlite3_vtab **ppVtab,
          507  +  char **pzErr
          508  +){
          509  +  int rc = SQLITE_OK;              /* Return code */
          510  +  closure_vtab *pNew = 0;          /* New virtual table */
          511  +  const char *zDb = argv[1];
          512  +  const char *zVal;
          513  +  int i;
          514  +
          515  +  (void)pAux;
          516  +  *ppVtab = 0;
          517  +  pNew = sqlite3_malloc( sizeof(*pNew) );
          518  +  if( pNew==0 ) return SQLITE_NOMEM;
          519  +  rc = SQLITE_NOMEM;
          520  +  memset(pNew, 0, sizeof(*pNew));
          521  +  pNew->db = db;
          522  +  pNew->zDb = sqlite3_mprintf("%s", zDb);
          523  +  if( pNew->zDb==0 ) goto closureConnectError;
          524  +  pNew->zSelf = sqlite3_mprintf("%s", argv[2]);
          525  +  if( pNew->zSelf==0 ) goto closureConnectError;
          526  +  for(i=3; i<argc; i++){
          527  +    zVal = closureValueOfKey("tablename", argv[i]);
          528  +    if( zVal ){
          529  +      sqlite3_free(pNew->zTableName);
          530  +      pNew->zTableName = closureDequote(zVal);
          531  +      if( pNew->zTableName==0 ) goto closureConnectError;
          532  +      continue;
          533  +    }
          534  +    zVal = closureValueOfKey("idcolumn", argv[i]);
          535  +    if( zVal ){
          536  +      sqlite3_free(pNew->zIdColumn);
          537  +      pNew->zIdColumn = closureDequote(zVal);
          538  +      if( pNew->zIdColumn==0 ) goto closureConnectError;
          539  +      continue;
          540  +    }
          541  +    zVal = closureValueOfKey("parentcolumn", argv[i]);
          542  +    if( zVal ){
          543  +      sqlite3_free(pNew->zParentColumn);
          544  +      pNew->zParentColumn = closureDequote(zVal);
          545  +      if( pNew->zParentColumn==0 ) goto closureConnectError;
          546  +      continue;
          547  +    }
          548  +    *pzErr = sqlite3_mprintf("unrecognized argument: [%s]\n", argv[i]);
          549  +    closureFree(pNew);
          550  +    *ppVtab = 0;
          551  +    return SQLITE_ERROR;
          552  +  }
          553  +  rc = sqlite3_declare_vtab(db,
          554  +         "CREATE TABLE x(id,depth,root HIDDEN,tablename HIDDEN,"
          555  +                        "idcolumn HIDDEN,parentcolumn HIDDEN)"
          556  +       );
          557  +#define CLOSURE_COL_ID              0
          558  +#define CLOSURE_COL_DEPTH           1
          559  +#define CLOSURE_COL_ROOT            2
          560  +#define CLOSURE_COL_TABLENAME       3
          561  +#define CLOSURE_COL_IDCOLUMN        4
          562  +#define CLOSURE_COL_PARENTCOLUMN    5
          563  +  if( rc!=SQLITE_OK ){
          564  +    closureFree(pNew);
          565  +  }
          566  +  *ppVtab = &pNew->base;
          567  +  return rc;
          568  +
          569  +closureConnectError:
          570  +  closureFree(pNew);
          571  +  return rc;
          572  +}
          573  +
          574  +/*
          575  +** Open a new closure cursor.
          576  +*/
          577  +static int closureOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
          578  +  closure_vtab *p = (closure_vtab*)pVTab;
          579  +  closure_cursor *pCur;
          580  +  pCur = sqlite3_malloc( sizeof(*pCur) );
          581  +  if( pCur==0 ) return SQLITE_NOMEM;
          582  +  memset(pCur, 0, sizeof(*pCur));
          583  +  pCur->pVtab = p;
          584  +  *ppCursor = &pCur->base;
          585  +  p->nCursor++;
          586  +  return SQLITE_OK;
          587  +}
          588  +
          589  +/*
          590  +** Free up all the memory allocated by a cursor.  Set it rLimit to 0
          591  +** to indicate that it is at EOF.
          592  +*/
          593  +static void closureClearCursor(closure_cursor *pCur){
          594  +  closureAvlDestroy(pCur->pClosure, (void(*)(closure_avl*))sqlite3_free);
          595  +  sqlite3_free(pCur->zTableName);
          596  +  sqlite3_free(pCur->zIdColumn);
          597  +  sqlite3_free(pCur->zParentColumn);
          598  +  pCur->zTableName = 0;
          599  +  pCur->zIdColumn = 0;
          600  +  pCur->zParentColumn = 0;
          601  +  pCur->pCurrent = 0;
          602  +  pCur->pClosure = 0;
          603  +}
          604  +
          605  +/*
          606  +** Close a closure cursor.
          607  +*/
          608  +static int closureClose(sqlite3_vtab_cursor *cur){
          609  +  closure_cursor *pCur = (closure_cursor *)cur;
          610  +  closureClearCursor(pCur);
          611  +  pCur->pVtab->nCursor--;
          612  +  sqlite3_free(pCur);
          613  +  return SQLITE_OK;
          614  +}
          615  +
          616  +/*
          617  +** Advance a cursor to its next row of output
          618  +*/
          619  +static int closureNext(sqlite3_vtab_cursor *cur){
          620  +  closure_cursor *pCur = (closure_cursor*)cur;
          621  +  pCur->pCurrent = closureAvlNext(pCur->pCurrent);
          622  +  return SQLITE_OK;
          623  +}
          624  +
          625  +/*
          626  +** Allocate and insert a node
          627  +*/
          628  +static int closureInsertNode(
          629  +  closure_queue *pQueue,  /* Add new node to this queue */
          630  +  closure_cursor *pCur,   /* The cursor into which to add the node */
          631  +  sqlite3_int64 id,       /* The node ID */
          632  +  int iGeneration         /* The generation number for this node */
          633  +){
          634  +  closure_avl *pNew = sqlite3_malloc( sizeof(*pNew) );
          635  +  if( pNew==0 ) return SQLITE_NOMEM;
          636  +  memset(pNew, 0, sizeof(*pNew));
          637  +  pNew->id = id;
          638  +  pNew->iGeneration = iGeneration;
          639  +  closureAvlInsert(&pCur->pClosure, pNew);
          640  +  queuePush(pQueue, pNew);
          641  +  return SQLITE_OK;
          642  +}
          643  +
          644  +/*
          645  +** Called to "rewind" a cursor back to the beginning so that
          646  +** it starts its output over again.  Always called at least once
          647  +** prior to any closureColumn, closureRowid, or closureEof call.
          648  +**
          649  +** This routine actually computes the closure.
          650  +**
          651  +** See the comment at the beginning of closureBestIndex() for a 
          652  +** description of the meaning of idxNum.  The idxStr parameter is
          653  +** not used.
          654  +*/
          655  +static int closureFilter(
          656  +  sqlite3_vtab_cursor *pVtabCursor, 
          657  +  int idxNum, const char *idxStr,
          658  +  int argc, sqlite3_value **argv
          659  +){
          660  +  closure_cursor *pCur = (closure_cursor *)pVtabCursor;
          661  +  closure_vtab *pVtab = pCur->pVtab;
          662  +  sqlite3_int64 iRoot;
          663  +  int mxGen = 999999999;
          664  +  char *zSql;
          665  +  sqlite3_stmt *pStmt;
          666  +  closure_avl *pAvl;
          667  +  int rc = SQLITE_OK;
          668  +  const char *zTableName = pVtab->zTableName;
          669  +  const char *zIdColumn = pVtab->zIdColumn;
          670  +  const char *zParentColumn = pVtab->zParentColumn;
          671  +  closure_queue sQueue;
          672  +
          673  +  (void)idxStr;  /* Unused parameter */
          674  +  (void)argc;    /* Unused parameter */
          675  +  closureClearCursor(pCur);
          676  +  memset(&sQueue, 0, sizeof(sQueue));
          677  +  if( (idxNum & 1)==0 ){
          678  +    /* No root=$root in the WHERE clause.  Return an empty set */
          679  +    return SQLITE_OK;
          680  +  }
          681  +  iRoot = sqlite3_value_int64(argv[0]);
          682  +  if( (idxNum & 0x000f0)!=0 ){
          683  +    mxGen = sqlite3_value_int(argv[(idxNum>>4)&0x0f]);
          684  +    if( (idxNum & 0x00002)!=0 ) mxGen--;
          685  +  }
          686  +  if( (idxNum & 0x00f00)!=0 ){
          687  +    zTableName = (const char*)sqlite3_value_text(argv[(idxNum>>8)&0x0f]);
          688  +    pCur->zTableName = sqlite3_mprintf("%s", zTableName);
          689  +  }
          690  +  if( (idxNum & 0x0f000)!=0 ){
          691  +    zIdColumn = (const char*)sqlite3_value_text(argv[(idxNum>>12)&0x0f]);
          692  +    pCur->zIdColumn = sqlite3_mprintf("%s", zIdColumn);
          693  +  }
          694  +  if( (idxNum & 0x0f0000)!=0 ){
          695  +    zParentColumn = (const char*)sqlite3_value_text(argv[(idxNum>>16)&0x0f]);
          696  +    pCur->zParentColumn = sqlite3_mprintf("%s", zParentColumn);
          697  +  }
          698  +
          699  +  zSql = sqlite3_mprintf(
          700  +       "SELECT \"%w\".\"%w\" FROM \"%w\" WHERE \"%w\".\"%w\"=?1",
          701  +       zTableName, zIdColumn, zTableName, zTableName, zParentColumn);
          702  +  if( zSql==0 ){
          703  +    return SQLITE_NOMEM;
          704  +  }else{
          705  +    rc = sqlite3_prepare_v2(pVtab->db, zSql, -1, &pStmt, 0);
          706  +    sqlite3_free(zSql);
          707  +    if( rc ){
          708  +      sqlite3_free(pVtab->base.zErrMsg);
          709  +      pVtab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pVtab->db));
          710  +      return rc;
          711  +    }
          712  +  }
          713  +  if( rc==SQLITE_OK ){
          714  +    rc = closureInsertNode(&sQueue, pCur, iRoot, 0);
          715  +  }
          716  +  while( (pAvl = queuePull(&sQueue))!=0 ){
          717  +    if( pAvl->iGeneration>=mxGen ) continue;
          718  +    sqlite3_bind_int64(pStmt, 1, pAvl->id);
          719  +    while( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
          720  +      if( sqlite3_column_type(pStmt,0)==SQLITE_INTEGER ){
          721  +        sqlite3_int64 iNew = sqlite3_column_int64(pStmt, 0);
          722  +        if( closureAvlSearch(pCur->pClosure, iNew)==0 ){
          723  +          rc = closureInsertNode(&sQueue, pCur, iNew, pAvl->iGeneration+1);
          724  +        }
          725  +      }
          726  +    }
          727  +    sqlite3_reset(pStmt);
          728  +  }
          729  +  sqlite3_finalize(pStmt);
          730  +  if( rc==SQLITE_OK ){
          731  +    pCur->pCurrent = closureAvlFirst(pCur->pClosure);
          732  +  }
          733  +
          734  +  return rc;
          735  +}
          736  +
          737  +/*
          738  +** Only the word and distance columns have values.  All other columns
          739  +** return NULL
          740  +*/
          741  +static int closureColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
          742  +  closure_cursor *pCur = (closure_cursor*)cur;
          743  +  switch( i ){
          744  +    case CLOSURE_COL_ID: {
          745  +      sqlite3_result_int64(ctx, pCur->pCurrent->id);
          746  +      break;
          747  +    }
          748  +    case CLOSURE_COL_DEPTH: {
          749  +      sqlite3_result_int(ctx, pCur->pCurrent->iGeneration);
          750  +      break;
          751  +    }
          752  +    case CLOSURE_COL_ROOT: {
          753  +      sqlite3_result_null(ctx);
          754  +      break;
          755  +    }
          756  +    case CLOSURE_COL_TABLENAME: {
          757  +      sqlite3_result_text(ctx,
          758  +         pCur->zTableName ? pCur->zTableName : pCur->pVtab->zTableName,
          759  +         -1, SQLITE_TRANSIENT);
          760  +      break;
          761  +    }
          762  +    case CLOSURE_COL_IDCOLUMN: {
          763  +      sqlite3_result_text(ctx,
          764  +         pCur->zIdColumn ? pCur->zIdColumn : pCur->pVtab->zIdColumn,
          765  +         -1, SQLITE_TRANSIENT);
          766  +      break;
          767  +    }
          768  +    case CLOSURE_COL_PARENTCOLUMN: {
          769  +      sqlite3_result_text(ctx,
          770  +         pCur->zParentColumn ? pCur->zParentColumn : pCur->pVtab->zParentColumn,
          771  +         -1, SQLITE_TRANSIENT);
          772  +      break;
          773  +    }
          774  +  }
          775  +  return SQLITE_OK;
          776  +}
          777  +
          778  +/*
          779  +** The rowid.  For the closure table, this is the same as the "id" column.
          780  +*/
          781  +static int closureRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
          782  +  closure_cursor *pCur = (closure_cursor*)cur;
          783  +  *pRowid = pCur->pCurrent->id;
          784  +  return SQLITE_OK;
          785  +}
          786  +
          787  +/*
          788  +** EOF indicator
          789  +*/
          790  +static int closureEof(sqlite3_vtab_cursor *cur){
          791  +  closure_cursor *pCur = (closure_cursor*)cur;
          792  +  return pCur->pCurrent==0;
          793  +}
          794  +
          795  +/*
          796  +** Search for terms of these forms:
          797  +**
          798  +**   (A)    root = $root
          799  +**   (B1)   depth < $depth
          800  +**   (B2)   depth <= $depth
          801  +**   (B3)   depth = $depth
          802  +**   (C)    tablename = $tablename
          803  +**   (D)    idcolumn = $idcolumn
          804  +**   (E)    parentcolumn = $parentcolumn
          805  +**
          806  +** 
          807  +**
          808  +**   idxNum       meaning
          809  +**   ----------   ------------------------------------------------------
          810  +**   0x00000001   Term of the form (A) found
          811  +**   0x00000002   The term of bit-2 is like (B1)
          812  +**   0x000000f0   Index in filter.argv[] of $depth.  0 if not used.
          813  +**   0x00000f00   Index in filter.argv[] of $tablename.  0 if not used.
          814  +**   0x0000f000   Index in filter.argv[] of $idcolumn.  0 if not used
          815  +**   0x000f0000   Index in filter.argv[] of $parentcolumn.  0 if not used.
          816  +**
          817  +** There must be a term of type (A).  If there is not, then the index type
          818  +** is 0 and the query will return an empty set.
          819  +*/
          820  +static int closureBestIndex(
          821  +  sqlite3_vtab *pTab,             /* The virtual table */
          822  +  sqlite3_index_info *pIdxInfo    /* Information about the query */
          823  +){
          824  +  int iPlan = 0;
          825  +  int i;
          826  +  int idx = 1;
          827  +  const struct sqlite3_index_constraint *pConstraint;
          828  +  closure_vtab *pVtab = (closure_vtab*)pTab;
          829  +
          830  +  pConstraint = pIdxInfo->aConstraint;
          831  +  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
          832  +    if( pConstraint->usable==0 ) continue;
          833  +    if( (iPlan & 1)==0 
          834  +     && pConstraint->iColumn==CLOSURE_COL_ROOT
          835  +     && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
          836  +    ){
          837  +      iPlan |= 1;
          838  +      pIdxInfo->aConstraintUsage[i].argvIndex = 1;
          839  +      pIdxInfo->aConstraintUsage[i].omit = 1;
          840  +    }
          841  +    if( (iPlan & 0x0000f0)==0
          842  +     && pConstraint->iColumn==CLOSURE_COL_DEPTH
          843  +     && (pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT
          844  +           || pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE
          845  +           || pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ)
          846  +    ){
          847  +      iPlan |= idx<<4;
          848  +      pIdxInfo->aConstraintUsage[i].argvIndex = ++idx;
          849  +      if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT ) iPlan |= 0x000002;
          850  +    }
          851  +    if( (iPlan & 0x000f00)==0
          852  +     && pConstraint->iColumn==CLOSURE_COL_TABLENAME
          853  +     && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
          854  +    ){
          855  +      iPlan |= idx<<8;
          856  +      pIdxInfo->aConstraintUsage[i].argvIndex = ++idx;
          857  +      pIdxInfo->aConstraintUsage[i].omit = 1;
          858  +    }
          859  +    if( (iPlan & 0x00f000)==0
          860  +     && pConstraint->iColumn==CLOSURE_COL_IDCOLUMN
          861  +     && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
          862  +    ){
          863  +      iPlan |= idx<<12;
          864  +      pIdxInfo->aConstraintUsage[i].argvIndex = ++idx;
          865  +      pIdxInfo->aConstraintUsage[i].omit = 1;
          866  +    }
          867  +    if( (iPlan & 0x0f0000)==0
          868  +     && pConstraint->iColumn==CLOSURE_COL_PARENTCOLUMN
          869  +     && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
          870  +    ){
          871  +      iPlan |= idx<<16;
          872  +      pIdxInfo->aConstraintUsage[i].argvIndex = ++idx;
          873  +      pIdxInfo->aConstraintUsage[i].omit = 1;
          874  +    }
          875  +  }
          876  +  if( (pVtab->zTableName==0    && (iPlan & 0x000f00)==0)
          877  +   || (pVtab->zIdColumn==0     && (iPlan & 0x00f000)==0)
          878  +   || (pVtab->zParentColumn==0 && (iPlan & 0x0f0000)==0)
          879  +  ){
          880  +    /* All of tablename, idcolumn, and parentcolumn must be specified
          881  +    ** in either the CREATE VIRTUAL TABLE or in the WHERE clause constraints
          882  +    ** or else the result is an empty set. */
          883  +    iPlan = 0;
          884  +  }
          885  +  pIdxInfo->idxNum = iPlan;
          886  +  if( pIdxInfo->nOrderBy==1
          887  +   && pIdxInfo->aOrderBy[0].iColumn==CLOSURE_COL_ID
          888  +   && pIdxInfo->aOrderBy[0].desc==0
          889  +  ){
          890  +    pIdxInfo->orderByConsumed = 1;
          891  +  }
          892  +  pIdxInfo->estimatedCost = (double)10000;
          893  +   
          894  +  return SQLITE_OK;
          895  +}
          896  +
          897  +/*
          898  +** A virtual table module that implements the "approximate_match".
          899  +*/
          900  +static sqlite3_module closureModule = {
          901  +  0,                      /* iVersion */
          902  +  closureConnect,         /* xCreate */
          903  +  closureConnect,         /* xConnect */
          904  +  closureBestIndex,       /* xBestIndex */
          905  +  closureDisconnect,      /* xDisconnect */
          906  +  closureDisconnect,      /* xDestroy */
          907  +  closureOpen,            /* xOpen - open a cursor */
          908  +  closureClose,           /* xClose - close a cursor */
          909  +  closureFilter,          /* xFilter - configure scan constraints */
          910  +  closureNext,            /* xNext - advance a cursor */
          911  +  closureEof,             /* xEof - check for end of scan */
          912  +  closureColumn,          /* xColumn - read data */
          913  +  closureRowid,           /* xRowid - read data */
          914  +  0,                      /* xUpdate */
          915  +  0,                      /* xBegin */
          916  +  0,                      /* xSync */
          917  +  0,                      /* xCommit */
          918  +  0,                      /* xRollback */
          919  +  0,                      /* xFindMethod */
          920  +  0,                      /* xRename */
          921  +  0,                      /* xSavepoint */
          922  +  0,                      /* xRelease */
          923  +  0                       /* xRollbackTo */
          924  +};
          925  +
          926  +/*
          927  +** Register the closure virtual table
          928  +*/
          929  +#ifdef _WIN32
          930  +__declspec(dllexport)
          931  +#endif
          932  +int sqlite3_closure_init(
          933  +  sqlite3 *db, 
          934  +  char **pzErrMsg, 
          935  +  const sqlite3_api_routines *pApi
          936  +){
          937  +  int rc = SQLITE_OK;
          938  +  SQLITE_EXTENSION_INIT2(pApi);
          939  +  (void)pzErrMsg;
          940  +  rc = sqlite3_create_module(db, "transitive_closure", &closureModule, 0);
          941  +  return rc;
          942  +}

Name change from src/test_fuzzer.c to ext/misc/fuzzer.c.

   137    137   **
   138    138   ** LIMITS
   139    139   **
   140    140   ** The maximum ruleset number is 2147483647.  The maximum length of either
   141    141   ** of the strings in the second or third column of the fuzzer data table
   142    142   ** is 50 bytes.  The maximum cost on a rule is 1000.
   143    143   */
          144  +#include "sqlite3ext.h"
          145  +SQLITE_EXTENSION_INIT1
   144    146   
   145    147   /* If SQLITE_DEBUG is not defined, disable assert statements. */
   146    148   #if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
   147    149   # define NDEBUG
   148    150   #endif
   149    151   
   150         -#include "sqlite3.h"
   151    152   #include <stdlib.h>
   152    153   #include <string.h>
   153    154   #include <assert.h>
   154    155   #include <stdio.h>
   155    156   
   156    157   #ifndef SQLITE_OMIT_VIRTUALTABLE
   157    158   
................................................................................
  1151   1152     0,                           /* xFindMethod */
  1152   1153     0,                           /* xRename */
  1153   1154   };
  1154   1155   
  1155   1156   #endif /* SQLITE_OMIT_VIRTUALTABLE */
  1156   1157   
  1157   1158   
  1158         -/*
  1159         -** Register the fuzzer virtual table
  1160         -*/
  1161         -int fuzzer_register(sqlite3 *db){
         1159  +#ifdef _WIN32
         1160  +__declspec(dllexport)
         1161  +#endif
         1162  +int sqlite3_fuzzer_init(
         1163  +  sqlite3 *db, 
         1164  +  char **pzErrMsg, 
         1165  +  const sqlite3_api_routines *pApi
         1166  +){
  1162   1167     int rc = SQLITE_OK;
  1163         -#ifndef SQLITE_OMIT_VIRTUALTABLE
         1168  +  SQLITE_EXTENSION_INIT2(pApi);
  1164   1169     rc = sqlite3_create_module(db, "fuzzer", &fuzzerModule, 0);
  1165         -#endif
  1166   1170     return rc;
  1167   1171   }
  1168         -
  1169         -#ifdef SQLITE_TEST
  1170         -#include <tcl.h>
  1171         -/*
  1172         -** Decode a pointer to an sqlite3 object.
  1173         -*/
  1174         -extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
  1175         -
  1176         -/*
  1177         -** Register the echo virtual table module.
  1178         -*/
  1179         -static int register_fuzzer_module(
  1180         -  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  1181         -  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  1182         -  int objc,              /* Number of arguments */
  1183         -  Tcl_Obj *CONST objv[]  /* Command arguments */
  1184         -){
  1185         -  sqlite3 *db;
  1186         -  if( objc!=2 ){
  1187         -    Tcl_WrongNumArgs(interp, 1, objv, "DB");
  1188         -    return TCL_ERROR;
  1189         -  }
  1190         -  getDbPointer(interp, Tcl_GetString(objv[1]), &db);
  1191         -  fuzzer_register(db);
  1192         -  return TCL_OK;
  1193         -}
  1194         -
  1195         -
  1196         -/*
  1197         -** Register commands with the TCL interpreter.
  1198         -*/
  1199         -int Sqlitetestfuzzer_Init(Tcl_Interp *interp){
  1200         -  static struct {
  1201         -     char *zName;
  1202         -     Tcl_ObjCmdProc *xProc;
  1203         -     void *clientData;
  1204         -  } aObjCmd[] = {
  1205         -     { "register_fuzzer_module",   register_fuzzer_module, 0 },
  1206         -  };
  1207         -  int i;
  1208         -  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
  1209         -    Tcl_CreateObjCommand(interp, aObjCmd[i].zName, 
  1210         -        aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
  1211         -  }
  1212         -  return TCL_OK;
  1213         -}
  1214         -
  1215         -#endif /* SQLITE_TEST */

Added ext/misc/ieee754.c.

            1  +/*
            2  +** 2013-04-17
            3  +**
            4  +** The author disclaims copyright to this source code.  In place of
            5  +** a legal notice, here is a blessing:
            6  +**
            7  +**    May you do good and not evil.
            8  +**    May you find forgiveness for yourself and forgive others.
            9  +**    May you share freely, never taking more than you give.
           10  +**
           11  +******************************************************************************
           12  +**
           13  +** This SQLite extension implements functions for the exact display
           14  +** and input of IEEE754 Binary64 floating-point numbers.
           15  +**
           16  +**   ieee754(X)
           17  +**   ieee754(Y,Z)
           18  +**
           19  +** In the first form, the value X should be a floating-point number.
           20  +** The function will return a string of the form 'ieee754(Y,Z)' where
           21  +** Y and Z are integers such that X==Y*pow(w.0,Z).
           22  +**
           23  +** In the second form, Y and Z are integers which are the mantissa and
           24  +** base-2 exponent of a new floating point number.  The function returns
           25  +** a floating-point value equal to Y*pow(2.0,Z).
           26  +**
           27  +** Examples:
           28  +**
           29  +**     ieee754(2.0)       ->     'ieee754(2,0)'
           30  +**     ieee754(45.25)     ->     'ieee754(181,-2)'
           31  +**     ieee754(2, 0)      ->     2.0
           32  +**     ieee754(181, -2)   ->     45.25
           33  +*/
           34  +#include "sqlite3ext.h"
           35  +SQLITE_EXTENSION_INIT1
           36  +#include <assert.h>
           37  +#include <string.h>
           38  +
           39  +/*
           40  +** Implementation of the ieee754() function
           41  +*/
           42  +static void ieee754func(
           43  +  sqlite3_context *context,
           44  +  int argc,
           45  +  sqlite3_value **argv
           46  +){
           47  +  if( argc==1 ){
           48  +    sqlite3_int64 m, a;
           49  +    double r;
           50  +    int e;
           51  +    int isNeg;
           52  +    char zResult[100];
           53  +    assert( sizeof(m)==sizeof(r) );
           54  +    if( sqlite3_value_type(argv[0])!=SQLITE_FLOAT ) return;
           55  +    r = sqlite3_value_double(argv[0]);
           56  +    if( r<0.0 ){
           57  +      isNeg = 1;
           58  +      r = -r;
           59  +    }else{
           60  +      isNeg = 0;
           61  +    }
           62  +    memcpy(&a,&r,sizeof(a));
           63  +    if( a==0 ){
           64  +      e = 0;
           65  +      m = 0;
           66  +    }else{
           67  +      e = a>>52;
           68  +      m = a & ((((sqlite3_int64)1)<<52)-1);
           69  +      m |= ((sqlite3_int64)1)<<52;
           70  +      while( e<1075 && m>0 && (m&1)==0 ){
           71  +        m >>= 1;
           72  +        e++;
           73  +      }
           74  +      if( isNeg ) m = -m;
           75  +    }
           76  +    sqlite3_snprintf(sizeof(zResult), zResult, "ieee754(%lld,%d)",
           77  +                     m, e-1075);
           78  +    sqlite3_result_text(context, zResult, -1, SQLITE_TRANSIENT);
           79  +  }else if( argc==2 ){
           80  +    sqlite3_int64 m, e, a;
           81  +    double r;
           82  +    int isNeg = 0;
           83  +    m = sqlite3_value_int64(argv[0]);
           84  +    e = sqlite3_value_int64(argv[1]);
           85  +    if( m<0 ){
           86  +      isNeg = 1;
           87  +      m = -m;
           88  +      if( m<0 ) return;
           89  +    }else if( m==0 && e>1000 && e<1000 ){
           90  +      sqlite3_result_double(context, 0.0);
           91  +      return;
           92  +    }
           93  +    while( (m>>32)&0xffe00000 ){
           94  +      m >>= 1;
           95  +      e++;
           96  +    }
           97  +    while( ((m>>32)&0xfff00000)==0 ){
           98  +      m <<= 1;
           99  +      e--;
          100  +    }
          101  +    e += 1075;
          102  +    if( e<0 ) e = m = 0;
          103  +    if( e>0x7ff ) m = 0;
          104  +    a = m & ((((sqlite3_int64)1)<<52)-1);
          105  +    a |= e<<52;
          106  +    if( isNeg ) a |= ((sqlite3_int64)1)<<63;
          107  +    memcpy(&r, &a, sizeof(r));
          108  +    sqlite3_result_double(context, r);
          109  +  }
          110  +}
          111  +
          112  +
          113  +#ifdef _WIN32
          114  +__declspec(dllexport)
          115  +#endif
          116  +int sqlite3_ieee_init(
          117  +  sqlite3 *db, 
          118  +  char **pzErrMsg, 
          119  +  const sqlite3_api_routines *pApi
          120  +){
          121  +  int rc = SQLITE_OK;
          122  +  SQLITE_EXTENSION_INIT2(pApi);
          123  +  (void)pzErrMsg;  /* Unused parameter */
          124  +  rc = sqlite3_create_function(db, "ieee754", 1, SQLITE_UTF8, 0,
          125  +                               ieee754func, 0, 0);
          126  +  if( rc==SQLITE_OK ){
          127  +    rc = sqlite3_create_function(db, "ieee754", 2, SQLITE_UTF8, 0,
          128  +                                 ieee754func, 0, 0);
          129  +  }
          130  +  return rc;
          131  +}

Added ext/misc/nextchar.c.

            1  +/*
            2  +** 2013-02-28
            3  +**
            4  +** The author disclaims copyright to this source code.  In place of
            5  +** a legal notice, here is a blessing:
            6  +**
            7  +**    May you do good and not evil.
            8  +**    May you find forgiveness for yourself and forgive others.
            9  +**    May you share freely, never taking more than you give.
           10  +**
           11  +******************************************************************************
           12  +**
           13  +** This file contains code to implement the next_char(A,T,F,W) SQL function.
           14  +**
           15  +** The next_char(A,T,F,H) function finds all valid "next" characters for
           16  +** string A given the vocabulary in T.F.  The T.F field should be indexed.
           17  +** If the W value exists and is a non-empty string, then it is an SQL
           18  +** expression that limits the entries in T.F that will be considered.
           19  +**
           20  +** For example, suppose an application has a dictionary like this:
           21  +**
           22  +**   CREATE TABLE dictionary(word TEXT UNIQUE);
           23  +**
           24  +** Further suppose that for user keypad entry, it is desired to disable
           25  +** (gray out) keys that are not valid as the next character.  If the
           26  +** the user has previously entered (say) 'cha' then to find all allowed
           27  +** next characters (and thereby determine when keys should not be grayed
           28  +** out) run the following query:
           29  +**
           30  +**   SELECT next_char('cha','dictionary','word');
           31  +*/
           32  +#include "sqlite3ext.h"
           33  +SQLITE_EXTENSION_INIT1
           34  +#include <string.h>
           35  +
           36  +/*
           37  +** A structure to hold context of the next_char() computation across
           38  +** nested function calls.
           39  +*/
           40  +typedef struct nextCharContext nextCharContext;
           41  +struct nextCharContext {
           42  +  sqlite3 *db;                      /* Database connection */
           43  +  sqlite3_stmt *pStmt;              /* Prepared statement used to query */
           44  +  const unsigned char *zPrefix;     /* Prefix to scan */
           45  +  int nPrefix;                      /* Size of zPrefix in bytes */
           46  +  int nAlloc;                       /* Space allocated to aResult */
           47  +  int nUsed;                        /* Space used in aResult */
           48  +  unsigned int *aResult;            /* Array of next characters */
           49  +  int mallocFailed;                 /* True if malloc fails */
           50  +  int otherError;                   /* True for any other failure */
           51  +};
           52  +
           53  +/*
           54  +** Append a result character if the character is not already in the
           55  +** result.
           56  +*/
           57  +static void nextCharAppend(nextCharContext *p, unsigned c){
           58  +  int i;
           59  +  for(i=0; i<p->nUsed; i++){
           60  +    if( p->aResult[i]==c ) return;
           61  +  }
           62  +  if( p->nUsed+1 > p->nAlloc ){
           63  +    unsigned int *aNew;
           64  +    int n = p->nAlloc*2 + 30;
           65  +    aNew = sqlite3_realloc(p->aResult, n*sizeof(unsigned int));
           66  +    if( aNew==0 ){
           67  +      p->mallocFailed = 1;
           68  +      return;
           69  +    }else{
           70  +      p->aResult = aNew;
           71  +      p->nAlloc = n;
           72  +    }
           73  +  }
           74  +  p->aResult[p->nUsed++] = c;
           75  +}
           76  +
           77  +/*
           78  +** Write a character into z[] as UTF8.  Return the number of bytes needed
           79  +** to hold the character
           80  +*/
           81  +static int writeUtf8(unsigned char *z, unsigned c){
           82  +  if( c<0x00080 ){
           83  +    z[0] = (unsigned char)(c&0xff);
           84  +    return 1;
           85  +  }
           86  +  if( c<0x00800 ){
           87  +    z[0] = 0xC0 + (unsigned char)((c>>6)&0x1F);
           88  +    z[1] = 0x80 + (unsigned char)(c & 0x3F);
           89  +    return 2;
           90  +  }
           91  +  if( c<0x10000 ){
           92  +    z[0] = 0xE0 + (unsigned char)((c>>12)&0x0F);
           93  +    z[1] = 0x80 + (unsigned char)((c>>6) & 0x3F);
           94  +    z[2] = 0x80 + (unsigned char)(c & 0x3F);
           95  +    return 3;
           96  +  }
           97  +  z[0] = 0xF0 + (unsigned char)((c>>18) & 0x07);
           98  +  z[1] = 0x80 + (unsigned char)((c>>12) & 0x3F);
           99  +  z[2] = 0x80 + (unsigned char)((c>>6) & 0x3F);
          100  +  z[3] = 0x80 + (unsigned char)(c & 0x3F);
          101  +  return 4;
          102  +}
          103  +
          104  +/*
          105  +** Read a UTF8 character out of z[] and write it into *pOut.  Return
          106  +** the number of bytes in z[] that were used to construct the character.
          107  +*/
          108  +static int readUtf8(const unsigned char *z, unsigned *pOut){
          109  +  static const unsigned char validBits[] = {
          110  +    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
          111  +    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
          112  +    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
          113  +    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
          114  +    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
          115  +    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
          116  +    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
          117  +    0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
          118  +  };
          119  +  unsigned c = z[0];
          120  +  if( c<0xc0 ){
          121  +    *pOut = c;
          122  +    return 1;
          123  +  }else{
          124  +    int n = 1;
          125  +    c = validBits[c-0xc0];
          126  +    while( (z[n] & 0xc0)==0x80 ){
          127  +      c = (c<<6) + (0x3f & z[n++]);
          128  +    }
          129  +    if( c<0x80 || (c&0xFFFFF800)==0xD800 || (c&0xFFFFFFFE)==0xFFFE ){
          130  +      c = 0xFFFD;
          131  +    }
          132  +    *pOut = c;
          133  +    return n;
          134  +  }
          135  +}
          136  +
          137  +/*
          138  +** The nextCharContext structure has been set up.  Add all "next" characters
          139  +** to the result set.
          140  +*/
          141  +static void findNextChars(nextCharContext *p){
          142  +  unsigned cPrev = 0;
          143  +  unsigned char zPrev[8];
          144  +  int n, rc;
          145  +  
          146  +  for(;;){
          147  +    sqlite3_bind_text(p->pStmt, 1, (char*)p->zPrefix, p->nPrefix,
          148  +                      SQLITE_STATIC);
          149  +    n = writeUtf8(zPrev, cPrev+1);
          150  +    sqlite3_bind_text(p->pStmt, 2, (char*)zPrev, n, SQLITE_STATIC);
          151  +    rc = sqlite3_step(p->pStmt);
          152  +    if( rc==SQLITE_DONE ){
          153  +      sqlite3_reset(p->pStmt);
          154  +      return;
          155  +    }else if( rc!=SQLITE_ROW ){
          156  +      p->otherError = rc;
          157  +      return;
          158  +    }else{
          159  +      const unsigned char *zOut = sqlite3_column_text(p->pStmt, 0);
          160  +      unsigned cNext;
          161  +      n = readUtf8(zOut+p->nPrefix, &cNext);
          162  +      sqlite3_reset(p->pStmt);
          163  +      nextCharAppend(p, cNext);
          164  +      cPrev = cNext;
          165  +      if( p->mallocFailed ) return;
          166  +    }
          167  +  }
          168  +}
          169  +
          170  +
          171  +/*
          172  +** next_character(A,T,F,W)
          173  +**
          174  +** Return a string composted of all next possible characters after
          175  +** A for elements of T.F.  If W is supplied, then it is an SQL expression
          176  +** that limits the elements in T.F that are considered.
          177  +*/
          178  +static void nextCharFunc(
          179  +  sqlite3_context *context,
          180  +  int argc,
          181  +  sqlite3_value **argv
          182  +){
          183  +  nextCharContext c;
          184  +  const unsigned char *zTable = sqlite3_value_text(argv[1]);
          185  +  const unsigned char *zField = sqlite3_value_text(argv[2]);
          186  +  const unsigned char *zWhere;
          187  +  char *zSql;
          188  +  int rc;
          189  +
          190  +  memset(&c, 0, sizeof(c));
          191  +  c.db = sqlite3_context_db_handle(context);
          192  +  c.zPrefix = sqlite3_value_text(argv[0]);
          193  +  c.nPrefix = sqlite3_value_bytes(argv[0]);
          194  +  if( zTable==0 || zField==0 || c.zPrefix==0 ) return;
          195  +  if( argc<4
          196  +   || (zWhere = sqlite3_value_text(argv[3]))==0
          197  +   || zWhere[0]==0
          198  +  ){
          199  +    zSql = sqlite3_mprintf(
          200  +        "SELECT \"%w\" FROM \"%w\""
          201  +        " WHERE \"%w\">=(?1 || ?2)"
          202  +        "   AND \"%w\"<=(?1 || char(1114111))" /* 1114111 == 0x10ffff */
          203  +        " ORDER BY 1 ASC LIMIT 1",
          204  +        zField, zTable, zField, zField);
          205  +  }else{
          206  +    zSql = sqlite3_mprintf(
          207  +        "SELECT \"%w\" FROM \"%w\""
          208  +        " WHERE \"%w\">=(?1 || ?2)"
          209  +        "   AND \"%w\"<=(?1 || char(1114111))" /* 1114111 == 0x10ffff */
          210  +        "   AND (%s)"
          211  +        " ORDER BY 1 ASC LIMIT 1",
          212  +        zField, zTable, zField, zField, zWhere);
          213  +  }
          214  +  if( zSql==0 ){
          215  +    sqlite3_result_error_nomem(context);
          216  +    return;
          217  +  }
          218  +
          219  +  rc = sqlite3_prepare_v2(c.db, zSql, -1, &c.pStmt, 0);
          220  +  sqlite3_free(zSql);
          221  +  if( rc ){
          222  +    sqlite3_result_error(context, sqlite3_errmsg(c.db), -1);
          223  +    return;
          224  +  }
          225  +  findNextChars(&c);
          226  +  if( c.mallocFailed ){
          227  +    sqlite3_result_error_nomem(context);
          228  +  }else{
          229  +    unsigned char *pRes;
          230  +    pRes = sqlite3_malloc( c.nUsed*4 + 1 );
          231  +    if( pRes==0 ){
          232  +      sqlite3_result_error_nomem(context);
          233  +    }else{
          234  +      int i;
          235  +      int n = 0;
          236  +      for(i=0; i<c.nUsed; i++){
          237  +        n += writeUtf8(pRes+n, c.aResult[i]);
          238  +      }
          239  +      pRes[n] = 0;
          240  +      sqlite3_result_text(context, (const char*)pRes, n, sqlite3_free);
          241  +    }
          242  +  }
          243  +  sqlite3_finalize(c.pStmt);
          244  +  sqlite3_free(c.aResult);
          245  +}
          246  +
          247  +#ifdef _WIN32
          248  +__declspec(dllexport)
          249  +#endif
          250  +int sqlite3_nextchar_init(
          251  +  sqlite3 *db, 
          252  +  char **pzErrMsg, 
          253  +  const sqlite3_api_routines *pApi
          254  +){
          255  +  int rc = SQLITE_OK;
          256  +  SQLITE_EXTENSION_INIT2(pApi);
          257  +  (void)pzErrMsg;  /* Unused parameter */
          258  +  rc = sqlite3_create_function(db, "next_char", 3, SQLITE_UTF8, 0,
          259  +                               nextCharFunc, 0, 0);
          260  +  if( rc==SQLITE_OK ){
          261  +    rc = sqlite3_create_function(db, "next_char", 4, SQLITE_UTF8, 0,
          262  +                                 nextCharFunc, 0, 0);
          263  +  }
          264  +  return rc;
          265  +}

Name change from src/test_regexp.c to ext/misc/regexp.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   ******************************************************************************
    12     12   **
    13     13   ** The code in this file implements a compact but reasonably
    14     14   ** efficient regular-expression matcher for posix extended regular
    15         -** expressions against UTF8 text.  The following syntax is supported:
           15  +** expressions against UTF8 text.
           16  +**
           17  +** This file is an SQLite extension.  It registers a single function
           18  +** named "regexp(A,B)" where A is the regular expression and B is the
           19  +** string to be matched.  By registering this function, SQLite will also
           20  +** then implement the "B regexp A" operator.  Note that with the function
           21  +** the regular expression comes first, but with the operator it comes
           22  +** second.
           23  +**
           24  +**  The following regular expression syntax is supported:
    16     25   **
    17     26   **     X*      zero or more occurrences of X
    18     27   **     X+      one or more occurrences of X
    19     28   **     X?      zero or one occurrences of X
    20     29   **     X{p,q}  between p and q occurrences of X
    21     30   **     (X)     match X
    22     31   **     X|Y     X or Y
................................................................................
    45     54   ** exhibits exponential behavior.  Note that the X{p,q} operator expands
    46     55   ** to p copies of X following by q-p copies of X? and that the size of the
    47     56   ** regular expression in the O(N*M) performance bound is computed after
    48     57   ** this expansion.
    49     58   */
    50     59   #include <string.h>
    51     60   #include <stdlib.h>
    52         -#include "sqlite3.h"
           61  +#include "sqlite3ext.h"
           62  +SQLITE_EXTENSION_INIT1
           63  +
           64  +/*
           65  +** The following #defines change the names of some functions implemented in
           66  +** this file to prevent name collisions with C-library functions of the
           67  +** same name.
           68  +*/
           69  +#define re_match   sqlite3re_match
           70  +#define re_compile sqlite3re_compile
           71  +#define re_free    sqlite3re_free
    53     72   
    54     73   /* The end-of-input character */
    55     74   #define RE_EOF            0    /* End of input */
    56     75   
    57     76   /* The NFA is implemented as sequence of opcodes taken from the following
    58     77   ** set.  Each opcode has a single integer argument.
    59     78   */
................................................................................
   171    190   static int re_space_char(int c){
   172    191     return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
   173    192   }
   174    193   
   175    194   /* Run a compiled regular expression on the zero-terminated input
   176    195   ** string zIn[].  Return true on a match and false if there is no match.
   177    196   */
   178         -int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
          197  +static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
   179    198     ReStateSet aStateSet[2], *pThis, *pNext;
   180    199     ReStateNumber aSpace[100];
   181    200     ReStateNumber *pToFree;
   182    201     unsigned int i = 0;
   183    202     unsigned int iSwap = 0;
   184    203     int c = RE_EOF+1;
   185    204     int cPrev = 0;
   186    205     int rc = 0;
   187    206     ReInput in;
   188    207   
   189    208     in.z = zIn;
   190    209     in.i = 0;
   191         -  in.mx = nIn>=0 ? nIn : strlen((char const*)zIn);
          210  +  in.mx = nIn>=0 ? nIn : (int)strlen((char const*)zIn);
   192    211   
   193    212     /* Look for the initial prefix match, if there is one. */
   194    213     if( pRe->nInit ){
   195    214       unsigned char x = pRe->zInit[0];
   196    215       while( in.i+pRe->nInit<=in.mx 
   197    216        && (zIn[in.i]!=x ||
   198    217            strncmp((const char*)zIn+in.i, (const char*)pRe->zInit, pRe->nInit)!=0)
................................................................................
   624    643     if( zIn[0]=='^' ){
   625    644       zIn++;
   626    645     }else{
   627    646       re_append(pRe, RE_OP_ANYSTAR, 0);
   628    647     }
   629    648     pRe->sIn.z = (unsigned char*)zIn;
   630    649     pRe->sIn.i = 0;
   631         -  pRe->sIn.mx = strlen(zIn);
          650  +  pRe->sIn.mx = (int)strlen(zIn);
   632    651     zErr = re_subcompile_re(pRe);
   633    652     if( zErr ){
   634    653       re_free(pRe);
   635    654       return zErr;
   636    655     }
   637    656     if( rePeek(pRe)=='$' && pRe->sIn.i+1>=pRe->sIn.mx ){
   638    657       re_append(pRe, RE_OP_MATCH, RE_EOF);
................................................................................
   714    733     zStr = (const unsigned char*)sqlite3_value_text(argv[1]);
   715    734     if( zStr!=0 ){
   716    735       sqlite3_result_int(context, re_match(pRe, zStr, -1));
   717    736     }
   718    737   }
   719    738   
   720    739   /*
   721         -** Invoke this routine in order to install the REGEXP function in an
          740  +** Invoke this routine to register the regexp() function with the
   722    741   ** SQLite database connection.
   723         -**
   724         -** Use:
   725         -**
   726         -**      sqlite3_auto_extension(sqlite3_add_regexp_func);
   727         -**
   728         -** to cause this extension to be automatically loaded into each new
   729         -** database connection.
   730    742   */
   731         -int sqlite3_add_regexp_func(sqlite3 *db){
   732         -  return sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8, 0,
          743  +#ifdef _WIN32
          744  +__declspec(dllexport)
          745  +#endif
          746  +int sqlite3_regexp_init(
          747  +  sqlite3 *db, 
          748  +  char **pzErrMsg, 
          749  +  const sqlite3_api_routines *pApi
          750  +){
          751  +  int rc = SQLITE_OK;
          752  +  SQLITE_EXTENSION_INIT2(pApi);
          753  +  rc = sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8, 0,
   733    754                                    re_sql_func, 0, 0);
          755  +  return rc;
   734    756   }
   735         -
   736         -
   737         -/***************************** Test Code ***********************************/
   738         -#ifdef SQLITE_TEST
   739         -#include <tcl.h>
   740         -extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
   741         -
   742         -/* Implementation of the TCL command:
   743         -**
   744         -**      sqlite3_add_regexp_func $DB
   745         -*/
   746         -static int tclSqlite3AddRegexpFunc(
   747         -  void * clientData,
   748         -  Tcl_Interp *interp,
   749         -  int objc,
   750         -  Tcl_Obj *CONST objv[]
   751         -){
   752         -  sqlite3 *db;
   753         -  if( objc!=2 ){
   754         -    Tcl_WrongNumArgs(interp, 1, objv, "DB");
   755         -    return TCL_ERROR;
   756         -  }
   757         -  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
   758         -  sqlite3_add_regexp_func(db);
   759         -  return TCL_OK;
   760         -}
   761         -
   762         -/* Register the sqlite3_add_regexp_func TCL command with the TCL interpreter.
   763         -*/
   764         -int Sqlitetestregexp_Init(Tcl_Interp *interp){
   765         -  Tcl_CreateObjCommand(interp, "sqlite3_add_regexp_func",
   766         -                       tclSqlite3AddRegexpFunc, 0, 0);
   767         -  return TCL_OK;
   768         -}
   769         -#endif /* SQLITE_TEST */
   770         -/**************************** End Of Test Code *******************************/

Name change from src/test_spellfix.c to ext/misc/spellfix.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   **
    13     13   ** This module implements the spellfix1 VIRTUAL TABLE that can be used
    14     14   ** to search a large vocabulary for close matches.  See separate
    15         -** documentation files (spellfix1.wiki and editdist3.wiki) for details.
           15  +** documentation (http://www.sqlite.org/spellfix1.html) for details.
    16     16   */
    17         -#if SQLITE_CORE
    18         -# include "sqliteInt.h"
    19         -#else
           17  +#include "sqlite3ext.h"
           18  +SQLITE_EXTENSION_INIT1
           19  +
           20  +#ifndef SQLITE_AMALGAMATION
    20     21   # include <string.h>
    21     22   # include <stdio.h>
    22     23   # include <stdlib.h>
    23         -# include "sqlite3ext.h"
    24     24   # include <assert.h>
    25     25   # define ALWAYS(X)  1
    26     26   # define NEVER(X)   0
    27     27     typedef unsigned char u8;
    28     28     typedef unsigned short u16;
    29         -  SQLITE_EXTENSION_INIT1
    30         -#endif /* !SQLITE_CORE */
    31         -#include <ctype.h>
           29  +# include <ctype.h>
           30  +#endif
    32     31   
    33     32   /*
    34     33   ** Character classes for ASCII characters:
    35     34   **
    36     35   **   0   ''        Silent letters:   H W
    37     36   **   1   'A'       Any vowel:   A E I O U (Y)
    38     37   **   2   'B'       A bilabeal stop or fricative:  B F P V W
................................................................................
  2818   2817     for(i=0; i<sizeof(translit)/sizeof(translit[0])-1; i++){
  2819   2818       assert( translit[i].cFrom<translit[i+1].cFrom );
  2820   2819     }
  2821   2820   
  2822   2821     return rc;
  2823   2822   }
  2824   2823   
  2825         -#if SQLITE_CORE || defined(SQLITE_TEST)
  2826         -/*
  2827         -** Register the spellfix1 virtual table and its associated functions.
  2828         -*/
  2829         -int sqlite3_spellfix1_register(sqlite3 *db){
  2830         -  return spellfix1Register(db);
  2831         -}
  2832         -#endif
  2833         -
  2834         -
  2835         -#if !SQLITE_CORE
  2836   2824   /*
  2837   2825   ** Extension load function.
  2838   2826   */
  2839         -int sqlite3_spellfix1_init(
         2827  +#ifdef _WIN32
         2828  +__declspec(dllexport)
         2829  +#endif
         2830  +int sqlite3_spellfix_init(
  2840   2831     sqlite3 *db, 
  2841   2832     char **pzErrMsg, 
  2842   2833     const sqlite3_api_routines *pApi
  2843   2834   ){
  2844   2835     SQLITE_EXTENSION_INIT2(pApi);
  2845   2836     return spellfix1Register(db);
  2846   2837   }
  2847         -#endif /* !SQLITE_CORE */

Name change from src/test_wholenumber.c to ext/misc/wholenumber.c.

    18     18   **     CREATE VIRTUAL TABLE nums USING wholenumber;
    19     19   **     SELECT value FROM nums WHERE value<10;
    20     20   **
    21     21   ** Results in:
    22     22   **
    23     23   **     1 2 3 4 5 6 7 8 9
    24     24   */
    25         -#include "sqlite3.h"
           25  +#include "sqlite3ext.h"
           26  +SQLITE_EXTENSION_INIT1
    26     27   #include <assert.h>
    27     28   #include <string.h>
    28     29   
    29     30   #ifndef SQLITE_OMIT_VIRTUALTABLE
    30     31   
    31     32   
    32     33   /* A wholenumber cursor object */
................................................................................
   213    214       pIdxInfo->aConstraintUsage[gtIdx].omit = 1;
   214    215     }
   215    216     if( pIdxInfo->nOrderBy==1
   216    217      && pIdxInfo->aOrderBy[0].desc==0
   217    218     ){
   218    219       pIdxInfo->orderByConsumed = 1;
   219    220     }
   220         -  pIdxInfo->estimatedCost = (double)1;
          221  +  if( (idxNum & 12)==0 ){
          222  +    pIdxInfo->estimatedCost = (double)100000000;
          223  +  }else if( (idxNum & 3)==0 ){
          224  +    pIdxInfo->estimatedCost = (double)5;
          225  +  }else{
          226  +    pIdxInfo->estimatedCost = (double)1;
          227  +  }
   221    228     return SQLITE_OK;
   222    229   }
   223    230   
   224    231   /*
   225    232   ** A virtual table module that provides read-only access to a
   226    233   ** Tcl global variable namespace.
   227    234   */
................................................................................
   246    253     0,                         /* xRollback */
   247    254     0,                         /* xFindMethod */
   248    255     0,                         /* xRename */
   249    256   };
   250    257   
   251    258   #endif /* SQLITE_OMIT_VIRTUALTABLE */
   252    259   
   253         -
   254         -/*
   255         -** Register the wholenumber virtual table
   256         -*/
   257         -int wholenumber_register(sqlite3 *db){
          260  +#ifdef _WIN32
          261  +__declspec(dllexport)
          262  +#endif
          263  +int sqlite3_wholenumber_init(
          264  +  sqlite3 *db, 
          265  +  char **pzErrMsg, 
          266  +  const sqlite3_api_routines *pApi
          267  +){
   258    268     int rc = SQLITE_OK;
          269  +  SQLITE_EXTENSION_INIT2(pApi);
   259    270   #ifndef SQLITE_OMIT_VIRTUALTABLE
   260    271     rc = sqlite3_create_module(db, "wholenumber", &wholenumberModule, 0);
   261    272   #endif
   262    273     return rc;
   263    274   }
   264         -
   265         -#ifdef SQLITE_TEST
   266         -#include <tcl.h>
   267         -/*
   268         -** Decode a pointer to an sqlite3 object.
   269         -*/
   270         -extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
   271         -
   272         -/*
   273         -** Register the echo virtual table module.
   274         -*/
   275         -static int register_wholenumber_module(
   276         -  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
   277         -  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   278         -  int objc,              /* Number of arguments */
   279         -  Tcl_Obj *CONST objv[]  /* Command arguments */
   280         -){
   281         -  sqlite3 *db;
   282         -  if( objc!=2 ){
   283         -    Tcl_WrongNumArgs(interp, 1, objv, "DB");
   284         -    return TCL_ERROR;
   285         -  }
   286         -  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
   287         -  wholenumber_register(db);
   288         -  return TCL_OK;
   289         -}
   290         -
   291         -
   292         -/*
   293         -** Register commands with the TCL interpreter.
   294         -*/
   295         -int Sqlitetestwholenumber_Init(Tcl_Interp *interp){
   296         -  static struct {
   297         -     char *zName;
   298         -     Tcl_ObjCmdProc *xProc;
   299         -     void *clientData;
   300         -  } aObjCmd[] = {
   301         -     { "register_wholenumber_module",   register_wholenumber_module, 0 },
   302         -  };
   303         -  int i;
   304         -  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
   305         -    Tcl_CreateObjCommand(interp, aObjCmd[i].zName, 
   306         -        aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
   307         -  }
   308         -  return TCL_OK;
   309         -}
   310         -
   311         -#endif /* SQLITE_TEST */

Changes to ext/rtree/rtree.c.

  2661   2661   static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
  2662   2662     int rc;                         /* Return code */
  2663   2663     RtreeNode *pLeaf = 0;           /* Leaf node containing record iDelete */
  2664   2664     int iCell;                      /* Index of iDelete cell in pLeaf */
  2665   2665     RtreeNode *pRoot;               /* Root node of rtree structure */
  2666   2666   
  2667   2667   
  2668         -  /* Obtain a reference to the root node to initialise Rtree.iDepth */
         2668  +  /* Obtain a reference to the root node to initialize Rtree.iDepth */
  2669   2669     rc = nodeAcquire(pRtree, 1, 0, &pRoot);
  2670   2670   
  2671   2671     /* Obtain a reference to the leaf node that contains the entry 
  2672   2672     ** about to be deleted. 
  2673   2673     */
  2674   2674     if( rc==SQLITE_OK ){
  2675   2675       rc = findLeafNode(pRtree, iDelete, &pLeaf);

Changes to ext/rtree/rtree1.test.

    13     13   #
    14     14   
    15     15   if {![info exists testdir]} {
    16     16     set testdir [file join [file dirname [info script]] .. .. test]
    17     17   }
    18     18   source [file join [file dirname [info script]] rtree_util.tcl]
    19     19   source $testdir/tester.tcl
           20  +set testprefix rtree1
    20     21   
    21     22   # Test plan:
    22     23   #
    23     24   #   rtree-1.*: Creating/destroying r-tree tables.
    24     25   #   rtree-2.*: Test the implicit constraints - unique rowid and
    25     26   #              (coord[N]<=coord[N+1]) for even values of N. Also
    26     27   #              automatic assigning of rowid values.

Changes to ext/rtree/rtree5.test.

    57     57   do_test rtree5-1.9 { 
    58     58     execsql { SELECT count(*) FROM t1 WHERE x1==5.0 }
    59     59   } {1}
    60     60   
    61     61   do_test rtree5-1.10 { 
    62     62     execsql { SELECT (1<<31)-5, (1<<31)-1, -1*(1<<31), -1*(1<<31)+5 }
    63     63   } {2147483643 2147483647 -2147483648 -2147483643}
    64         -do_test rtree5-1.10 { 
           64  +do_test rtree5-1.11 { 
    65     65     execsql { 
    66     66       INSERT INTO t1 VALUES(2, (1<<31)-5, (1<<31)-1, -1*(1<<31), -1*(1<<31)+5) 
    67     67     }
    68     68   } {}
    69     69   do_test rtree5-1.12 { 
    70     70     execsql { SELECT * FROM t1 WHERE id=2 }
    71     71   } {2 2147483643 2147483647 -2147483648 -2147483643}

Added magic.txt.

            1  +# This file contains suggested magic(5) text for the unix file(1)
            2  +# utility for recognizing SQLite3 databases.
            3  +#
            4  +# When SQLite is used as an application file format, it is desirable to
            5  +# have file(1) recognize the database file as being with the specific
            6  +# application.  You can set the application_id for a database file
            7  +# using:
            8  +#
            9  +#     PRAGMA application_id = INTEGER;
           10  +#
           11  +# INTEGER can be any signed 32-bit integer.  That integer is written as
           12  +# a 4-byte big-endian integer into offset 68 of the database header. 
           13  +#
           14  +# The Monotone application used "PRAGMA user_version=1598903374;" to set
           15  +# its identifier long before "PRAGMA application_id" became available.
           16  +# The user_version is very similar to application_id except that it is
           17  +# stored at offset 68 instead of offset 60.  The application_id pragma
           18  +# is preferred.  The rule using offset 60 for Monotone is for historical
           19  +# compatibility only.
           20  +#
           21  +0    string  =SQLite\ format\ 3
           22  +>68  belong  =0x0f055111  Fossil repository -
           23  +>68  belong  =0x0f055112  Fossil checkout - 
           24  +>68  belong  =0x0f055113  Fossil global configuration - 
           25  +>68  belong  =0x42654462  Bentley Systems BeSQLite Database -
           26  +>68  belong  =0x42654c6e  Bentley Systems Localization File -
           27  +>60  belong  =0x5f4d544e  Monotone source repository -
           28  +>0   string  =SQLite      SQLite3 database

Changes to main.mk.

    51     51   # Object files for the SQLite library.
    52     52   #
    53     53   LIBOBJ+= alter.o analyze.o attach.o auth.o \
    54     54            backup.o bitvec.o btmutex.o btree.o build.o \
    55     55            callback.o complete.o ctime.o date.o delete.o expr.o fault.o fkey.o \
    56     56            fts3.o fts3_aux.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \
    57     57            fts3_snippet.o fts3_tokenizer.o fts3_tokenizer1.o \
           58  +         fts3_tokenize_vtab.o \
    58     59   	 fts3_unicode.o fts3_unicode2.o \
    59     60            fts3_write.o func.o global.o hash.o \
    60     61            icu.o insert.o journal.o legacy.o loadext.o \
    61     62            main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
    62     63            memjournal.o \
    63     64            mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \
    64     65            notify.o opcodes.o os.o os_unix.o os_win.o \
................................................................................
   193    194     $(TOP)/ext/fts3/fts3_hash.h \
   194    195     $(TOP)/ext/fts3/fts3_icu.c \
   195    196     $(TOP)/ext/fts3/fts3_porter.c \
   196    197     $(TOP)/ext/fts3/fts3_snippet.c \
   197    198     $(TOP)/ext/fts3/fts3_tokenizer.h \
   198    199     $(TOP)/ext/fts3/fts3_tokenizer.c \
   199    200     $(TOP)/ext/fts3/fts3_tokenizer1.c \
          201  +  $(TOP)/ext/fts3/fts3_tokenize_vtab.c \
   200    202     $(TOP)/ext/fts3/fts3_unicode.c \
   201    203     $(TOP)/ext/fts3/fts3_unicode2.c \
   202    204     $(TOP)/ext/fts3/fts3_write.c
   203    205   SRC += \
   204    206     $(TOP)/ext/icu/sqliteicu.h \
   205    207     $(TOP)/ext/icu/icu.c
   206    208   SRC += \
................................................................................
   238    240     $(TOP)/src/test_backup.c \
   239    241     $(TOP)/src/test_btree.c \
   240    242     $(TOP)/src/test_config.c \
   241    243     $(TOP)/src/test_demovfs.c \
   242    244     $(TOP)/src/test_devsym.c \
   243    245     $(TOP)/src/test_fs.c \
   244    246     $(TOP)/src/test_func.c \
   245         -  $(TOP)/src/test_fuzzer.c \
   246    247     $(TOP)/src/test_hexio.c \
   247    248     $(TOP)/src/test_init.c \
   248    249     $(TOP)/src/test_intarray.c \
   249    250     $(TOP)/src/test_journal.c \
   250    251     $(TOP)/src/test_malloc.c \
   251    252     $(TOP)/src/test_multiplex.c \
   252    253     $(TOP)/src/test_mutex.c \
   253    254     $(TOP)/src/test_onefile.c \
   254    255     $(TOP)/src/test_osinst.c \
   255    256     $(TOP)/src/test_pcache.c \
   256    257     $(TOP)/src/test_quota.c \
   257         -  $(TOP)/src/test_regexp.c \
   258    258     $(TOP)/src/test_rtree.c \
   259    259     $(TOP)/src/test_schema.c \
   260    260     $(TOP)/src/test_server.c \
   261    261     $(TOP)/src/test_stat.c \
   262    262     $(TOP)/src/test_sqllog.c \
   263    263     $(TOP)/src/test_superlock.c \
   264    264     $(TOP)/src/test_syscall.c \
   265    265     $(TOP)/src/test_tclvar.c \
   266    266     $(TOP)/src/test_thread.c \
   267    267     $(TOP)/src/test_vfs.c \
   268         -  $(TOP)/src/test_wholenumber.c \
   269    268     $(TOP)/src/test_wsd.c
          269  +
          270  +# Extensions to be statically loaded.
          271  +#
          272  +TESTSRC += \
          273  +  $(TOP)/ext/misc/amatch.c \
          274  +  $(TOP)/ext/misc/closure.c \
          275  +  $(TOP)/ext/misc/fuzzer.c \
          276  +  $(TOP)/ext/misc/ieee754.c \
          277  +  $(TOP)/ext/misc/nextchar.c \
          278  +  $(TOP)/ext/misc/regexp.c \
          279  +  $(TOP)/ext/misc/spellfix.c \
          280  +  $(TOP)/ext/misc/wholenumber.c
          281  +
   270    282   
   271    283   #TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c
   272    284   #TESTSRC += $(TOP)/ext/fts3/fts3_tokenizer.c
   273    285   
   274    286   TESTSRC2 = \
   275    287     $(TOP)/src/attach.c \
   276    288     $(TOP)/src/backup.c \
................................................................................
   361    373   	$(RANLIB) libsqlite3.a
   362    374   
   363    375   sqlite3$(EXE):	$(TOP)/src/shell.c libsqlite3.a sqlite3.h
   364    376   	$(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE)                  \
   365    377   		$(TOP)/src/shell.c                                  \
   366    378   		libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB)
   367    379   
          380  +mptester$(EXE):	sqlite3.c $(TOP)/mptest/mptest.c
          381  +	$(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
          382  +		$(TLIBS) $(THREADLIB)
          383  +
   368    384   sqlite3.o:	sqlite3.c
   369    385   	$(TCCX) -c sqlite3.c
   370    386   
   371    387   # This target creates a directory named "tsrc" and fills it with
   372    388   # copies of all of the C source code and header files needed to
   373    389   # build on the target system.  Some of the C source code and header
   374    390   # files are automatically generated.  This target takes care of
................................................................................
   381    397   	rm tsrc/sqlite.h.in tsrc/parse.y
   382    398   	tclsh $(TOP)/tool/vdbe-compress.tcl <tsrc/vdbe.c >vdbe.new
   383    399   	mv vdbe.new tsrc/vdbe.c
   384    400   	touch target_source
   385    401   
   386    402   sqlite3.c:	target_source $(TOP)/tool/mksqlite3c.tcl
   387    403   	tclsh $(TOP)/tool/mksqlite3c.tcl
          404  +	cp tsrc/shell.c tsrc/sqlite3ext.h .
   388    405   	echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c
   389    406   	cat sqlite3.c >>tclsqlite3.c
   390    407   	echo '#endif /* USE_SYSTEM_SQLITE */' >>tclsqlite3.c
   391    408   	cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c
   392    409   
   393    410   sqlite3.c-debug:	target_source $(TOP)/tool/mksqlite3c.tcl
   394    411   	tclsh $(TOP)/tool/mksqlite3c.tcl --linemacros
................................................................................
   506    523   	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_porter.c
   507    524   
   508    525   fts3_tokenizer.o:	$(TOP)/ext/fts3/fts3_tokenizer.c $(HDR) $(EXTHDR)
   509    526   	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer.c
   510    527   
   511    528   fts3_tokenizer1.o:	$(TOP)/ext/fts3/fts3_tokenizer1.c $(HDR) $(EXTHDR)
   512    529   	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer1.c
          530  +
          531  +fts3_tokenize_vtab.o:	$(TOP)/ext/fts3/fts3_tokenize_vtab.c $(HDR) $(EXTHDR)
          532  +	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenize_vtab.c
   513    533   
   514    534   fts3_unicode.o:	$(TOP)/ext/fts3/fts3_unicode.c $(HDR) $(EXTHDR)
   515    535   	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode.c
   516    536   
   517    537   fts3_unicode2.o:	$(TOP)/ext/fts3/fts3_unicode2.c $(HDR) $(EXTHDR)
   518    538   	$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode2.c
   519    539   
................................................................................
   617    637   	rm -rf tsrc target_source
   618    638   	rm -f testloadext.dll libtestloadext.so
   619    639   	rm -f amalgamation-testfixture amalgamation-testfixture.exe
   620    640   	rm -f fts3-testfixture fts3-testfixture.exe
   621    641   	rm -f testfixture testfixture.exe
   622    642   	rm -f threadtest3 threadtest3.exe
   623    643   	rm -f sqlite3.c fts?amal.c tclsqlite3.c
          644  +	rm -f sqlite3rc.h
          645  +	rm -f shell.c sqlite3ext.h
   624    646   	rm -f sqlite3_analyzer sqlite3_analyzer.exe sqlite3_analyzer.c
   625    647   	rm -f sqlite-*-output.vsix
          648  +	rm -f mptester mptester.exe

Added mptest/config01.test.

            1  +/*
            2  +** Configure five tasks in different ways, then run tests.
            3  +*/
            4  +--if vfsname() GLOB 'unix'
            5  +PRAGMA page_size=8192;
            6  +--task 1
            7  +  PRAGMA journal_mode=PERSIST;
            8  +  PRAGMA mmap_size=0;
            9  +--end
           10  +--task 2
           11  +  PRAGMA journal_mode=TRUNCATE;
           12  +  PRAGMA mmap_size=28672;
           13  +--end
           14  +--task 3
           15  +  PRAGMA journal_mode=MEMORY;
           16  +--end
           17  +--task 4
           18  +  PRAGMA journal_mode=OFF;
           19  +--end
           20  +--task 4
           21  +  PRAGMA mmap_size(268435456);
           22  +--end
           23  +--source multiwrite01.test
           24  +--wait all
           25  +PRAGMA page_size=16384;
           26  +VACUUM;
           27  +CREATE TABLE pgsz(taskid, sz INTEGER);
           28  +--task 1
           29  +  INSERT INTO pgsz VALUES(1, eval('PRAGMA page_size'));
           30  +--end
           31  +--task 2
           32  +  INSERT INTO pgsz VALUES(2, eval('PRAGMA page_size'));
           33  +--end
           34  +--task 3
           35  +  INSERT INTO pgsz VALUES(3, eval('PRAGMA page_size'));
           36  +--end
           37  +--task 4
           38  +  INSERT INTO pgsz VALUES(4, eval('PRAGMA page_size'));
           39  +--end
           40  +--task 5
           41  +  INSERT INTO pgsz VALUES(5, eval('PRAGMA page_size'));
           42  +--end
           43  +--source multiwrite01.test
           44  +--wait all
           45  +SELECT sz FROM pgsz;
           46  +--match 16384 16384 16384 16384 16384

Added mptest/config02.test.

            1  +/*
            2  +** Configure five tasks in different ways, then run tests.
            3  +*/
            4  +PRAGMA page_size=512;
            5  +--task 1
            6  +  PRAGMA mmap_size=0;
            7  +--end
            8  +--task 2
            9  +  PRAGMA mmap_size=28672;
           10  +--end
           11  +--task 3
           12  +  PRAGMA mmap_size=8192;
           13  +--end
           14  +--task 4
           15  +  PRAGMA mmap_size=65536;
           16  +--end
           17  +--task 5
           18  +  PRAGMA mmap_size=268435456;
           19  +--end
           20  +--source multiwrite01.test
           21  +--source crash02.subtest
           22  +PRAGMA page_size=1024;
           23  +VACUUM;
           24  +CREATE TABLE pgsz(taskid, sz INTEGER);
           25  +--task 1
           26  +  INSERT INTO pgsz VALUES(1, eval('PRAGMA page_size'));
           27  +--end
           28  +--task 2
           29  +  INSERT INTO pgsz VALUES(2, eval('PRAGMA page_size'));
           30  +--end
           31  +--task 3
           32  +  INSERT INTO pgsz VALUES(3, eval('PRAGMA page_size'));
           33  +--end
           34  +--task 4
           35  +  INSERT INTO pgsz VALUES(4, eval('PRAGMA page_size'));
           36  +--end
           37  +--task 5
           38  +  INSERT INTO pgsz VALUES(5, eval('PRAGMA page_size'));
           39  +--end
           40  +--source multiwrite01.test
           41  +--source crash02.subtest
           42  +--wait all
           43  +SELECT sz FROM pgsz;
           44  +--match 1024 1024 1024 1024 1024
           45  +PRAGMA page_size=2048;
           46  +VACUUM;
           47  +DELETE FROM pgsz;
           48  +--task 1
           49  +  INSERT INTO pgsz VALUES(1, eval('PRAGMA page_size'));
           50  +--end
           51  +--task 2
           52  +  INSERT INTO pgsz VALUES(2, eval('PRAGMA page_size'));
           53  +--end
           54  +--task 3
           55  +  INSERT INTO pgsz VALUES(3, eval('PRAGMA page_size'));
           56  +--end
           57  +--task 4
           58  +  INSERT INTO pgsz VALUES(4, eval('PRAGMA page_size'));
           59  +--end
           60  +--task 5
           61  +  INSERT INTO pgsz VALUES(5, eval('PRAGMA page_size'));
           62  +--end
           63  +--source multiwrite01.test
           64  +--source crash02.subtest
           65  +--wait all
           66  +SELECT sz FROM pgsz;
           67  +--match 2048 2048 2048 2048 2048
           68  +PRAGMA page_size=8192;
           69  +VACUUM;
           70  +DELETE FROM pgsz;
           71  +--task 1
           72  +  INSERT INTO pgsz VALUES(1, eval('PRAGMA page_size'));
           73  +--end
           74  +--task 2
           75  +  INSERT INTO pgsz VALUES(2, eval('PRAGMA page_size'));
           76  +--end
           77  +--task 3
           78  +  INSERT INTO pgsz VALUES(3, eval('PRAGMA page_size'));
           79  +--end
           80  +--task 4
           81  +  INSERT INTO pgsz VALUES(4, eval('PRAGMA page_size'));
           82  +--end
           83  +--task 5
           84  +  INSERT INTO pgsz VALUES(5, eval('PRAGMA page_size'));
           85  +--end
           86  +--source multiwrite01.test
           87  +--source crash02.subtest
           88  +--wait all
           89  +SELECT sz FROM pgsz;
           90  +--match 8192 8192 8192 8192 8192
           91  +PRAGMA page_size=16384;
           92  +VACUUM;
           93  +DELETE FROM pgsz;
           94  +--task 1
           95  +  INSERT INTO pgsz VALUES(1, eval('PRAGMA page_size'));
           96  +--end
           97  +--task 2
           98  +  INSERT INTO pgsz VALUES(2, eval('PRAGMA page_size'));
           99  +--end
          100  +--task 3
          101  +  INSERT INTO pgsz VALUES(3, eval('PRAGMA page_size'));
          102  +--end
          103  +--task 4
          104  +  INSERT INTO pgsz VALUES(4, eval('PRAGMA page_size'));
          105  +--end
          106  +--task 5
          107  +  INSERT INTO pgsz VALUES(5, eval('PRAGMA page_size'));
          108  +--end
          109  +--source multiwrite01.test
          110  +--source crash02.subtest
          111  +--wait all
          112  +SELECT sz FROM pgsz;
          113  +--match 16384 16384 16384 16384 16384
          114  +PRAGMA auto_vacuum=FULL;
          115  +VACUUM;
          116  +--source multiwrite01.test
          117  +--source crash02.subtest
          118  +--wait all
          119  +PRAGMA auto_vacuum=FULL;
          120  +PRAGMA page_size=512;
          121  +VACUUM;
          122  +--source multiwrite01.test
          123  +--source crash02.subtest

Added mptest/crash01.test.

            1  +/* Test cases involving incomplete transactions that must be rolled back.
            2  +*/
            3  +--task 1
            4  +  DROP TABLE IF EXISTS t1;
            5  +  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
            6  +  --sleep 1
            7  +  INSERT INTO t1 VALUES(1, randomblob(2000));
            8  +  INSERT INTO t1 VALUES(2, randomblob(1000));
            9  +  --sleep 1
           10  +  INSERT INTO t1 SELECT a+2, randomblob(1500) FROM t1;
           11  +  INSERT INTO t1 SELECT a+4, randomblob(1500) FROM t1;
           12  +  INSERT INTO t1 SELECT a+8, randomblob(1500) FROM t1;
           13  +  --sleep 1
           14  +  INSERT INTO t1 SELECT a+16, randomblob(1500) FROM t1;
           15  +  --sleep 1
           16  +  INSERT INTO t1 SELECT a+32, randomblob(1500) FROM t1;
           17  +  SELECT count(*) FROM t1;
           18  +  --match 64
           19  +  SELECT avg(length(b)) FROM t1;
           20  +  --match 1500.0
           21  +  --sleep 2
           22  +  UPDATE t1 SET b='x'||a||'y';
           23  +  SELECT total(length(b)) FROM t1;
           24  +  --match 247
           25  +  SELECT a FROM t1 WHERE b='x17y';
           26  +  --match 17
           27  +  CREATE INDEX t1b ON t1(b);
           28  +  SELECT a FROM t1 WHERE b='x17y';
           29  +  --match 17
           30  +  SELECT a FROM t1 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
           31  +  --match 29 28 27 26 25
           32  +--end
           33  +--wait 1
           34  +--task 2
           35  +  CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
           36  +  INSERT INTO t2 SELECT a, b FROM t1;
           37  +  UPDATE t1 SET b='x'||a||'y';
           38  +  SELECT total(length(b)) FROM t2;
           39  +  --match 247
           40  +  SELECT a FROM t2 WHERE b='x17y';
           41  +  --match 17
           42  +  CREATE INDEX t2b ON t2(b);
           43  +  SELECT a FROM t2 WHERE b='x17y';
           44  +  --match 17
           45  +  SELECT a FROM t2 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
           46  +  --match 29 28 27 26 25
           47  +--end
           48  +--task 3
           49  +  CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
           50  +  INSERT INTO t3 SELECT a, b FROM t1;
           51  +  UPDATE t1 SET b='x'||a||'y';
           52  +  SELECT total(length(b)) FROM t3;
           53  +  --match 247
           54  +  SELECT a FROM t3 WHERE b='x17y';
           55  +  --match 17
           56  +  CREATE INDEX t3b ON t3(b);
           57  +  SELECT a FROM t3 WHERE b='x17y';
           58  +  --match 17
           59  +  SELECT a FROM t3 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
           60  +  --match 29 28 27 26 25
           61  +--end
           62  +--task 4
           63  +  CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
           64  +  INSERT INTO t4 SELECT a, b FROM t1;
           65  +  UPDATE t1 SET b='x'||a||'y';
           66  +  SELECT total(length(b)) FROM t4;
           67  +  --match 247
           68  +  SELECT a FROM t4 WHERE b='x17y';
           69  +  --match 17
           70  +  CREATE INDEX t4b ON t4(b);
           71  +  SELECT a FROM t4 WHERE b='x17y';
           72  +  --match 17
           73  +  SELECT a FROM t4 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
           74  +  --match 29 28 27 26 25
           75  +--end
           76  +--task 5
           77  +  CREATE TABLE t5(a INTEGER PRIMARY KEY, b);
           78  +  INSERT INTO t5 SELECT a, b FROM t1;
           79  +  UPDATE t1 SET b='x'||a||'y';
           80  +  SELECT total(length(b)) FROM t5;
           81  +  --match 247
           82  +  SELECT a FROM t5 WHERE b='x17y';
           83  +  --match 17
           84  +  CREATE INDEX t5b ON t5(b);
           85  +  SELECT a FROM t5 WHERE b='x17y';
           86  +  --match 17
           87  +  SELECT a FROM t5 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
           88  +  --match 29 28 27 26 25
           89  +--end
           90  +
           91  +--wait all
           92  +/* After the database file has been set up, run the crash2 subscript
           93  +** multiple times. */
           94  +--source crash02.subtest
           95  +--source crash02.subtest
           96  +--source crash02.subtest
           97  +--source crash02.subtest
           98  +--source crash02.subtest
           99  +--source crash02.subtest
          100  +--source crash02.subtest
          101  +--source crash02.subtest
          102  +--source crash02.subtest

Added mptest/crash02.subtest.

            1  +/*
            2  +** This script is called from crash01.test and config02.test and perhaps other
            3  +** script.  After the database file has been set up, make a big rollback 
            4  +** journal in client 1, then crash client 1.
            5  +** Then in the other clients, do an integrity check.
            6  +*/
            7  +--task 1 leave-hot-journal
            8  +  --sleep 5
            9  +  --finish
           10  +  PRAGMA cache_size=10;
           11  +  BEGIN;
           12  +  UPDATE t1 SET b=randomblob(20000);
           13  +  UPDATE t2 SET b=randomblob(20000);
           14  +  UPDATE t3 SET b=randomblob(20000);
           15  +  UPDATE t4 SET b=randomblob(20000);
           16  +  UPDATE t5 SET b=randomblob(20000);
           17  +  UPDATE t1 SET b=NULL;
           18  +  UPDATE t2 SET b=NULL;
           19  +  UPDATE t3 SET b=NULL;
           20  +  UPDATE t4 SET b=NULL;
           21  +  UPDATE t5 SET b=NULL;
           22  +  --print Task one crashing an incomplete transaction
           23  +  --exit 1
           24  +--end
           25  +--task 2 integrity_check-2
           26  +  SELECT count(*) FROM t1;
           27  +  --match 64
           28  +  --sleep 100
           29  +  PRAGMA integrity_check(10);
           30  +  --match ok
           31  +--end
           32  +--task 3 integrity_check-3
           33  +  SELECT count(*) FROM t1;
           34  +  --match 64
           35  +  --sleep 100
           36  +  PRAGMA integrity_check(10);
           37  +  --match ok
           38  +--end
           39  +--task 4 integrity_check-4
           40  +  SELECT count(*) FROM t1;
           41  +  --match 64
           42  +  --sleep 100
           43  +  PRAGMA integrity_check(10);
           44  +  --match ok
           45  +--end
           46  +--task 5 integrity_check-5
           47  +  SELECT count(*) FROM t1;
           48  +  --match 64
           49  +  --sleep 100
           50  +  PRAGMA integrity_check(10);
           51  +  --match ok
           52  +--end
           53  +--wait all

Added mptest/mptest.c.

            1  +/*
            2  +** 2013-04-05
            3  +**
            4  +** The author disclaims copyright to this source code.  In place of
            5  +** a legal notice, here is a blessing:
            6  +**
            7  +**    May you do good and not evil.
            8  +**    May you find forgiveness for yourself and forgive others.
            9  +**    May you share freely, never taking more than you give.
           10  +**
           11  +*************************************************************************
           12  +** 
           13  +** This is a program used for testing SQLite, and specifically for testing
           14  +** the ability of independent processes to access the same SQLite database
           15  +** concurrently.
           16  +**
           17  +** Compile this program as follows:
           18  +**
           19  +**    gcc -g -c -Wall sqlite3.c $(OPTS)
           20  +**    gcc -g -o mptest mptest.c sqlite3.o $(LIBS)
           21  +**
           22  +** Recommended options:
           23  +**
           24  +**    -DHAVE_USLEEP
           25  +**    -DSQLITE_NO_SYNC
           26  +**    -DSQLITE_THREADSAFE=0
           27  +**    -DSQLITE_OMIT_LOAD_EXTENSION
           28  +**
           29  +** Run like this:
           30  +**
           31  +**     ./mptest $database $script
           32  +**
           33  +** where $database is the database to use for testing and $script is a
           34  +** test script.
           35  +*/
           36  +#include "sqlite3.h"
           37  +#include <stdio.h>
           38  +#if defined(_WIN32)
           39  +# define WIN32_LEAN_AND_MEAN
           40  +# include <windows.h>
           41  +#else
           42  +# include <unistd.h>
           43  +#endif
           44  +#include <stdlib.h>
           45  +#include <string.h>
           46  +#include <assert.h>
           47  +#include <ctype.h>
           48  +
           49  +/* The suffix to append to the child command lines, if any */
           50  +#if defined(_WIN32)
           51  +# define GETPID (int)GetCurrentProcessId
           52  +#else
           53  +# define GETPID getpid
           54  +#endif
           55  +
           56  +/* Mark a parameter as unused to suppress compiler warnings */
           57  +#define UNUSED_PARAMETER(x)  (void)x
           58  +
           59  +/* Global data
           60  +*/
           61  +static struct Global {
           62  +  char *argv0;           /* Name of the executable */
           63  +  const char *zVfs;      /* Name of VFS to use. Often NULL meaning "default" */
           64  +  char *zDbFile;         /* Name of the database */
           65  +  sqlite3 *db;           /* Open connection to database */
           66  +  char *zErrLog;         /* Filename for error log */
           67  +  FILE *pErrLog;         /* Where to write errors */
           68  +  char *zLog;            /* Name of output log file */
           69  +  FILE *pLog;            /* Where to write log messages */
           70  +  char zName[32];        /* Symbolic name of this process */
           71  +  int taskId;            /* Task ID.  0 means supervisor. */
           72  +  int iTrace;            /* Tracing level */
           73  +  int bSqlTrace;         /* True to trace SQL commands */
           74  +  int bIgnoreSqlErrors;  /* Ignore errors in SQL statements */
           75  +  int nError;            /* Number of errors */
           76  +  int nTest;             /* Number of --match operators */
           77  +  int iTimeout;          /* Milliseconds until a busy timeout */
           78  +  int bSync;             /* Call fsync() */
           79  +} g;
           80  +
           81  +/* Default timeout */
           82  +#define DEFAULT_TIMEOUT 10000
           83  +
           84  +/*
           85  +** Print a message adding zPrefix[] to the beginning of every line.
           86  +*/
           87  +static void printWithPrefix(FILE *pOut, const char *zPrefix, const char *zMsg){
           88  +  while( zMsg && zMsg[0] ){
           89  +    int i;
           90  +    for(i=0; zMsg[i] && zMsg[i]!='\n' && zMsg[i]!='\r'; i++){}
           91  +    fprintf(pOut, "%s%.*s\n", zPrefix, i, zMsg);
           92  +    zMsg += i;
           93  +    while( zMsg[0]=='\n' || zMsg[0]=='\r' ) zMsg++;
           94  +  }
           95  +}
           96  +
           97  +/*
           98  +** Compare two pointers to strings, where the pointers might be NULL.
           99  +*/
          100  +static int safe_strcmp(const char *a, const char *b){
          101  +  if( a==b ) return 0;
          102  +  if( a==0 ) return -1;
          103  +  if( b==0 ) return 1;
          104  +  return strcmp(a,b);
          105  +}
          106  +
          107  +/*
          108  +** Return TRUE if string z[] matches glob pattern zGlob[].
          109  +** Return FALSE if the pattern does not match.
          110  +**
          111  +** Globbing rules:
          112  +**
          113  +**      '*'       Matches any sequence of zero or more characters.
          114  +**
          115  +**      '?'       Matches exactly one character.
          116  +**
          117  +**     [...]      Matches one character from the enclosed list of
          118  +**                characters.
          119  +**
          120  +**     [^...]     Matches one character not in the enclosed list.
          121  +**
          122  +**      '#'       Matches any sequence of one or more digits with an
          123  +**                optional + or - sign in front
          124  +*/
          125  +int strglob(const char *zGlob, const char *z){
          126  +  int c, c2;
          127  +  int invert;
          128  +  int seen;
          129  +
          130  +  while( (c = (*(zGlob++)))!=0 ){
          131  +    if( c=='*' ){
          132  +      while( (c=(*(zGlob++))) == '*' || c=='?' ){
          133  +        if( c=='?' && (*(z++))==0 ) return 0;
          134  +      }
          135  +      if( c==0 ){
          136  +        return 1;
          137  +      }else if( c=='[' ){
          138  +        while( *z && strglob(zGlob-1,z) ){
          139  +          z++;
          140  +        }
          141  +        return (*z)!=0;
          142  +      }
          143  +      while( (c2 = (*(z++)))!=0 ){
          144  +        while( c2!=c ){
          145  +          c2 = *(z++);
          146  +          if( c2==0 ) return 0;
          147  +        }
          148  +        if( strglob(zGlob,z) ) return 1;
          149  +      }
          150  +      return 0;
          151  +    }else if( c=='?' ){
          152  +      if( (*(z++))==0 ) return 0;
          153  +    }else if( c=='[' ){
          154  +      int prior_c = 0;
          155  +      seen = 0;
          156  +      invert = 0;
          157  +      c = *(z++);
          158  +      if( c==0 ) return 0;
          159  +      c2 = *(zGlob++);
          160  +      if( c2=='^' ){
          161  +        invert = 1;
          162  +        c2 = *(zGlob++);
          163  +      }
          164  +      if( c2==']' ){
          165  +        if( c==']' ) seen = 1;
          166  +        c2 = *(zGlob++);
          167  +      }
          168  +      while( c2 && c2!=']' ){
          169  +        if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
          170  +          c2 = *(zGlob++);
          171  +          if( c>=prior_c && c<=c2 ) seen = 1;
          172  +          prior_c = 0;
          173  +        }else{
          174  +          if( c==c2 ){
          175  +            seen = 1;
          176  +          }
          177  +          prior_c = c2;
          178  +        }
          179  +        c2 = *(zGlob++);
          180  +      }
          181  +      if( c2==0 || (seen ^ invert)==0 ) return 0;
          182  +    }else if( c=='#' ){
          183  +      if( (z[0]=='-' || z[0]=='+') && isdigit(z[1]) ) z++;
          184  +      if( !isdigit(z[0]) ) return 0;
          185  +      z++;
          186  +      while( isdigit(z[0]) ){ z++; }
          187  +    }else{
          188  +      if( c!=(*(z++)) ) return 0;
          189  +    }
          190  +  }
          191  +  return *z==0;
          192  +}
          193  +
          194  +/*
          195  +** Close output stream pOut if it is not stdout or stderr
          196  +*/
          197  +static void maybeClose(FILE *pOut){
          198  +  if( pOut!=stdout && pOut!=stderr ) fclose(pOut);
          199  +}
          200  +
          201  +/*
          202  +** Print an error message
          203  +*/
          204  +static void errorMessage(const char *zFormat, ...){
          205  +  va_list ap;
          206  +  char *zMsg;
          207  +  char zPrefix[30];
          208  +  va_start(ap, zFormat);
          209  +  zMsg = sqlite3_vmprintf(zFormat, ap);
          210  +  va_end(ap);
          211  +  sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s:ERROR: ", g.zName);
          212  +  if( g.pLog ){
          213  +    printWithPrefix(g.pLog, zPrefix, zMsg);
          214  +    fflush(g.pLog);
          215  +  }
          216  +  if( g.pErrLog && safe_strcmp(g.zErrLog,g.zLog) ){
          217  +    printWithPrefix(g.pErrLog, zPrefix, zMsg);
          218  +    fflush(g.pErrLog);
          219  +  }
          220  +  sqlite3_free(zMsg);
          221  +  g.nError++;
          222  +}
          223  +
          224  +/* Forward declaration */
          225  +static int trySql(const char*, ...);
          226  +
          227  +/*
          228  +** Print an error message and then quit.
          229  +*/
          230  +static void fatalError(const char *zFormat, ...){
          231  +  va_list ap;
          232  +  char *zMsg;
          233  +  char zPrefix[30];
          234  +  va_start(ap, zFormat);
          235  +  zMsg = sqlite3_vmprintf(zFormat, ap);
          236  +  va_end(ap);
          237  +  sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s:FATAL: ", g.zName);
          238  +  if( g.pLog ){
          239  +    printWithPrefix(g.pLog, zPrefix, zMsg);
          240  +    fflush(g.pLog);
          241  +    maybeClose(g.pLog);
          242  +  }
          243  +  if( g.pErrLog && safe_strcmp(g.zErrLog,g.zLog) ){
          244  +    printWithPrefix(g.pErrLog, zPrefix, zMsg);
          245  +    fflush(g.pErrLog);
          246  +    maybeClose(g.pErrLog);
          247  +  }
          248  +  sqlite3_free(zMsg);
          249  +  if( g.db ){
          250  +    int nTry = 0;
          251  +    g.iTimeout = 0;
          252  +    while( trySql("UPDATE client SET wantHalt=1;")==SQLITE_BUSY
          253  +           && (nTry++)<100 ){
          254  +      sqlite3_sleep(10);
          255  +    }
          256  +  }
          257  +  sqlite3_close(g.db);
          258  +  exit(1);  
          259  +}
          260  +
          261  +
          262  +/*
          263  +** Print a log message
          264  +*/
          265  +static void logMessage(const char *zFormat, ...){
          266  +  va_list ap;
          267  +  char *zMsg;
          268  +  char zPrefix[30];
          269  +  va_start(ap, zFormat);
          270  +  zMsg = sqlite3_vmprintf(zFormat, ap);
          271  +  va_end(ap);
          272  +  sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s: ", g.zName);
          273  +  if( g.pLog ){
          274  +    printWithPrefix(g.pLog, zPrefix, zMsg);
          275  +    fflush(g.pLog);
          276  +  }
          277  +  sqlite3_free(zMsg);
          278  +}
          279  +
          280  +/*
          281  +** Return the length of a string omitting trailing whitespace
          282  +*/
          283  +static int clipLength(const char *z){
          284  +  int n = (int)strlen(z);
          285  +  while( n>0 && isspace(z[n-1]) ){ n--; }
          286  +  return n;
          287  +}
          288  +
          289  +/*
          290  +** Auxiliary SQL function to return the name of the VFS
          291  +*/
          292  +static void vfsNameFunc(
          293  +  sqlite3_context *context,
          294  +  int argc,
          295  +  sqlite3_value **argv
          296  +){
          297  +  sqlite3 *db = sqlite3_context_db_handle(context);
          298  +  char *zVfs = 0;
          299  +  UNUSED_PARAMETER(argc);
          300  +  UNUSED_PARAMETER(argv);
          301  +  sqlite3_file_control(db, "main", SQLITE_FCNTL_VFSNAME, &zVfs);
          302  +  if( zVfs ){
          303  +    sqlite3_result_text(context, zVfs, -1, sqlite3_free);
          304  +  }
          305  +}
          306  +
          307  +/*
          308  +** Busy handler with a g.iTimeout-millisecond timeout
          309  +*/
          310  +static int busyHandler(void *pCD, int count){
          311  +  UNUSED_PARAMETER(pCD);
          312  +  if( count*10>g.iTimeout ){
          313  +    if( g.iTimeout>0 ) errorMessage("timeout after %dms", g.iTimeout);
          314  +    return 0;
          315  +  }
          316  +  sqlite3_sleep(10);
          317  +  return 1;
          318  +}
          319  +
          320  +/*
          321  +** SQL Trace callback
          322  +*/
          323  +static void sqlTraceCallback(void *NotUsed1, const char *zSql){
          324  +  UNUSED_PARAMETER(NotUsed1);
          325  +  logMessage("[%.*s]", clipLength(zSql), zSql);
          326  +}
          327  +
          328  +/*
          329  +** SQL error log callback
          330  +*/
          331  +static void sqlErrorCallback(void *pArg, int iErrCode, const char *zMsg){
          332  +  UNUSED_PARAMETER(pArg);
          333  +  if( iErrCode==SQLITE_ERROR && g.bIgnoreSqlErrors ) return;
          334  +  if( (iErrCode&0xff)==SQLITE_SCHEMA && g.iTrace<3 ) return;
          335  +  if( g.iTimeout==0 && (iErrCode&0xff)==SQLITE_BUSY && g.iTrace<3 ) return;
          336  +  if( (iErrCode&0xff)==SQLITE_NOTICE ){
          337  +    logMessage("(info) %s", zMsg);
          338  +  }else{
          339  +    errorMessage("(errcode=%d) %s", iErrCode, zMsg);
          340  +  }
          341  +}
          342  +
          343  +/*
          344  +** Prepare an SQL statement.  Issue a fatal error if unable.
          345  +*/
          346  +static sqlite3_stmt *prepareSql(const char *zFormat, ...){
          347  +  va_list ap;
          348  +  char *zSql;
          349  +  int rc;
          350  +  sqlite3_stmt *pStmt = 0;
          351  +  va_start(ap, zFormat);
          352  +  zSql = sqlite3_vmprintf(zFormat, ap);
          353  +  va_end(ap);
          354  +  rc = sqlite3_prepare_v2(g.db, zSql, -1, &pStmt, 0);
          355  +  if( rc!=SQLITE_OK ){
          356  +    sqlite3_finalize(pStmt);
          357  +    fatalError("%s\n%s\n", sqlite3_errmsg(g.db), zSql);
          358  +  }
          359  +  sqlite3_free(zSql);
          360  +  return pStmt;
          361  +}
          362  +
          363  +/*
          364  +** Run arbitrary SQL.  Issue a fatal error on failure.
          365  +*/
          366  +static void runSql(const char *zFormat, ...){
          367  +  va_list ap;
          368  +  char *zSql;
          369  +  int rc;
          370  +  va_start(ap, zFormat);
          371  +  zSql = sqlite3_vmprintf(zFormat, ap);
          372  +  va_end(ap);
          373  +  rc = sqlite3_exec(g.db, zSql, 0, 0, 0);
          374  +  if( rc!=SQLITE_OK ){
          375  +    fatalError("%s\n%s\n", sqlite3_errmsg(g.db), zSql);
          376  +  }
          377  +  sqlite3_free(zSql);
          378  +}
          379  +
          380  +/*
          381  +** Try to run arbitrary SQL.  Return success code.
          382  +*/
          383  +static int trySql(const char *zFormat, ...){
          384  +  va_list ap;
          385  +  char *zSql;
          386  +  int rc;
          387  +  va_start(ap, zFormat);
          388  +  zSql = sqlite3_vmprintf(zFormat, ap);
          389  +  va_end(ap);
          390  +  rc = sqlite3_exec(g.db, zSql, 0, 0, 0);
          391  +  sqlite3_free(zSql);
          392  +  return rc;
          393  +}
          394  +
          395  +/* Structure for holding an arbitrary length string
          396  +*/
          397  +typedef struct String String;
          398  +struct String {
          399  +  char *z;         /* the string */
          400  +  int n;           /* Slots of z[] used */
          401  +  int nAlloc;      /* Slots of z[] allocated */
          402  +};
          403  +
          404  +/* Free a string */
          405  +static void stringFree(String *p){
          406  +  if( p->z ) sqlite3_free(p->z);
          407  +  memset(p, 0, sizeof(*p));
          408  +}
          409  +
          410  +/* Append n bytes of text to a string.  If n<0 append the entire string. */
          411  +static void stringAppend(String *p, const char *z, int n){
          412  +  if( n<0 ) n = (int)strlen(z);
          413  +  if( p->n+n>=p->nAlloc ){
          414  +    int nAlloc = p->nAlloc*2 + n + 100;
          415  +    char *z = sqlite3_realloc(p->z, nAlloc);
          416  +    if( z==0 ) fatalError("out of memory");
          417  +    p->z = z;
          418  +    p->nAlloc = nAlloc;
          419  +  }
          420  +  memcpy(p->z+p->n, z, n);
          421  +  p->n += n;
          422  +  p->z[p->n] = 0;
          423  +}
          424  +
          425  +/* Reset a string to an empty string */
          426  +static void stringReset(String *p){
          427  +  if( p->z==0 ) stringAppend(p, " ", 1);
          428  +  p->n = 0;
          429  +  p->z[0] = 0;
          430  +}
          431  +
          432  +/* Append a new token onto the end of the string */
          433  +static void stringAppendTerm(String *p, const char *z){
          434  +  int i;
          435  +  if( p->n ) stringAppend(p, " ", 1);
          436  +  if( z==0 ){
          437  +    stringAppend(p, "nil", 3);
          438  +    return;
          439  +  }
          440  +  for(i=0; z[i] && !isspace(z[i]); i++){}
          441  +  if( i>0 && z[i]==0 ){
          442  +    stringAppend(p, z, i);
          443  +    return;
          444  +  }
          445  +  stringAppend(p, "'", 1);
          446  +  while( z[0] ){
          447  +    for(i=0; z[i] && z[i]!='\''; i++){}
          448  +    if( z[i] ){
          449  +      stringAppend(p, z, i+1);
          450  +      stringAppend(p, "'", 1);
          451  +      z += i+1;
          452  +    }else{
          453  +      stringAppend(p, z, i);
          454  +      break;
          455  +    }
          456  +  }
          457  +  stringAppend(p, "'", 1);
          458  +}
          459  +
          460  +/*
          461  +** Callback function for evalSql()
          462  +*/
          463  +static int evalCallback(void *pCData, int argc, char **argv, char **azCol){
          464  +  String *p = (String*)pCData;
          465  +  int i;
          466  +  UNUSED_PARAMETER(azCol);
          467  +  for(i=0; i<argc; i++) stringAppendTerm(p, argv[i]);
          468  +  return 0;
          469  +}
          470  +
          471  +/*
          472  +** Run arbitrary SQL and record the results in an output string
          473  +** given by the first parameter.
          474  +*/
          475  +static int evalSql(String *p, const char *zFormat, ...){
          476  +  va_list ap;
          477  +  char *zSql;
          478  +  int rc;
          479  +  char *zErrMsg = 0;
          480  +  va_start(ap, zFormat);
          481  +  zSql = sqlite3_vmprintf(zFormat, ap);
          482  +  va_end(ap);
          483  +  assert( g.iTimeout>0 );
          484  +  rc = sqlite3_exec(g.db, zSql, evalCallback, p, &zErrMsg);
          485  +  sqlite3_free(zSql);
          486  +  if( rc ){
          487  +    char zErr[30];
          488  +    sqlite3_snprintf(sizeof(zErr), zErr, "error(%d)", rc);
          489  +    stringAppendTerm(p, zErr);
          490  +    if( zErrMsg ){
          491  +      stringAppendTerm(p, zErrMsg);
          492  +      sqlite3_free(zErrMsg);
          493  +    }
          494  +  }
          495  +  return rc;
          496  +}
          497  +
          498  +/*
          499  +** Auxiliary SQL function to recursively evaluate SQL.
          500  +*/
          501  +static void evalFunc(
          502  +  sqlite3_context *context,
          503  +  int argc,
          504  +  sqlite3_value **argv
          505  +){
          506  +  sqlite3 *db = sqlite3_context_db_handle(context);
          507  +  const char *zSql = (const char*)sqlite3_value_text(argv[0]);
          508  +  String res;
          509  +  char *zErrMsg = 0;
          510  +  int rc;
          511  +  UNUSED_PARAMETER(argc);
          512  +  memset(&res, 0, sizeof(res));
          513  +  rc = sqlite3_exec(db, zSql, evalCallback, &res, &zErrMsg);
          514  +  if( zErrMsg ){
          515  +    sqlite3_result_error(context, zErrMsg, -1);
          516  +    sqlite3_free(zErrMsg);
          517  +  }else if( rc ){
          518  +    sqlite3_result_error_code(context, rc);
          519  +  }else{
          520  +    sqlite3_result_text(context, res.z, -1, SQLITE_TRANSIENT);
          521  +  }
          522  +  stringFree(&res);
          523  +}
          524  +
          525  +/*
          526  +** Look up the next task for client iClient in the database.
          527  +** Return the task script and the task number and mark that
          528  +** task as being under way.
          529  +*/
          530  +static int startScript(
          531  +  int iClient,              /* The client number */
          532  +  char **pzScript,          /* Write task script here */
          533  +  int *pTaskId,             /* Write task number here */
          534  +  char **pzTaskName         /* Name of the task */
          535  +){
          536  +  sqlite3_stmt *pStmt = 0;
          537  +  int taskId;
          538  +  int rc;
          539  +  int totalTime = 0;
          540  +
          541  +  *pzScript = 0;
          542  +  g.iTimeout = 0;
          543  +  while(1){
          544  +    rc = trySql("BEGIN IMMEDIATE");
          545  +    if( rc==SQLITE_BUSY ){
          546  +      sqlite3_sleep(10);
          547  +      totalTime += 10;
          548  +      continue;
          549  +    }
          550  +    if( rc!=SQLITE_OK ){
          551  +      fatalError("in startScript: %s", sqlite3_errmsg(g.db));
          552  +    }
          553  +    if( g.nError || g.nTest ){
          554  +      runSql("UPDATE counters SET nError=nError+%d, nTest=nTest+%d",
          555  +             g.nError, g.nTest);
          556  +      g.nError = 0;
          557  +      g.nTest = 0;
          558  +    }
          559  +    pStmt = prepareSql("SELECT 1 FROM client WHERE id=%d AND wantHalt",iClient);
          560  +    rc = sqlite3_step(pStmt);
          561  +    sqlite3_finalize(pStmt);
          562  +    if( rc==SQLITE_ROW ){
          563  +      runSql("DELETE FROM client WHERE id=%d", iClient);
          564  +      g.iTimeout = DEFAULT_TIMEOUT;
          565  +      runSql("COMMIT TRANSACTION;");
          566  +      return SQLITE_DONE;
          567  +    }
          568  +    pStmt = prepareSql(
          569  +              "SELECT script, id, name FROM task"
          570  +              " WHERE client=%d AND starttime IS NULL"
          571  +              " ORDER BY id LIMIT 1", iClient);
          572  +    rc = sqlite3_step(pStmt);
          573  +    if( rc==SQLITE_ROW ){
          574  +      int n = sqlite3_column_bytes(pStmt, 0);
          575  +      *pzScript = sqlite3_malloc(n+1);
          576  +      strcpy(*pzScript, (const char*)sqlite3_column_text(pStmt, 0));
          577  +      *pTaskId = taskId = sqlite3_column_int(pStmt, 1);
          578  +      *pzTaskName = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 2));
          579  +      sqlite3_finalize(pStmt);
          580  +      runSql("UPDATE task"
          581  +             "   SET starttime=strftime('%%Y-%%m-%%d %%H:%%M:%%f','now')"
          582  +             " WHERE id=%d;", taskId);
          583  +      g.iTimeout = DEFAULT_TIMEOUT;
          584  +      runSql("COMMIT TRANSACTION;");
          585  +      return SQLITE_OK;
          586  +    }
          587  +    sqlite3_finalize(pStmt);
          588  +    if( rc==SQLITE_DONE ){
          589  +      if( totalTime>30000 ){
          590  +        errorMessage("Waited over 30 seconds with no work.  Giving up.");
          591  +        runSql("DELETE FROM client WHERE id=%d; COMMIT;", iClient);
          592  +        sqlite3_close(g.db);
          593  +        exit(1);
          594  +      }
          595  +      while( trySql("COMMIT")==SQLITE_BUSY ){
          596  +        sqlite3_sleep(10);
          597  +        totalTime += 10;
          598  +      }
          599  +      sqlite3_sleep(100);
          600  +      totalTime += 100;
          601  +      continue;
          602  +    }
          603  +    fatalError("%s", sqlite3_errmsg(g.db));
          604  +  }
          605  +  g.iTimeout = DEFAULT_TIMEOUT;
          606  +}
          607  +
          608  +/*
          609  +** Mark a script as having finished.   Remove the CLIENT table entry
          610  +** if bShutdown is true.
          611  +*/
          612  +static int finishScript(int iClient, int taskId, int bShutdown){
          613  +  runSql("UPDATE task"
          614  +         "   SET endtime=strftime('%%Y-%%m-%%d %%H:%%M:%%f','now')"
          615  +         " WHERE id=%d;", taskId);
          616  +  if( bShutdown ){
          617  +    runSql("DELETE FROM client WHERE id=%d", iClient);
          618  +  }
          619  +  return SQLITE_OK;
          620  +}
          621  +
          622  +/*
          623  +** Start up a client process for iClient, if it is not already
          624  +** running.  If the client is already running, then this routine
          625  +** is a no-op.
          626  +*/
          627  +static void startClient(int iClient){
          628  +  runSql("INSERT OR IGNORE INTO client VALUES(%d,0)", iClient);
          629  +  if( sqlite3_changes(g.db) ){
          630  +    char *zSys;
          631  +    int rc;
          632  +    zSys = sqlite3_mprintf("%s \"%s\" --client %d --trace %d",
          633  +                 g.argv0, g.zDbFile, iClient, g.iTrace);
          634  +    if( g.bSqlTrace ){
          635  +      zSys = sqlite3_mprintf("%z --sqltrace", zSys);
          636  +    }
          637  +    if( g.bSync ){
          638  +      zSys = sqlite3_mprintf("%z --sync", zSys);
          639  +    }
          640  +    if( g.zVfs ){
          641  +      zSys = sqlite3_mprintf("%z --vfs \"%s\"", zSys, g.zVfs);
          642  +    }
          643  +    if( g.iTrace>=2 ) logMessage("system('%q')", zSys);
          644  +#if !defined(_WIN32)
          645  +    zSys = sqlite3_mprintf("%z &", zSys);
          646  +    rc = system(zSys);
          647  +    if( rc ) errorMessage("system() fails with error code %d", rc);
          648  +#else
          649  +    {
          650  +      STARTUPINFOA startupInfo;
          651  +      PROCESS_INFORMATION processInfo;
          652  +      memset(&startupInfo, 0, sizeof(startupInfo));
          653  +      startupInfo.cb = sizeof(startupInfo);
          654  +      memset(&processInfo, 0, sizeof(processInfo));
          655  +      rc = CreateProcessA(NULL, zSys, NULL, NULL, FALSE, 0, NULL, NULL,
          656  +                        &startupInfo, &processInfo);
          657  +      if( rc ){
          658  +        CloseHandle(processInfo.hThread);
          659  +        CloseHandle(processInfo.hProcess);
          660  +      }else{
          661  +        errorMessage("CreateProcessA() fails with error code %lu",
          662  +                     GetLastError());
          663  +      }
          664  +    }
          665  +#endif
          666  +    sqlite3_free(zSys);
          667  +  }
          668  +}
          669  +
          670  +/*
          671  +** Read the entire content of a file into memory
          672  +*/
          673  +static char *readFile(const char *zFilename){
          674  +  FILE *in = fopen(zFilename, "rb");
          675  +  long sz;
          676  +  char *z;
          677  +  if( in==0 ){
          678  +    fatalError("cannot open \"%s\" for reading", zFilename);
          679  +  }
          680  +  fseek(in, 0, SEEK_END);
          681  +  sz = ftell(in);
          682  +  rewind(in);
          683  +  z = sqlite3_malloc( sz+1 );
          684  +  sz = (long)fread(z, 1, sz, in);
          685  +  z[sz] = 0;
          686  +  fclose(in);
          687  +  return z;
          688  +}
          689  +
          690  +/*
          691  +** Return the length of the next token.
          692  +*/
          693  +static int tokenLength(const char *z, int *pnLine){
          694  +  int n = 0;
          695  +  if( isspace(z[0]) || (z[0]=='/' && z[1]=='*') ){
          696  +    int inC = 0;
          697  +    int c;
          698  +    if( z[0]=='/' ){
          699  +      inC = 1;
          700  +      n = 2;
          701  +    }
          702  +    while( (c = z[n++])!=0 ){
          703  +      if( c=='\n' ) (*pnLine)++;
          704  +      if( isspace(c) ) continue;
          705  +      if( inC && c=='*' && z[n]=='/' ){
          706  +        n++;
          707  +        inC = 0;
          708  +      }else if( !inC && c=='/' && z[n]=='*' ){
          709  +        n++;
          710  +        inC = 1;
          711  +      }else if( !inC ){
          712  +        break;
          713  +      }
          714  +    }
          715  +    n--;
          716  +  }else if( z[0]=='-' && z[1]=='-' ){
          717  +    for(n=2; z[n] && z[n]!='\n'; n++){}
          718  +    if( z[n] ){ (*pnLine)++; n++; }
          719  +  }else if( z[0]=='"' || z[0]=='\'' ){
          720  +    int delim = z[0];
          721  +    for(n=1; z[n]; n++){
          722  +      if( z[n]=='\n' ) (*pnLine)++;
          723  +      if( z[n]==delim ){
          724  +        n++;
          725  +        if( z[n+1]!=delim ) break;
          726  +      }
          727  +    }
          728  +  }else{
          729  +    int c;
          730  +    for(n=1; (c = z[n])!=0 && !isspace(c) && c!='"' && c!='\'' && c!=';'; n++){}
          731  +  }
          732  +  return n;
          733  +}
          734  +
          735  +/*
          736  +** Copy a single token into a string buffer.
          737  +*/
          738  +static int extractToken(const char *zIn, int nIn, char *zOut, int nOut){
          739  +  int i;
          740  +  if( nIn<=0 ){
          741  +    zOut[0] = 0;
          742  +    return 0;
          743  +  }
          744  +  for(i=0; i<nIn && i<nOut-1 && !isspace(zIn[i]); i++){ zOut[i] = zIn[i]; }
          745  +  zOut[i] = 0;
          746  +  return i;
          747  +}
          748  +
          749  +/*
          750  +** Find the number of characters up to the start of the next "--end" token.
          751  +*/
          752  +static int findEnd(const char *z, int *pnLine){
          753  +  int n = 0;
          754  +  while( z[n] && (strncmp(z+n,"--end",5) || !isspace(z[n+5])) ){
          755  +    n += tokenLength(z+n, pnLine);
          756  +  }
          757  +  return n;
          758  +}
          759  +
          760  +/*
          761  +** Find the number of characters up to the first character past the
          762  +** of the next "--endif"  or "--else" token. Nested --if commands are
          763  +** also skipped.
          764  +*/
          765  +static int findEndif(const char *z, int stopAtElse, int *pnLine){
          766  +  int n = 0;
          767  +  while( z[n] ){
          768  +    int len = tokenLength(z+n, pnLine);
          769  +    if( (strncmp(z+n,"--endif",7)==0 && isspace(z[n+7]))
          770  +     || (stopAtElse && strncmp(z+n,"--else",6)==0 && isspace(z[n+6]))
          771  +    ){
          772  +      return n+len;
          773  +    }
          774  +    if( strncmp(z+n,"--if",4)==0 && isspace(z[n+4]) ){
          775  +      int skip = findEndif(z+n+len, 0, pnLine);
          776  +      n += skip + len;
          777  +    }else{
          778  +      n += len;
          779  +    }
          780  +  }
          781  +  return n;
          782  +}
          783  +
          784  +/*
          785  +** Wait for a client process to complete all its tasks
          786  +*/
          787  +static void waitForClient(int iClient, int iTimeout, char *zErrPrefix){
          788  +  sqlite3_stmt *pStmt;
          789  +  int rc;
          790  +  if( iClient>0 ){
          791  +    pStmt = prepareSql(
          792  +               "SELECT 1 FROM task"
          793  +               " WHERE client=%d"
          794  +               "   AND client IN (SELECT id FROM client)"
          795  +               "  AND endtime IS NULL",
          796  +               iClient);
          797  +  }else{
          798  +    pStmt = prepareSql(
          799  +               "SELECT 1 FROM task"
          800  +               " WHERE client IN (SELECT id FROM client)"
          801  +               "   AND endtime IS NULL");
          802  +  }
          803  +  g.iTimeout = 0;
          804  +  while( ((rc = sqlite3_step(pStmt))==SQLITE_BUSY || rc==SQLITE_ROW)
          805  +    && iTimeout>0
          806  +  ){
          807  +    sqlite3_reset(pStmt);
          808  +    sqlite3_sleep(50);
          809  +    iTimeout -= 50;
          810  +  }
          811  +  sqlite3_finalize(pStmt);
          812  +  g.iTimeout = DEFAULT_TIMEOUT;
          813  +  if( rc!=SQLITE_DONE ){
          814  +    if( zErrPrefix==0 ) zErrPrefix = "";
          815  +    if( iClient>0 ){
          816  +      errorMessage("%stimeout waiting for client %d", zErrPrefix, iClient);
          817  +    }else{
          818  +      errorMessage("%stimeout waiting for all clients", zErrPrefix);
          819  +    }
          820  +  }
          821  +}
          822  +
          823  +/* Return a pointer to the tail of a filename
          824  +*/
          825  +static char *filenameTail(char *z){
          826  +  int i, j;
          827  +  for(i=j=0; z[i]; i++) if( z[i]=='/' ) j = i+1;
          828  +  return z+j;
          829  +}
          830  +
          831  +/*
          832  +** Interpret zArg as a boolean value.  Return either 0 or 1.
          833  +*/
          834  +static int booleanValue(char *zArg){
          835  +  int i;
          836  +  if( zArg==0 ) return 0;
          837  +  for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
          838  +  if( i>0 && zArg[i]==0 ) return atoi(zArg);
          839  +  if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
          840  +    return 1;
          841  +  }
          842  +  if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
          843  +    return 0;
          844  +  }
          845  +  errorMessage("unknown boolean: [%s]", zArg);
          846  +  return 0;
          847  +}
          848  +
          849  +
          850  +/* This routine exists as a convenient place to set a debugger
          851  +** breakpoint.
          852  +*/
          853  +static void test_breakpoint(void){ static volatile int cnt = 0; cnt++; }
          854  +
          855  +/* Maximum number of arguments to a --command */
          856  +#define MX_ARG 2
          857  +
          858  +/*
          859  +** Run a script.
          860  +*/
          861  +static void runScript(
          862  +  int iClient,       /* The client number, or 0 for the master */
          863  +  int taskId,        /* The task ID for clients.  0 for master */
          864  +  char *zScript,     /* Text of the script */
          865  +  char *zFilename    /* File from which script was read. */
          866  +){
          867  +  int lineno = 1;
          868  +  int prevLine = 1;
          869  +  int ii = 0;
          870  +  int iBegin = 0;
          871  +  int n, c, j;
          872  +  int len;
          873  +  int nArg;
          874  +  String sResult;
          875  +  char zCmd[30];
          876  +  char zError[1000];
          877  +  char azArg[MX_ARG][100];
          878  +
          879  +  memset(&sResult, 0, sizeof(sResult));
          880  +  stringReset(&sResult);
          881  +  while( (c = zScript[ii])!=0 ){
          882  +    prevLine = lineno;
          883  +    len = tokenLength(zScript+ii, &lineno);
          884  +    if( isspace(c) || (c=='/' && zScript[ii+1]=='*') ){
          885  +      ii += len;
          886  +      continue;
          887  +    }
          888  +    if( c!='-' || zScript[ii+1]!='-' || !isalpha(zScript[ii+2]) ){
          889  +      ii += len;
          890  +      continue;
          891  +    }
          892  +
          893  +    /* Run any prior SQL before processing the new --command */
          894  +    if( ii>iBegin ){
          895  +      char *zSql = sqlite3_mprintf("%.*s", ii-iBegin, zScript+iBegin);
          896  +      evalSql(&sResult, zSql);
          897  +      sqlite3_free(zSql);
          898  +      iBegin = ii + len;
          899  +    }
          900  +
          901  +    /* Parse the --command */
          902  +    if( g.iTrace>=2 ) logMessage("%.*s", len, zScript+ii);
          903  +    n = extractToken(zScript+ii+2, len-2, zCmd, sizeof(zCmd));
          904  +    for(nArg=0; n<len-2 && nArg<MX_ARG; nArg++){
          905  +      while( n<len-2 && isspace(zScript[ii+2+n]) ){ n++; }
          906  +      if( n>=len-2 ) break;
          907  +      n += extractToken(zScript+ii+2+n, len-2-n,
          908  +                        azArg[nArg], sizeof(azArg[nArg]));
          909  +    }
          910  +    for(j=nArg; j<MX_ARG; j++) azArg[j++][0] = 0;
          911  +
          912  +    /*
          913  +    **  --sleep N
          914  +    **
          915  +    ** Pause for N milliseconds
          916  +    */
          917  +    if( strcmp(zCmd, "sleep")==0 ){
          918  +      sqlite3_sleep(atoi(azArg[0]));
          919  +    }else 
          920  +
          921  +    /*
          922  +    **   --exit N
          923  +    **
          924  +    ** Exit this process.  If N>0 then exit without shutting down
          925  +    ** SQLite.  (In other words, simulate a crash.)
          926  +    */
          927  +    if( strcmp(zCmd, "exit")==0 ){
          928  +      int rc = atoi(azArg[0]);
          929  +      finishScript(iClient, taskId, 1);
          930  +      if( rc==0 ) sqlite3_close(g.db);
          931  +      exit(rc);
          932  +    }else
          933  +
          934  +    /*
          935  +    **   --testcase NAME
          936  +    **
          937  +    ** Begin a new test case.  Announce in the log that the test case
          938  +    ** has begun.
          939  +    */
          940  +    if( strcmp(zCmd, "testcase")==0 ){
          941  +      if( g.iTrace==1 ) logMessage("%.*s", len - 1, zScript+ii);
          942  +      stringReset(&sResult);
          943  +    }else
          944  +
          945  +    /*
          946  +    **   --finish
          947  +    **
          948  +    ** Mark the current task as having finished, even if it is not.
          949  +    ** This can be used in conjunction with --exit to simulate a crash.
          950  +    */
          951  +    if( strcmp(zCmd, "finish")==0 && iClient>0 ){
          952  +      finishScript(iClient, taskId, 1);
          953  +    }else
          954  +
          955  +    /*
          956  +    **  --reset
          957  +    **
          958  +    ** Reset accumulated results back to an empty string
          959  +    */
          960  +    if( strcmp(zCmd, "reset")==0 ){
          961  +      stringReset(&sResult);
          962  +    }else
          963  +
          964  +    /*
          965  +    **  --match ANSWER...
          966  +    **
          967  +    ** Check to see if output matches ANSWER.  Report an error if not.
          968  +    */
          969  +    if( strcmp(zCmd, "match")==0 ){
          970  +      int jj;
          971  +      char *zAns = zScript+ii;
          972  +      for(jj=7; jj<len-1 && isspace(zAns[jj]); jj++){}
          973  +      zAns += jj;
          974  +      if( len-jj-1!=sResult.n || strncmp(sResult.z, zAns, len-jj-1) ){
          975  +        errorMessage("line %d of %s:\nExpected [%.*s]\n     Got [%s]",
          976  +          prevLine, zFilename, len-jj-1, zAns, sResult.z);
          977  +      }
          978  +      g.nTest++;
          979  +      stringReset(&sResult);
          980  +    }else
          981  +
          982  +    /*
          983  +    **  --glob ANSWER...
          984  +    **  --notglob ANSWER....
          985  +    **
          986  +    ** Check to see if output does or does not match the glob pattern
          987  +    ** ANSWER.
          988  +    */
          989  +    if( strcmp(zCmd, "glob")==0 || strcmp(zCmd, "notglob")==0 ){
          990  +      int jj;
          991  +      char *zAns = zScript+ii;
          992  +      char *zCopy;
          993  +      int isGlob = (zCmd[0]=='g');
          994  +      for(jj=9-3*isGlob; jj<len-1 && isspace(zAns[jj]); jj++){}
          995  +      zAns += jj;
          996  +      zCopy = sqlite3_mprintf("%.*s", len-jj-1, zAns);
          997  +      if( (sqlite3_strglob(zCopy, sResult.z)==0)^isGlob ){
          998  +        errorMessage("line %d of %s:\nExpected [%s]\n     Got [%s]",
          999  +          prevLine, zFilename, zCopy, sResult.z);
         1000  +      }
         1001  +      sqlite3_free(zCopy);
         1002  +      g.nTest++;
         1003  +      stringReset(&sResult);
         1004  +    }else
         1005  +
         1006  +    /*
         1007  +    **  --output
         1008  +    **
         1009  +    ** Output the result of the previous SQL.
         1010  +    */
         1011  +    if( strcmp(zCmd, "output")==0 ){
         1012  +      logMessage("%s", sResult.z);
         1013  +    }else
         1014  +
         1015  +    /*
         1016  +    **  --source FILENAME
         1017  +    **
         1018  +    ** Run a subscript from a separate file.
         1019  +    */
         1020  +    if( strcmp(zCmd, "source")==0 ){
         1021  +      char *zNewFile, *zNewScript;
         1022  +      char *zToDel = 0;
         1023  +      zNewFile = azArg[0];
         1024  +      if( zNewFile[0]!='/' ){
         1025  +        int k;
         1026  +        for(k=(int)strlen(zFilename)-1; k>=0 && zFilename[k]!='/'; k--){}
         1027  +        if( k>0 ){
         1028  +          zNewFile = zToDel = sqlite3_mprintf("%.*s/%s", k,zFilename,zNewFile);
         1029  +        }
         1030  +      }
         1031  +      zNewScript = readFile(zNewFile);
         1032  +      if( g.iTrace ) logMessage("begin script [%s]\n", zNewFile);
         1033  +      runScript(0, 0, zNewScript, zNewFile);
         1034  +      sqlite3_free(zNewScript);
         1035  +      if( g.iTrace ) logMessage("end script [%s]\n", zNewFile);
         1036  +      sqlite3_free(zToDel);
         1037  +    }else
         1038  +
         1039  +    /*
         1040  +    **  --print MESSAGE....
         1041  +    **
         1042  +    ** Output the remainder of the line to the log file
         1043  +    */
         1044  +    if( strcmp(zCmd, "print")==0 ){
         1045  +      int jj;
         1046  +      for(jj=7; jj<len && isspace(zScript[ii+jj]); jj++){}
         1047  +      logMessage("%.*s", len-jj, zScript+ii+jj);
         1048  +    }else
         1049  +
         1050  +    /*
         1051  +    **  --if EXPR
         1052  +    **
         1053  +    ** Skip forward to the next matching --endif or --else if EXPR is false.
         1054  +    */
         1055  +    if( strcmp(zCmd, "if")==0 ){
         1056  +      int jj, rc;
         1057  +      sqlite3_stmt *pStmt;
         1058  +      for(jj=4; jj<len && isspace(zScript[ii+jj]); jj++){}
         1059  +      pStmt = prepareSql("SELECT %.*s", len-jj, zScript+ii+jj);
         1060  +      rc = sqlite3_step(pStmt);
         1061  +      if( rc!=SQLITE_ROW || sqlite3_column_int(pStmt, 0)==0 ){
         1062  +        ii += findEndif(zScript+ii+len, 1, &lineno);
         1063  +      }
         1064  +      sqlite3_finalize(pStmt);
         1065  +    }else
         1066  +
         1067  +    /*
         1068  +    **  --else
         1069  +    **
         1070  +    ** This command can only be encountered if currently inside an --if that
         1071  +    ** is true.  Skip forward to the next matching --endif.
         1072  +    */
         1073  +    if( strcmp(zCmd, "else")==0 ){
         1074  +      ii += findEndif(zScript+ii+len, 0, &lineno);
         1075  +    }else
         1076  +
         1077  +    /*
         1078  +    **  --endif
         1079  +    **
         1080  +    ** This command can only be encountered if currently inside an --if that
         1081  +    ** is true or an --else of a false if.  This is a no-op.
         1082  +    */
         1083  +    if( strcmp(zCmd, "endif")==0 ){
         1084  +      /* no-op */
         1085  +    }else
         1086  +
         1087  +    /*
         1088  +    **  --start CLIENT
         1089  +    **
         1090  +    ** Start up the given client.
         1091  +    */
         1092  +    if( strcmp(zCmd, "start")==0 && iClient==0 ){
         1093  +      int iNewClient = atoi(azArg[0]);
         1094  +      if( iNewClient>0 ){
         1095  +        startClient(iNewClient);
         1096  +      }
         1097  +    }else
         1098  +
         1099  +    /*
         1100  +    **  --wait CLIENT TIMEOUT
         1101  +    **
         1102  +    ** Wait until all tasks complete for the given client.  If CLIENT is
         1103  +    ** "all" then wait for all clients to complete.  Wait no longer than
         1104  +    ** TIMEOUT milliseconds (default 10,000)
         1105  +    */
         1106  +    if( strcmp(zCmd, "wait")==0 && iClient==0 ){
         1107  +      int iTimeout = nArg>=2 ? atoi(azArg[1]) : 10000;
         1108  +      sqlite3_snprintf(sizeof(zError),zError,"line %d of %s\n",
         1109  +                       prevLine, zFilename);
         1110  +      waitForClient(atoi(azArg[0]), iTimeout, zError);
         1111  +    }else
         1112  +
         1113  +    /*
         1114  +    **  --task CLIENT
         1115  +    **     <task-content-here>
         1116  +    **  --end
         1117  +    **
         1118  +    ** Assign work to a client.  Start the client if it is not running
         1119  +    ** already.
         1120  +    */
         1121  +    if( strcmp(zCmd, "task")==0 && iClient==0 ){
         1122  +      int iTarget = atoi(azArg[0]);
         1123  +      int iEnd;
         1124  +      char *zTask;
         1125  +      char *zTName;
         1126  +      iEnd = findEnd(zScript+ii+len, &lineno);
         1127  +      if( iTarget<0 ){
         1128  +        errorMessage("line %d of %s: bad client number: %d",
         1129  +                     prevLine, zFilename, iTarget);
         1130  +      }else{
         1131  +        zTask = sqlite3_mprintf("%.*s", iEnd, zScript+ii+len);
         1132  +        if( nArg>1 ){
         1133  +          zTName = sqlite3_mprintf("%s", azArg[1]);
         1134  +        }else{
         1135  +          zTName = sqlite3_mprintf("%s:%d", filenameTail(zFilename), prevLine);
         1136  +        }
         1137  +        startClient(iTarget);
         1138  +        runSql("INSERT INTO task(client,script,name)"
         1139  +               " VALUES(%d,'%q',%Q)", iTarget, zTask, zTName);
         1140  +        sqlite3_free(zTask);
         1141  +        sqlite3_free(zTName);
         1142  +      }
         1143  +      iEnd += tokenLength(zScript+ii+len+iEnd, &lineno);
         1144  +      len += iEnd;
         1145  +      iBegin = ii+len;
         1146  +    }else
         1147  +
         1148  +    /*
         1149  +    **  --breakpoint
         1150  +    **
         1151  +    ** This command calls "test_breakpoint()" which is a routine provided
         1152  +    ** as a convenient place to set a debugger breakpoint.
         1153  +    */
         1154  +    if( strcmp(zCmd, "breakpoint")==0 ){
         1155  +      test_breakpoint();
         1156  +    }else
         1157  +
         1158  +    /*
         1159  +    **  --show-sql-errors BOOLEAN
         1160  +    **
         1161  +    ** Turn display of SQL errors on and off.
         1162  +    */
         1163  +    if( strcmp(zCmd, "show-sql-errors")==0 ){
         1164  +      g.bIgnoreSqlErrors = nArg>=1 ? !booleanValue(azArg[0]) : 1;
         1165  +    }else
         1166  +
         1167  +
         1168  +    /* error */{
         1169  +      errorMessage("line %d of %s: unknown command --%s",
         1170  +                   prevLine, zFilename, zCmd);
         1171  +    }
         1172  +    ii += len;
         1173  +  }
         1174  +  if( iBegin<ii ){
         1175  +    char *zSql = sqlite3_mprintf("%.*s", ii-iBegin, zScript+iBegin);
         1176  +    runSql(zSql);
         1177  +    sqlite3_free(zSql);
         1178  +  }
         1179  +  stringFree(&sResult);
         1180  +}
         1181  +
         1182  +/*
         1183  +** Look for a command-line option.  If present, return a pointer.
         1184  +** Return NULL if missing.
         1185  +**
         1186  +** hasArg==0 means the option is a flag.  It is either present or not.
         1187  +** hasArg==1 means the option has an argument.  Return a pointer to the
         1188  +** argument.
         1189  +*/
         1190  +static char *findOption(
         1191  +  char **azArg,
         1192  +  int *pnArg,
         1193  +  const char *zOption,
         1194  +  int hasArg
         1195  +){
         1196  +  int i, j;
         1197  +  char *zReturn = 0;
         1198  +  int nArg = *pnArg;
         1199  +
         1200  +  assert( hasArg==0 || hasArg==1 );
         1201  +  for(i=0; i<nArg; i++){
         1202  +    const char *z;
         1203  +    if( i+hasArg >= nArg ) break;
         1204  +    z = azArg[i];
         1205  +    if( z[0]!='-' ) continue;
         1206  +    z++;
         1207  +    if( z[0]=='-' ){
         1208  +      if( z[1]==0 ) break;
         1209  +      z++;
         1210  +    }
         1211  +    if( strcmp(z,zOption)==0 ){
         1212  +      if( hasArg && i==nArg-1 ){
         1213  +        fatalError("command-line option \"--%s\" requires an argument", z);
         1214  +      }
         1215  +      if( hasArg ){
         1216  +        zReturn = azArg[i+1];
         1217  +      }else{
         1218  +        zReturn = azArg[i];
         1219  +      }
         1220  +      j = i+1+(hasArg!=0);
         1221  +      while( j<nArg ) azArg[i++] = azArg[j++];
         1222  +      *pnArg = i;
         1223  +      return zReturn;
         1224  +    }
         1225  +  }
         1226  +  return zReturn;
         1227  +}
         1228  +
         1229  +/* Print a usage message for the program and exit */
         1230  +static void usage(const char *argv0){
         1231  +  int i;
         1232  +  const char *zTail = argv0;
         1233  +  for(i=0; argv0[i]; i++){
         1234  +    if( argv0[i]=='/' ) zTail = argv0+i+1;
         1235  +  }
         1236  +  fprintf(stderr,"Usage: %s DATABASE ?OPTIONS? ?SCRIPT?\n", zTail);
         1237  +  exit(1);
         1238  +}
         1239  +
         1240  +/* Report on unrecognized arguments */
         1241  +static void unrecognizedArguments(
         1242  +  const char *argv0,
         1243  +  int nArg,
         1244  +  char **azArg
         1245  +){
         1246  +  int i;
         1247  +  fprintf(stderr,"%s: unrecognized arguments:", argv0);
         1248  +  for(i=0; i<nArg; i++){
         1249  +    fprintf(stderr," %s", azArg[i]);
         1250  +  }
         1251  +  fprintf(stderr,"\n");
         1252  +  exit(1);
         1253  +}
         1254  +
         1255  +int main(int argc, char **argv){
         1256  +  const char *zClient;
         1257  +  int iClient;
         1258  +  int n, i;
         1259  +  int openFlags = SQLITE_OPEN_READWRITE;
         1260  +  int rc;
         1261  +  char *zScript;
         1262  +  int taskId;
         1263  +  const char *zTrace;
         1264  +  const char *zCOption;
         1265  +
         1266  +  g.argv0 = argv[0];
         1267  +  g.iTrace = 1;
         1268  +  if( argc<2 ) usage(argv[0]);
         1269  +  g.zDbFile = argv[1];
         1270  +  if( strglob("*.test", g.zDbFile) ) usage(argv[0]);
         1271  +  if( strcmp(sqlite3_sourceid(), SQLITE_SOURCE_ID)!=0 ){
         1272  +    fprintf(stderr, "SQLite library and header mismatch\n"
         1273  +                    "Library: %s\n"
         1274  +                    "Header:  %s\n",
         1275  +                    sqlite3_sourceid(), SQLITE_SOURCE_ID);
         1276  +    exit(1);
         1277  +  }
         1278  +  n = argc-2;
         1279  +  sqlite3_snprintf(sizeof(g.zName), g.zName, "%05d.mptest", GETPID());
         1280  +  g.zVfs = findOption(argv+2, &n, "vfs", 1);
         1281  +  zClient = findOption(argv+2, &n, "client", 1);
         1282  +  g.zErrLog = findOption(argv+2, &n, "errlog", 1);
         1283  +  g.zLog = findOption(argv+2, &n, "log", 1);
         1284  +  zTrace = findOption(argv+2, &n, "trace", 1);
         1285  +  if( zTrace ) g.iTrace = atoi(zTrace);
         1286  +  if( findOption(argv+2, &n, "quiet", 0)!=0 ) g.iTrace = 0;
         1287  +  g.bSqlTrace = findOption(argv+2, &n, "sqltrace", 0)!=0;
         1288  +  g.bSync = findOption(argv+2, &n, "sync", 0)!=0;
         1289  +  if( g.zErrLog ){
         1290  +    g.pErrLog = fopen(g.zErrLog, "a");
         1291  +  }else{
         1292  +    g.pErrLog = stderr;
         1293  +  }
         1294  +  if( g.zLog ){
         1295  +    g.pLog = fopen(g.zLog, "a");
         1296  +  }else{
         1297  +    g.pLog = stdout;
         1298  +  }
         1299  +  
         1300  +  sqlite3_config(SQLITE_CONFIG_LOG, sqlErrorCallback, 0);
         1301  +  if( zClient ){
         1302  +    iClient = atoi(zClient);
         1303  +    if( iClient<1 ) fatalError("illegal client number: %d\n", iClient);
         1304  +    sqlite3_snprintf(sizeof(g.zName), g.zName, "%05d.client%02d",
         1305  +                     GETPID(), iClient);
         1306  +  }else{
         1307  +    if( g.iTrace>0 ){
         1308  +      printf("With SQLite " SQLITE_VERSION " " SQLITE_SOURCE_ID "\n" );
         1309  +      for(i=0; (zCOption = sqlite3_compileoption_get(i))!=0; i++){
         1310  +        printf("-DSQLITE_%s\n", zCOption);
         1311  +      }
         1312  +      fflush(stdout);
         1313  +    }
         1314  +    iClient =  0;
         1315  +    unlink(g.zDbFile);
         1316  +    openFlags |= SQLITE_OPEN_CREATE;
         1317  +  }
         1318  +  rc = sqlite3_open_v2(g.zDbFile, &g.db, openFlags, g.zVfs);
         1319  +  if( rc ) fatalError("cannot open [%s]", g.zDbFile);
         1320  +  sqlite3_enable_load_extension(g.db, 1);
         1321  +  sqlite3_busy_handler(g.db, busyHandler, 0);
         1322  +  sqlite3_create_function(g.db, "vfsname", 0, SQLITE_UTF8, 0,
         1323  +                          vfsNameFunc, 0, 0);
         1324  +  sqlite3_create_function(g.db, "eval", 1, SQLITE_UTF8, 0,
         1325  +                          evalFunc, 0, 0);
         1326  +  g.iTimeout = DEFAULT_TIMEOUT;
         1327  +  if( g.bSqlTrace ) sqlite3_trace(g.db, sqlTraceCallback, 0);
         1328  +  if( !g.bSync ) trySql("PRAGMA synchronous=OFF");
         1329  +  if( iClient>0 ){
         1330  +    if( n>0 ) unrecognizedArguments(argv[0], n, argv+2);
         1331  +    if( g.iTrace ) logMessage("start-client");
         1332  +    while(1){
         1333  +      char *zTaskName = 0;
         1334  +      rc = startScript(iClient, &zScript, &taskId, &zTaskName);
         1335  +      if( rc==SQLITE_DONE ) break;
         1336  +      if( g.iTrace ) logMessage("begin %s (%d)", zTaskName, taskId);
         1337  +      runScript(iClient, taskId, zScript, zTaskName);
         1338  +      if( g.iTrace ) logMessage("end %s (%d)", zTaskName, taskId);
         1339  +      finishScript(iClient, taskId, 0);
         1340  +      sqlite3_free(zTaskName);
         1341  +      sqlite3_sleep(10);
         1342  +    }
         1343  +    if( g.iTrace ) logMessage("end-client");
         1344  +  }else{
         1345  +    sqlite3_stmt *pStmt;
         1346  +    int iTimeout;
         1347  +    if( n==0 ){
         1348  +      fatalError("missing script filename");
         1349  +    }
         1350  +    if( n>1 ) unrecognizedArguments(argv[0], n, argv+2);
         1351  +    runSql(
         1352  +      "CREATE TABLE task(\n"
         1353  +      "  id INTEGER PRIMARY KEY,\n"
         1354  +      "  name TEXT,\n"
         1355  +      "  client INTEGER,\n"
         1356  +      "  starttime DATE,\n"
         1357  +      "  endtime DATE,\n"
         1358  +      "  script TEXT\n"
         1359  +      ");"
         1360  +      "CREATE INDEX task_i1 ON task(client, starttime);\n"
         1361  +      "CREATE INDEX task_i2 ON task(client, endtime);\n"
         1362  +      "CREATE TABLE counters(nError,nTest);\n"
         1363  +      "INSERT INTO counters VALUES(0,0);\n"
         1364  +      "CREATE TABLE client(id INTEGER PRIMARY KEY, wantHalt);\n"
         1365  +    );
         1366  +    zScript = readFile(argv[2]);
         1367  +    if( g.iTrace ) logMessage("begin script [%s]\n", argv[2]);
         1368  +    runScript(0, 0, zScript, argv[2]);
         1369  +    sqlite3_free(zScript);
         1370  +    if( g.iTrace ) logMessage("end script [%s]\n", argv[2]);
         1371  +    waitForClient(0, 2000, "during shutdown...\n");
         1372  +    trySql("UPDATE client SET wantHalt=1");
         1373  +    sqlite3_sleep(10);
         1374  +    g.iTimeout = 0;
         1375  +    iTimeout = 1000;
         1376  +    while( ((rc = trySql("SELECT 1 FROM client"))==SQLITE_BUSY
         1377  +        || rc==SQLITE_ROW) && iTimeout>0 ){
         1378  +      sqlite3_sleep(10);
         1379  +      iTimeout -= 10;
         1380  +    }
         1381  +    sqlite3_sleep(100);
         1382  +    pStmt = prepareSql("SELECT nError, nTest FROM counters");
         1383  +    iTimeout = 1000;
         1384  +    while( (rc = sqlite3_step(pStmt))==SQLITE_BUSY && iTimeout>0 ){
         1385  +      sqlite3_sleep(10);
         1386  +      iTimeout -= 10;
         1387  +    }
         1388  +    if( rc==SQLITE_ROW ){
         1389  +      g.nError += sqlite3_column_int(pStmt, 0);
         1390  +      g.nTest += sqlite3_column_int(pStmt, 1);
         1391  +    }
         1392  +    sqlite3_finalize(pStmt);
         1393  +  }
         1394  +  sqlite3_close(g.db);  
         1395  +  maybeClose(g.pLog);
         1396  +  maybeClose(g.pErrLog);
         1397  +  if( iClient==0 ){
         1398  +    printf("Summary: %d errors in %d tests\n", g.nError, g.nTest);
         1399  +  }
         1400  +  return g.nError>0;
         1401  +}

Added mptest/multiwrite01.test.

            1  +/*
            2  +** This script sets up five different tasks all writing and updating
            3  +** the database at the same time, but each in its own table.
            4  +*/
            5  +--task 1 build-t1
            6  +  DROP TABLE IF EXISTS t1;
            7  +  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
            8  +  --sleep 1
            9  +  INSERT INTO t1 VALUES(1, randomblob(2000));
           10  +  INSERT INTO t1 VALUES(2, randomblob(1000));
           11  +  --sleep 1
           12  +  INSERT INTO t1 SELECT a+2, randomblob(1500) FROM t1;
           13  +  INSERT INTO t1 SELECT a+4, randomblob(1500) FROM t1;
           14  +  INSERT INTO t1 SELECT a+8, randomblob(1500) FROM t1;
           15  +  --sleep 1
           16  +  INSERT INTO t1 SELECT a+16, randomblob(1500) FROM t1;
           17  +  --sleep 1
           18  +  INSERT INTO t1 SELECT a+32, randomblob(1500) FROM t1;
           19  +  SELECT count(*) FROM t1;
           20  +  --match 64
           21  +  SELECT avg(length(b)) FROM t1;
           22  +  --match 1500.0
           23  +  --sleep 2
           24  +  UPDATE t1 SET b='x'||a||'y';
           25  +  SELECT total(length(b)) FROM t1;
           26  +  --match 247
           27  +  SELECT a FROM t1 WHERE b='x17y';
           28  +  --match 17
           29  +  CREATE INDEX t1b ON t1(b);
           30  +  SELECT a FROM t1 WHERE b='x17y';
           31  +  --match 17
           32  +  SELECT a FROM t1 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
           33  +  --match 29 28 27 26 25
           34  +--end
           35  +
           36  +
           37  +--task 2 build-t2
           38  +  DROP TABLE IF EXISTS t2;
           39  +  CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
           40  +  --sleep 1
           41  +  INSERT INTO t2 VALUES(1, randomblob(2000));
           42  +  INSERT INTO t2 VALUES(2, randomblob(1000));
           43  +  --sleep 1
           44  +  INSERT INTO t2 SELECT a+2, randomblob(1500) FROM t2;
           45  +  INSERT INTO t2 SELECT a+4, randomblob(1500) FROM t2;
           46  +  INSERT INTO t2 SELECT a+8, randomblob(1500) FROM t2;
           47  +  --sleep 1
           48  +  INSERT INTO t2 SELECT a+16, randomblob(1500) FROM t2;
           49  +  --sleep 1
           50  +  INSERT INTO t2 SELECT a+32, randomblob(1500) FROM t2;
           51  +  SELECT count(*) FROM t2;
           52  +  --match 64
           53  +  SELECT avg(length(b)) FROM t2;
           54  +  --match 1500.0
           55  +  --sleep 2
           56  +  UPDATE t2 SET b='x'||a||'y';
           57  +  SELECT total(length(b)) FROM t2;
           58  +  --match 247
           59  +  SELECT a FROM t2 WHERE b='x17y';
           60  +  --match 17
           61  +  CREATE INDEX t2b ON t2(b);
           62  +  SELECT a FROM t2 WHERE b='x17y';
           63  +  --match 17
           64  +  SELECT a FROM t2 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
           65  +  --match 29 28 27 26 25
           66  +--end
           67  +
           68  +--task 3 build-t3
           69  +  DROP TABLE IF EXISTS t3;
           70  +  CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
           71  +  --sleep 1
           72  +  INSERT INTO t3 VALUES(1, randomblob(2000));
           73  +  INSERT INTO t3 VALUES(2, randomblob(1000));
           74  +  --sleep 1
           75  +  INSERT INTO t3 SELECT a+2, randomblob(1500) FROM t3;
           76  +  INSERT INTO t3 SELECT a+4, randomblob(1500) FROM t3;
           77  +  INSERT INTO t3 SELECT a+8, randomblob(1500) FROM t3;
           78  +  --sleep 1
           79  +  INSERT INTO t3 SELECT a+16, randomblob(1500) FROM t3;
           80  +  --sleep 1
           81  +  INSERT INTO t3 SELECT a+32, randomblob(1500) FROM t3;
           82  +  SELECT count(*) FROM t3;
           83  +  --match 64
           84  +  SELECT avg(length(b)) FROM t3;
           85  +  --match 1500.0
           86  +  --sleep 2
           87  +  UPDATE t3 SET b='x'||a||'y';
           88  +  SELECT total(length(b)) FROM t3;
           89  +  --match 247
           90  +  SELECT a FROM t3 WHERE b='x17y';
           91  +  --match 17
           92  +  CREATE INDEX t3b ON t3(b);
           93  +  SELECT a FROM t3 WHERE b='x17y';
           94  +  --match 17
           95  +  SELECT a FROM t3 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
           96  +  --match 29 28 27 26 25
           97  +--end
           98  +
           99  +--task 4 build-t4
          100  +  DROP TABLE IF EXISTS t4;
          101  +  CREATE TABLE t4(a INTEGER PRIMARY KEY, b);
          102  +  --sleep 1
          103  +  INSERT INTO t4 VALUES(1, randomblob(2000));
          104  +  INSERT INTO t4 VALUES(2, randomblob(1000));
          105  +  --sleep 1
          106  +  INSERT INTO t4 SELECT a+2, randomblob(1500) FROM t4;
          107  +  INSERT INTO t4 SELECT a+4, randomblob(1500) FROM t4;
          108  +  INSERT INTO t4 SELECT a+8, randomblob(1500) FROM t4;
          109  +  --sleep 1
          110  +  INSERT INTO t4 SELECT a+16, randomblob(1500) FROM t4;
          111  +  --sleep 1
          112  +  INSERT INTO t4 SELECT a+32, randomblob(1500) FROM t4;
          113  +  SELECT count(*) FROM t4;
          114  +  --match 64
          115  +  SELECT avg(length(b)) FROM t4;
          116  +  --match 1500.0
          117  +  --sleep 2
          118  +  UPDATE t4 SET b='x'||a||'y';
          119  +  SELECT total(length(b)) FROM t4;
          120  +  --match 247
          121  +  SELECT a FROM t4 WHERE b='x17y';
          122  +  --match 17
          123  +  CREATE INDEX t4b ON t4(b);
          124  +  SELECT a FROM t4 WHERE b='x17y';
          125  +  --match 17
          126  +  SELECT a FROM t4 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
          127  +  --match 29 28 27 26 25
          128  +--end
          129  +
          130  +--task 5 build-t5
          131  +  DROP TABLE IF EXISTS t5;
          132  +  CREATE TABLE t5(a INTEGER PRIMARY KEY, b);
          133  +  --sleep 1
          134  +  INSERT INTO t5 VALUES(1, randomblob(2000));
          135  +  INSERT INTO t5 VALUES(2, randomblob(1000));
          136  +  --sleep 1
          137  +  INSERT INTO t5 SELECT a+2, randomblob(1500) FROM t5;
          138  +  INSERT INTO t5 SELECT a+4, randomblob(1500) FROM t5;
          139  +  INSERT INTO t5 SELECT a+8, randomblob(1500) FROM t5;
          140  +  --sleep 1
          141  +  INSERT INTO t5 SELECT a+16, randomblob(1500) FROM t5;
          142  +  --sleep 1
          143  +  INSERT INTO t5 SELECT a+32, randomblob(1500) FROM t5;
          144  +  SELECT count(*) FROM t5;
          145  +  --match 64
          146  +  SELECT avg(length(b)) FROM t5;
          147  +  --match 1500.0
          148  +  --sleep 2
          149  +  UPDATE t5 SET b='x'||a||'y';
          150  +  SELECT total(length(b)) FROM t5;
          151  +  --match 247
          152  +  SELECT a FROM t5 WHERE b='x17y';
          153  +  --match 17
          154  +  CREATE INDEX t5b ON t5(b);
          155  +  SELECT a FROM t5 WHERE b='x17y';
          156  +  --match 17
          157  +  SELECT a FROM t5 WHERE b GLOB 'x2?y' ORDER BY b DESC LIMIT 5;
          158  +  --match 29 28 27 26 25
          159  +--end
          160  +
          161  +--wait all
          162  +SELECT count(*), total(length(b)) FROM t1;
          163  +--match 64 247
          164  +SELECT count(*), total(length(b)) FROM t2;
          165  +--match 64 247
          166  +SELECT count(*), total(length(b)) FROM t3;
          167  +--match 64 247
          168  +SELECT count(*), total(length(b)) FROM t4;
          169  +--match 64 247
          170  +SELECT count(*), total(length(b)) FROM t5;
          171  +--match 64 247
          172  +
          173  +--task 1
          174  +  SELECT t1.a FROM t1, t2
          175  +   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
          176  +   ORDER BY t1.a LIMIT 4
          177  +  --match 33 34 35 36
          178  +  SELECT t3.a FROM t3, t4
          179  +   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
          180  +   ORDER BY t3.a LIMIT 7
          181  +  --match 45 46 47 48 49 50 51
          182  +--end
          183  +--task 5
          184  +  SELECT t1.a FROM t1, t2
          185  +   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
          186  +   ORDER BY t1.a LIMIT 4
          187  +  --match 33 34 35 36
          188  +  SELECT t3.a FROM t3, t4
          189  +   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
          190  +   ORDER BY t3.a LIMIT 7
          191  +  --match 45 46 47 48 49 50 51
          192  +--end
          193  +--task 3
          194  +  SELECT t1.a FROM t1, t2
          195  +   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
          196  +   ORDER BY t1.a LIMIT 4
          197  +  --match 33 34 35 36
          198  +  SELECT t3.a FROM t3, t4
          199  +   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
          200  +   ORDER BY t3.a LIMIT 7
          201  +  --match 45 46 47 48 49 50 51
          202  +--end
          203  +--task 2
          204  +  SELECT t1.a FROM t1, t2
          205  +   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
          206  +   ORDER BY t1.a LIMIT 4
          207  +  --match 33 34 35 36
          208  +  SELECT t3.a FROM t3, t4
          209  +   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
          210  +   ORDER BY t3.a LIMIT 7
          211  +  --match 45 46 47 48 49 50 51
          212  +--end
          213  +--task 4
          214  +  SELECT t1.a FROM t1, t2
          215  +   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
          216  +   ORDER BY t1.a LIMIT 4
          217  +  --match 33 34 35 36
          218  +  SELECT t3.a FROM t3, t4
          219  +   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
          220  +   ORDER BY t3.a LIMIT 7
          221  +  --match 45 46 47 48 49 50 51
          222  +--end
          223  +--wait all
          224  +
          225  +--task 5
          226  +  DROP INDEX t5b;
          227  +  --sleep 5
          228  +  PRAGMA integrity_check(10);
          229  +  --match ok
          230  +  CREATE INDEX t5b ON t5(b DESC);
          231  +--end
          232  +--task 3
          233  +  DROP INDEX t3b;
          234  +  --sleep 5
          235  +  PRAGMA integrity_check(10);
          236  +  --match ok
          237  +  CREATE INDEX t3b ON t3(b DESC);
          238  +--end
          239  +--task 1
          240  +  DROP INDEX t1b;
          241  +  --sleep 5
          242  +  PRAGMA integrity_check(10);
          243  +  --match ok
          244  +  CREATE INDEX t1b ON t1(b DESC);
          245  +--end
          246  +--task 2
          247  +  DROP INDEX t2b;
          248  +  --sleep 5
          249  +  PRAGMA integrity_check(10);
          250  +  --match ok
          251  +  CREATE INDEX t2b ON t2(b DESC);
          252  +--end
          253  +--task 4
          254  +  DROP INDEX t4b;
          255  +  --sleep 5
          256  +  PRAGMA integrity_check(10);
          257  +  --match ok
          258  +  CREATE INDEX t4b ON t4(b DESC);
          259  +--end
          260  +--wait all
          261  +
          262  +--task 1
          263  +  SELECT t1.a FROM t1, t2
          264  +   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
          265  +   ORDER BY t1.a LIMIT 4
          266  +  --match 33 34 35 36
          267  +  SELECT t3.a FROM t3, t4
          268  +   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
          269  +   ORDER BY t3.a LIMIT 7
          270  +  --match 45 46 47 48 49 50 51
          271  +--end
          272  +--task 5
          273  +  SELECT t1.a FROM t1, t2
          274  +   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
          275  +   ORDER BY t1.a LIMIT 4
          276  +  --match 33 34 35 36
          277  +  SELECT t3.a FROM t3, t4
          278  +   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
          279  +   ORDER BY t3.a LIMIT 7
          280  +  --match 45 46 47 48 49 50 51
          281  +--end
          282  +--task 3
          283  +  SELECT t1.a FROM t1, t2
          284  +   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
          285  +   ORDER BY t1.a LIMIT 4
          286  +  --match 33 34 35 36
          287  +  SELECT t3.a FROM t3, t4
          288  +   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
          289  +   ORDER BY t3.a LIMIT 7
          290  +  --match 45 46 47 48 49 50 51
          291  +--end
          292  +--task 2
          293  +  SELECT t1.a FROM t1, t2
          294  +   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
          295  +   ORDER BY t1.a LIMIT 4
          296  +  --match 33 34 35 36
          297  +  SELECT t3.a FROM t3, t4
          298  +   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
          299  +   ORDER BY t3.a LIMIT 7
          300  +  --match 45 46 47 48 49 50 51
          301  +--end
          302  +--task 4
          303  +  SELECT t1.a FROM t1, t2
          304  +   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
          305  +   ORDER BY t1.a LIMIT 4
          306  +  --match 33 34 35 36
          307  +  SELECT t3.a FROM t3, t4
          308  +   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
          309  +   ORDER BY t3.a LIMIT 7
          310  +  --match 45 46 47 48 49 50 51
          311  +--end
          312  +--wait all
          313  +
          314  +VACUUM;
          315  +PRAGMA integrity_check(10);
          316  +--match ok
          317  +
          318  +--task 1
          319  +  UPDATE t1 SET b=randomblob(20000);
          320  +  --sleep 5
          321  +  UPDATE t1 SET b='x'||a||'y';
          322  +  SELECT a FROM t1 WHERE b='x63y';
          323  +  --match 63
          324  +--end
          325  +--task 2
          326  +  UPDATE t2 SET b=randomblob(20000);
          327  +  --sleep 5
          328  +  UPDATE t2 SET b='x'||a||'y';
          329  +  SELECT a FROM t2 WHERE b='x63y';
          330  +  --match 63
          331  +--end
          332  +--task 3
          333  +  UPDATE t3 SET b=randomblob(20000);
          334  +  --sleep 5
          335  +  UPDATE t3 SET b='x'||a||'y';
          336  +  SELECT a FROM t3 WHERE b='x63y';
          337  +  --match 63
          338  +--end
          339  +--task 4
          340  +  UPDATE t4 SET b=randomblob(20000);
          341  +  --sleep 5
          342  +  UPDATE t4 SET b='x'||a||'y';
          343  +  SELECT a FROM t4 WHERE b='x63y';
          344  +  --match 63
          345  +--end
          346  +--task 5
          347  +  UPDATE t5 SET b=randomblob(20000);
          348  +  --sleep 5
          349  +  UPDATE t5 SET b='x'||a||'y';
          350  +  SELECT a FROM t5 WHERE b='x63y';
          351  +  --match 63
          352  +--end
          353  +--wait all
          354  +
          355  +--task 1
          356  +  SELECT t1.a FROM t1, t2
          357  +   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
          358  +   ORDER BY t1.a LIMIT 4
          359  +  --match 33 34 35 36
          360  +  SELECT t3.a FROM t3, t4
          361  +   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
          362  +   ORDER BY t3.a LIMIT 7
          363  +  --match 45 46 47 48 49 50 51
          364  +--end
          365  +--task 5
          366  +  SELECT t1.a FROM t1, t2
          367  +   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
          368  +   ORDER BY t1.a LIMIT 4
          369  +  --match 33 34 35 36
          370  +  SELECT t3.a FROM t3, t4
          371  +   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
          372  +   ORDER BY t3.a LIMIT 7
          373  +  --match 45 46 47 48 49 50 51
          374  +--end
          375  +--task 3
          376  +  SELECT t1.a FROM t1, t2
          377  +   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
          378  +   ORDER BY t1.a LIMIT 4
          379  +  --match 33 34 35 36
          380  +  SELECT t3.a FROM t3, t4
          381  +   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
          382  +   ORDER BY t3.a LIMIT 7
          383  +  --match 45 46 47 48 49 50 51
          384  +--end
          385  +--task 2
          386  +  SELECT t1.a FROM t1, t2
          387  +   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
          388  +   ORDER BY t1.a LIMIT 4
          389  +  --match 33 34 35 36
          390  +  SELECT t3.a FROM t3, t4
          391  +   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
          392  +   ORDER BY t3.a LIMIT 7
          393  +  --match 45 46 47 48 49 50 51
          394  +--end
          395  +--task 4
          396  +  SELECT t1.a FROM t1, t2
          397  +   WHERE t2.b GLOB 'x3?y' AND t1.b=('x'||(t2.a+3)||'y')
          398  +   ORDER BY t1.a LIMIT 4
          399  +  --match 33 34 35 36
          400  +  SELECT t3.a FROM t3, t4
          401  +   WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y')
          402  +   ORDER BY t3.a LIMIT 7
          403  +  --match 45 46 47 48 49 50 51
          404  +--end
          405  +--wait all

Changes to src/attach.c.

   105    105       assert( z && zName );
   106    106       if( sqlite3StrICmp(z, zName)==0 ){
   107    107         zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName);
   108    108         goto attach_error;
   109    109       }
   110    110     }
   111    111   
   112         -  /* Allocate the new entry in the db->aDb[] array and initialise the schema
          112  +  /* Allocate the new entry in the db->aDb[] array and initialize the schema
   113    113     ** hash tables.
   114    114     */
   115    115     if( db->aDb==db->aDbStatic ){
   116    116       aNew = sqlite3DbMallocRaw(db, sizeof(db->aDb[0])*3 );
   117    117       if( aNew==0 ) return;
   118    118       memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
   119    119     }else{
................................................................................
   122    122     }
   123    123     db->aDb = aNew;
   124    124     aNew = &db->aDb[db->nDb];
   125    125     memset(aNew, 0, sizeof(*aNew));
   126    126   
   127    127     /* Open the database file. If the btree is successfully opened, use
   128    128     ** it to obtain the database schema. At this point the schema may
   129         -  ** or may not be initialised.
          129  +  ** or may not be initialized.
   130    130     */
   131    131     flags = db->openFlags;
   132    132     rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr);
   133    133     if( rc!=SQLITE_OK ){
   134    134       if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
   135    135       sqlite3_result_error(context, zErr, -1);
   136    136       sqlite3_free(zErr);

Changes to src/backup.c.

   393    393       */
   394    394       nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc);
   395    395       assert( nSrcPage>=0 );
   396    396       for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){
   397    397         const Pgno iSrcPg = p->iNext;                 /* Source page number */
   398    398         if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
   399    399           DbPage *pSrcPg;                             /* Source page object */
   400         -        rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
          400  +        rc = sqlite3PagerAcquire(pSrcPager, iSrcPg, &pSrcPg,
          401  +                                 PAGER_ACQUIRE_READONLY);
   401    402           if( rc==SQLITE_OK ){
   402    403             rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0);
   403    404             sqlite3PagerUnref(pSrcPg);
   404    405           }
   405    406         }
   406    407         p->iNext++;
   407    408       }

Changes to src/bitvec.c.

    68     68   
    69     69   #define BITVEC_NPTR      (BITVEC_USIZE/sizeof(Bitvec *))
    70     70   
    71     71   
    72     72   /*
    73     73   ** A bitmap is an instance of the following structure.
    74     74   **
    75         -** This bitmap records the existance of zero or more bits
           75  +** This bitmap records the existence of zero or more bits
    76     76   ** with values between 1 and iSize, inclusive.
    77     77   **
    78     78   ** There are three possible representations of the bitmap.
    79     79   ** If iSize<=BITVEC_NBIT, then Bitvec.u.aBitmap[] is a straight
    80     80   ** bitmap.  The least significant bit is bit 1.
    81     81   **
    82     82   ** If iSize>BITVEC_NBIT and iDivisor==0 then Bitvec.u.aHash[] is

Changes to src/btree.c.

   570    570   ** Clear (destroy) the BtShared.pHasContent bitvec. This should be
   571    571   ** invoked at the conclusion of each write-transaction.
   572    572   */
   573    573   static void btreeClearHasContent(BtShared *pBt){
   574    574     sqlite3BitvecDestroy(pBt->pHasContent);
   575    575     pBt->pHasContent = 0;
   576    576   }
          577  +
          578  +/*
          579  +** Release all of the apPage[] pages for a cursor.
          580  +*/
          581  +static void btreeReleaseAllCursorPages(BtCursor *pCur){
          582  +  int i;
          583  +  for(i=0; i<=pCur->iPage; i++){
          584  +    releasePage(pCur->apPage[i]);
          585  +    pCur->apPage[i] = 0;
          586  +  }
          587  +  pCur->iPage = -1;
          588  +}
          589  +
   577    590   
   578    591   /*
   579    592   ** Save the current cursor position in the variables BtCursor.nKey 
   580    593   ** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK.
   581    594   **
   582    595   ** The caller must ensure that the cursor is valid (has eState==CURSOR_VALID)
   583    596   ** prior to calling this routine.  
................................................................................
   610    623       }else{
   611    624         rc = SQLITE_NOMEM;
   612    625       }
   613    626     }
   614    627     assert( !pCur->apPage[0]->intKey || !pCur->pKey );
   615    628   
   616    629     if( rc==SQLITE_OK ){
   617         -    int i;
   618         -    for(i=0; i<=pCur->iPage; i++){
   619         -      releasePage(pCur->apPage[i]);
   620         -      pCur->apPage[i] = 0;
   621         -    }
   622         -    pCur->iPage = -1;
          630  +    btreeReleaseAllCursorPages(pCur);
   623    631       pCur->eState = CURSOR_REQUIRESEEK;
   624    632     }
   625    633   
   626    634     invalidateOverflowCache(pCur);
   627    635     return rc;
   628    636   }
   629    637   
................................................................................
   633    641   ** pExcept is used to modify the table (BtreeDelete() or BtreeInsert()).
   634    642   */
   635    643   static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){
   636    644     BtCursor *p;
   637    645     assert( sqlite3_mutex_held(pBt->mutex) );
   638    646     assert( pExcept==0 || pExcept->pBt==pBt );
   639    647     for(p=pBt->pCursor; p; p=p->pNext){
   640         -    if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) && 
   641         -        p->eState==CURSOR_VALID ){
   642         -      int rc = saveCursorPosition(p);
   643         -      if( SQLITE_OK!=rc ){
   644         -        return rc;
          648  +    if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){
          649  +      if( p->eState==CURSOR_VALID ){
          650  +        int rc = saveCursorPosition(p);
          651  +        if( SQLITE_OK!=rc ){
          652  +          return rc;
          653  +        }
          654  +      }else{
          655  +        testcase( p->iPage>0 );
          656  +        btreeReleaseAllCursorPages(p);
   645    657         }
   646    658       }
   647    659     }
   648    660     return SQLITE_OK;
   649    661   }
   650    662   
   651    663   /*
................................................................................
  1565   1577   ** means we have started to be concerned about content and the disk
  1566   1578   ** read should occur at that point.
  1567   1579   */
  1568   1580   static int btreeGetPage(
  1569   1581     BtShared *pBt,       /* The btree */
  1570   1582     Pgno pgno,           /* Number of the page to fetch */
  1571   1583     MemPage **ppPage,    /* Return the page in this parameter */
  1572         -  int noContent        /* Do not load page content if true */
         1584  +  int noContent,       /* Do not load page content if true */
         1585  +  int bReadonly        /* True if a read-only (mmap) page is ok */
  1573   1586   ){
  1574   1587     int rc;
  1575   1588     DbPage *pDbPage;
         1589  +  int flags = (noContent ? PAGER_ACQUIRE_NOCONTENT : 0) 
         1590  +            | (bReadonly ? PAGER_ACQUIRE_READONLY : 0);
  1576   1591   
         1592  +  assert( noContent==0 || bReadonly==0 );
  1577   1593     assert( sqlite3_mutex_held(pBt->mutex) );
  1578         -  rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, noContent);
         1594  +  rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, flags);
  1579   1595     if( rc ) return rc;
  1580   1596     *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt);
  1581   1597     return SQLITE_OK;
  1582   1598   }
  1583   1599   
  1584   1600   /*
  1585   1601   ** Retrieve a page from the pager cache. If the requested page is not
................................................................................
  1614   1630   ** convenience wrapper around separate calls to btreeGetPage() and 
  1615   1631   ** btreeInitPage().
  1616   1632   **
  1617   1633   ** If an error occurs, then the value *ppPage is set to is undefined. It
  1618   1634   ** may remain unchanged, or it may be set to an invalid value.
  1619   1635   */
  1620   1636   static int getAndInitPage(
  1621         -  BtShared *pBt,          /* The database file */
  1622         -  Pgno pgno,           /* Number of the page to get */
  1623         -  MemPage **ppPage     /* Write the page pointer here */
         1637  +  BtShared *pBt,                  /* The database file */
         1638  +  Pgno pgno,                      /* Number of the page to get */
         1639  +  MemPage **ppPage,               /* Write the page pointer here */
         1640  +  int bReadonly                   /* True if a read-only (mmap) page is ok */
  1624   1641   ){
  1625   1642     int rc;
  1626   1643     assert( sqlite3_mutex_held(pBt->mutex) );
  1627   1644   
  1628   1645     if( pgno>btreePagecount(pBt) ){
  1629   1646       rc = SQLITE_CORRUPT_BKPT;
  1630   1647     }else{
  1631         -    rc = btreeGetPage(pBt, pgno, ppPage, 0);
         1648  +    rc = btreeGetPage(pBt, pgno, ppPage, 0, bReadonly);
  1632   1649       if( rc==SQLITE_OK ){
  1633   1650         rc = btreeInitPage(*ppPage);
  1634   1651         if( rc!=SQLITE_OK ){
  1635   1652           releasePage(*ppPage);
  1636   1653         }
  1637   1654       }
  1638   1655     }
................................................................................
  1855   1872       if( pBt==0 ){
  1856   1873         rc = SQLITE_NOMEM;
  1857   1874         goto btree_open_out;
  1858   1875       }
  1859   1876       rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename,
  1860   1877                             EXTRA_SIZE, flags, vfsFlags, pageReinit);
  1861   1878       if( rc==SQLITE_OK ){
         1879  +      sqlite3PagerSetMmapLimit(pBt->pPager, db->szMmap);
  1862   1880         rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);
  1863   1881       }
  1864   1882       if( rc!=SQLITE_OK ){
  1865   1883         goto btree_open_out;
  1866   1884       }
  1867   1885       pBt->openFlags = (u8)flags;
  1868   1886       pBt->db = db;
................................................................................
  2120   2138     BtShared *pBt = p->pBt;
  2121   2139     assert( sqlite3_mutex_held(p->db->mutex) );
  2122   2140     sqlite3BtreeEnter(p);
  2123   2141     sqlite3PagerSetCachesize(pBt->pPager, mxPage);
  2124   2142     sqlite3BtreeLeave(p);
  2125   2143     return SQLITE_OK;
  2126   2144   }
         2145  +
         2146  +/*
         2147  +** Change the limit on the amount of the database file that may be
         2148  +** memory mapped.
         2149  +*/
         2150  +int sqlite3BtreeSetMmapLimit(Btree *p, sqlite3_int64 szMmap){
         2151  +  BtShared *pBt = p->pBt;
         2152  +  assert( sqlite3_mutex_held(p->db->mutex) );
         2153  +  sqlite3BtreeEnter(p);
         2154  +  sqlite3PagerSetMmapLimit(pBt->pPager, szMmap);
         2155  +  sqlite3BtreeLeave(p);
         2156  +  return SQLITE_OK;
         2157  +}
  2127   2158   
  2128   2159   /*
  2129   2160   ** Change the way data is synced to disk in order to increase or decrease
  2130   2161   ** how well the database resists damage due to OS crashes and power
  2131   2162   ** failures.  Level 1 is the same as asynchronous (no syncs() occur and
  2132   2163   ** there is a high probability of damage)  Level 2 is the default.  There
  2133   2164   ** is a very low but non-zero probability of damage.  Level 3 reduces the
................................................................................
  2225   2256   ** may only be called if it is guaranteed that the b-tree mutex is already
  2226   2257   ** held.
  2227   2258   **
  2228   2259   ** This is useful in one special case in the backup API code where it is
  2229   2260   ** known that the shared b-tree mutex is held, but the mutex on the 
  2230   2261   ** database handle that owns *p is not. In this case if sqlite3BtreeEnter()
  2231   2262   ** were to be called, it might collide with some other operation on the
  2232         -** database handle that owns *p, causing undefined behaviour.
         2263  +** database handle that owns *p, causing undefined behavior.
  2233   2264   */
  2234   2265   int sqlite3BtreeGetReserveNoMutex(Btree *p){
  2235   2266     assert( sqlite3_mutex_held(p->pBt->mutex) );
  2236   2267     return p->pBt->pageSize - p->pBt->usableSize;
  2237   2268   }
  2238   2269   #endif /* SQLITE_HAS_CODEC || SQLITE_DEBUG */
  2239   2270   
................................................................................
  2346   2377     int nPageFile = 0;   /* Number of pages in the database file */
  2347   2378     int nPageHeader;     /* Number of pages in the database according to hdr */
  2348   2379   
  2349   2380     assert( sqlite3_mutex_held(pBt->mutex) );
  2350   2381     assert( pBt->pPage1==0 );
  2351   2382     rc = sqlite3PagerSharedLock(pBt->pPager);
  2352   2383     if( rc!=SQLITE_OK ) return rc;
  2353         -  rc = btreeGetPage(pBt, 1, &pPage1, 0);
         2384  +  rc = btreeGetPage(pBt, 1, &pPage1, 0, 0);
  2354   2385     if( rc!=SQLITE_OK ) return rc;
  2355   2386   
  2356   2387     /* Do some checking to help insure the file we opened really is
  2357   2388     ** a valid database file. 
  2358   2389     */
  2359   2390     nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData);
  2360   2391     sqlite3PagerPagecount(pBt->pPager, &nPageFile);
................................................................................
  2905   2936     }
  2906   2937   
  2907   2938     /* Fix the database pointer on page iPtrPage that pointed at iDbPage so
  2908   2939     ** that it points at iFreePage. Also fix the pointer map entry for
  2909   2940     ** iPtrPage.
  2910   2941     */
  2911   2942     if( eType!=PTRMAP_ROOTPAGE ){
  2912         -    rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0);
         2943  +    rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0, 0);
  2913   2944       if( rc!=SQLITE_OK ){
  2914   2945         return rc;
  2915   2946       }
  2916   2947       rc = sqlite3PagerWrite(pPtrPage->pDbPage);
  2917   2948       if( rc!=SQLITE_OK ){
  2918   2949         releasePage(pPtrPage);
  2919   2950         return rc;
................................................................................
  2989   3020         }
  2990   3021       } else {
  2991   3022         Pgno iFreePg;             /* Index of free page to move pLastPg to */
  2992   3023         MemPage *pLastPg;
  2993   3024         u8 eMode = BTALLOC_ANY;   /* Mode parameter for allocateBtreePage() */
  2994   3025         Pgno iNear = 0;           /* nearby parameter for allocateBtreePage() */
  2995   3026   
  2996         -      rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0);
         3027  +      rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0, 0);
  2997   3028         if( rc!=SQLITE_OK ){
  2998   3029           return rc;
  2999   3030         }
  3000   3031   
  3001   3032         /* If bCommit is zero, this loop runs exactly once and page pLastPg
  3002   3033         ** is swapped with the first free page pulled off the free list.
  3003   3034         **
................................................................................
  3081   3112       Pgno nOrig = btreePagecount(pBt);
  3082   3113       Pgno nFree = get4byte(&pBt->pPage1->aData[36]);
  3083   3114       Pgno nFin = finalDbSize(pBt, nOrig, nFree);
  3084   3115   
  3085   3116       if( nOrig<nFin ){
  3086   3117         rc = SQLITE_CORRUPT_BKPT;
  3087   3118       }else if( nFree>0 ){
  3088         -      invalidateAllOverflowCache(pBt);
  3089         -      rc = incrVacuumStep(pBt, nFin, nOrig, 0);
         3119  +      rc = saveAllCursors(pBt, 0, 0);
         3120  +      if( rc==SQLITE_OK ){
         3121  +        invalidateAllOverflowCache(pBt);
         3122  +        rc = incrVacuumStep(pBt, nFin, nOrig, 0);
         3123  +      }
  3090   3124         if( rc==SQLITE_OK ){
  3091   3125           rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
  3092   3126           put4byte(&pBt->pPage1->aData[28], pBt->nPage);
  3093   3127         }
  3094   3128       }else{
  3095   3129         rc = SQLITE_DONE;
  3096   3130       }
................................................................................
  3130   3164         */
  3131   3165         return SQLITE_CORRUPT_BKPT;
  3132   3166       }
  3133   3167   
  3134   3168       nFree = get4byte(&pBt->pPage1->aData[36]);
  3135   3169       nFin = finalDbSize(pBt, nOrig, nFree);
  3136   3170       if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT;
  3137         -
         3171  +    if( nFin<nOrig ){
         3172  +      rc = saveAllCursors(pBt, 0, 0);
         3173  +    }
  3138   3174       for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){
  3139   3175         rc = incrVacuumStep(pBt, nFin, iFree, 1);
  3140   3176       }
  3141   3177       if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){
  3142   3178         rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
  3143   3179         put4byte(&pBt->pPage1->aData[32], 0);
  3144   3180         put4byte(&pBt->pPage1->aData[36], 0);
................................................................................
  3147   3183         pBt->nPage = nFin;
  3148   3184       }
  3149   3185       if( rc!=SQLITE_OK ){
  3150   3186         sqlite3PagerRollback(pPager);
  3151   3187       }
  3152   3188     }
  3153   3189   
  3154         -  assert( nRef==sqlite3PagerRefcount(pPager) );
         3190  +  assert( nRef>=sqlite3PagerRefcount(pPager) );
  3155   3191     return rc;
  3156   3192   }
  3157   3193   
  3158   3194   #else /* ifndef SQLITE_OMIT_AUTOVACUUM */
  3159   3195   # define setChildPtrmaps(x) SQLITE_OK
  3160   3196   #endif
  3161   3197   
................................................................................
  3403   3439       if( rc2!=SQLITE_OK ){
  3404   3440         rc = rc2;
  3405   3441       }
  3406   3442   
  3407   3443       /* The rollback may have destroyed the pPage1->aData value.  So
  3408   3444       ** call btreeGetPage() on page 1 again to make
  3409   3445       ** sure pPage1->aData is set correctly. */
  3410         -    if( btreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){
         3446  +    if( btreeGetPage(pBt, 1, &pPage1, 0, 0)==SQLITE_OK ){
  3411   3447         int nPage = get4byte(28+(u8*)pPage1->aData);
  3412   3448         testcase( nPage==0 );
  3413   3449         if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
  3414   3450         testcase( pBt->nPage!=nPage );
  3415   3451         pBt->nPage = nPage;
  3416   3452         releasePage(pPage1);
  3417   3453       }
................................................................................
  3837   3873         }
  3838   3874       }
  3839   3875     }
  3840   3876   #endif
  3841   3877   
  3842   3878     assert( next==0 || rc==SQLITE_DONE );
  3843   3879     if( rc==SQLITE_OK ){
  3844         -    rc = btreeGetPage(pBt, ovfl, &pPage, 0);
         3880  +    rc = btreeGetPage(pBt, ovfl, &pPage, 0, (ppPage==0));
  3845   3881       assert( rc==SQLITE_OK || pPage==0 );
  3846   3882       if( rc==SQLITE_OK ){
  3847   3883         next = get4byte(pPage->aData);
  3848   3884       }
  3849   3885     }
  3850   3886   
  3851   3887     *pPgnoNext = next;
................................................................................
  4058   4094             nextPage = get4byte(aWrite);
  4059   4095             memcpy(aWrite, aSave, 4);
  4060   4096           }else
  4061   4097   #endif
  4062   4098   
  4063   4099           {
  4064   4100             DbPage *pDbPage;
  4065         -          rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage);
         4101  +          rc = sqlite3PagerAcquire(pBt->pPager, nextPage, &pDbPage,
         4102  +              (eOp==0 ? PAGER_ACQUIRE_READONLY : 0)
         4103  +          );
  4066   4104             if( rc==SQLITE_OK ){
  4067   4105               aPayload = sqlite3PagerGetData(pDbPage);
  4068   4106               nextPage = get4byte(aPayload);
  4069   4107               rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
  4070   4108               sqlite3PagerUnref(pDbPage);
  4071   4109               offset = 0;
  4072   4110             }
................................................................................
  4237   4275     int i = pCur->iPage;
  4238   4276     MemPage *pNewPage;
  4239   4277     BtShared *pBt = pCur->pBt;
  4240   4278   
  4241   4279     assert( cursorHoldsMutex(pCur) );
  4242   4280     assert( pCur->eState==CURSOR_VALID );
  4243   4281     assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
         4282  +  assert( pCur->iPage>=0 );
  4244   4283     if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
  4245   4284       return SQLITE_CORRUPT_BKPT;
  4246   4285     }
  4247         -  rc = getAndInitPage(pBt, newPgno, &pNewPage);
         4286  +  rc = getAndInitPage(pBt, newPgno, &pNewPage, (pCur->wrFlag==0));
  4248   4287     if( rc ) return rc;
  4249   4288     pCur->apPage[i+1] = pNewPage;
  4250   4289     pCur->aiIdx[i+1] = 0;
  4251   4290     pCur->iPage++;
  4252   4291   
  4253   4292     pCur->info.nSize = 0;
  4254   4293     pCur->validNKey = 0;
................................................................................
  4357   4396         releasePage(pCur->apPage[i]);
  4358   4397       }
  4359   4398       pCur->iPage = 0;
  4360   4399     }else if( pCur->pgnoRoot==0 ){
  4361   4400       pCur->eState = CURSOR_INVALID;
  4362   4401       return SQLITE_OK;
  4363   4402     }else{
  4364         -    rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]);
         4403  +    rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0], pCur->wrFlag==0);
  4365   4404       if( rc!=SQLITE_OK ){
  4366   4405         pCur->eState = CURSOR_INVALID;
  4367   4406         return rc;
  4368   4407       }
  4369   4408       pCur->iPage = 0;
  4370   4409   
  4371   4410       /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
................................................................................
  4971   5010         }else{
  4972   5011           iTrunk = get4byte(&pPage1->aData[32]);
  4973   5012         }
  4974   5013         testcase( iTrunk==mxPage );
  4975   5014         if( iTrunk>mxPage ){
  4976   5015           rc = SQLITE_CORRUPT_BKPT;
  4977   5016         }else{
  4978         -        rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
         5017  +        rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0, 0);
  4979   5018         }
  4980   5019         if( rc ){
  4981   5020           pTrunk = 0;
  4982   5021           goto end_allocate_page;
  4983   5022         }
  4984   5023         assert( pTrunk!=0 );
  4985   5024         assert( pTrunk->aData!=0 );
................................................................................
  5035   5074             MemPage *pNewTrunk;
  5036   5075             Pgno iNewTrunk = get4byte(&pTrunk->aData[8]);
  5037   5076             if( iNewTrunk>mxPage ){ 
  5038   5077               rc = SQLITE_CORRUPT_BKPT;
  5039   5078               goto end_allocate_page;
  5040   5079             }
  5041   5080             testcase( iNewTrunk==mxPage );
  5042         -          rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0);
         5081  +          rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0, 0);
  5043   5082             if( rc!=SQLITE_OK ){
  5044   5083               goto end_allocate_page;
  5045   5084             }
  5046   5085             rc = sqlite3PagerWrite(pNewTrunk->pDbPage);
  5047   5086             if( rc!=SQLITE_OK ){
  5048   5087               releasePage(pNewTrunk);
  5049   5088               goto end_allocate_page;
................................................................................
  5115   5154             rc = sqlite3PagerWrite(pTrunk->pDbPage);
  5116   5155             if( rc ) goto end_allocate_page;
  5117   5156             if( closest<k-1 ){
  5118   5157               memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
  5119   5158             }
  5120   5159             put4byte(&aData[4], k-1);
  5121   5160             noContent = !btreeGetHasContent(pBt, *pPgno);
  5122         -          rc = btreeGetPage(pBt, *pPgno, ppPage, noContent);
         5161  +          rc = btreeGetPage(pBt, *pPgno, ppPage, noContent, 0);
  5123   5162             if( rc==SQLITE_OK ){
  5124   5163               rc = sqlite3PagerWrite((*ppPage)->pDbPage);
  5125   5164               if( rc!=SQLITE_OK ){
  5126   5165                 releasePage(*ppPage);
  5127   5166               }
  5128   5167             }
  5129   5168             searchList = 0;
................................................................................
  5163   5202         /* If *pPgno refers to a pointer-map page, allocate two new pages
  5164   5203         ** at the end of the file instead of one. The first allocated page
  5165   5204         ** becomes a new pointer-map page, the second is used by the caller.
  5166   5205         */
  5167   5206         MemPage *pPg = 0;
  5168   5207         TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage));
  5169   5208         assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) );
  5170         -      rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent);
         5209  +      rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent, 0);
  5171   5210         if( rc==SQLITE_OK ){
  5172   5211           rc = sqlite3PagerWrite(pPg->pDbPage);
  5173   5212           releasePage(pPg);
  5174   5213         }
  5175   5214         if( rc ) return rc;
  5176   5215         pBt->nPage++;
  5177   5216         if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ){ pBt->nPage++; }
  5178   5217       }
  5179   5218   #endif
  5180   5219       put4byte(28 + (u8*)pBt->pPage1->aData, pBt->nPage);
  5181   5220       *pPgno = pBt->nPage;
  5182   5221   
  5183   5222       assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
  5184         -    rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent);
         5223  +    rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent, 0);
  5185   5224       if( rc ) return rc;
  5186   5225       rc = sqlite3PagerWrite((*ppPage)->pDbPage);
  5187   5226       if( rc!=SQLITE_OK ){
  5188   5227         releasePage(*ppPage);
  5189   5228       }
  5190   5229       TRACE(("ALLOCATE: %d from end of file\n", *pPgno));
  5191   5230     }
................................................................................
  5245   5284     nFree = get4byte(&pPage1->aData[36]);
  5246   5285     put4byte(&pPage1->aData[36], nFree+1);
  5247   5286   
  5248   5287     if( pBt->btsFlags & BTS_SECURE_DELETE ){
  5249   5288       /* If the secure_delete option is enabled, then
  5250   5289       ** always fully overwrite deleted information with zeros.
  5251   5290       */
  5252         -    if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) )
         5291  +    if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0, 0))!=0) )
  5253   5292        ||            ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0)
  5254   5293       ){
  5255   5294         goto freepage_out;
  5256   5295       }
  5257   5296       memset(pPage->aData, 0, pPage->pBt->pageSize);
  5258   5297     }
  5259   5298   
................................................................................
  5272   5311     ** first trunk page in the current free-list. This block tests if it
  5273   5312     ** is possible to add the page as a new free-list leaf.
  5274   5313     */
  5275   5314     if( nFree!=0 ){
  5276   5315       u32 nLeaf;                /* Initial number of leaf cells on trunk page */
  5277   5316   
  5278   5317       iTrunk = get4byte(&pPage1->aData[32]);
  5279         -    rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
         5318  +    rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0, 0);
  5280   5319       if( rc!=SQLITE_OK ){
  5281   5320         goto freepage_out;
  5282   5321       }
  5283   5322   
  5284   5323       nLeaf = get4byte(&pTrunk->aData[4]);
  5285   5324       assert( pBt->usableSize>32 );
  5286   5325       if( nLeaf > (u32)pBt->usableSize/4 - 2 ){
................................................................................
  5318   5357   
  5319   5358     /* If control flows to this point, then it was not possible to add the
  5320   5359     ** the page being freed as a leaf page of the first trunk in the free-list.
  5321   5360     ** Possibly because the free-list is empty, or possibly because the 
  5322   5361     ** first trunk in the free-list is full. Either way, the page being freed
  5323   5362     ** will become the new first trunk page in the free-list.
  5324   5363     */
  5325         -  if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0)) ){
         5364  +  if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0, 0)) ){
  5326   5365       goto freepage_out;
  5327   5366     }
  5328   5367     rc = sqlite3PagerWrite(pPage->pDbPage);
  5329   5368     if( rc!=SQLITE_OK ){
  5330   5369       goto freepage_out;
  5331   5370     }
  5332   5371     put4byte(pPage->aData, iTrunk);
................................................................................
  5505   5544         /* If the database supports auto-vacuum, and the second or subsequent
  5506   5545         ** overflow page is being allocated, add an entry to the pointer-map
  5507   5546         ** for that page now. 
  5508   5547         **
  5509   5548         ** If this is the first overflow page, then write a partial entry 
  5510   5549         ** to the pointer-map. If we write nothing to this pointer-map slot,
  5511   5550         ** then the optimistic overflow chain processing in clearCell()
  5512         -      ** may misinterpret the uninitialised values and delete the
         5551  +      ** may misinterpret the uninitialized values and delete the
  5513   5552         ** wrong pages from the database.
  5514   5553         */
  5515   5554         if( pBt->autoVacuum && rc==SQLITE_OK ){
  5516   5555           u8 eType = (pgnoPtrmap?PTRMAP_OVERFLOW2:PTRMAP_OVERFLOW1);
  5517   5556           ptrmapPut(pBt, pgnoOvfl, eType, pgnoPtrmap, &rc);
  5518   5557           if( rc ){
  5519   5558             releasePage(pOvfl);
................................................................................
  6119   6158     if( (i+nxDiv-pParent->nOverflow)==pParent->nCell ){
  6120   6159       pRight = &pParent->aData[pParent->hdrOffset+8];
  6121   6160     }else{
  6122   6161       pRight = findCell(pParent, i+nxDiv-pParent->nOverflow);
  6123   6162     }
  6124   6163     pgno = get4byte(pRight);
  6125   6164     while( 1 ){
  6126         -    rc = getAndInitPage(pBt, pgno, &apOld[i]);
         6165  +    rc = getAndInitPage(pBt, pgno, &apOld[i], 0);
  6127   6166       if( rc ){
  6128   6167         memset(apOld, 0, (i+1)*sizeof(MemPage*));
  6129   6168         goto balance_cleanup;
  6130   6169       }
  6131   6170       nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
  6132   6171       if( (i--)==0 ) break;
  6133   6172   
................................................................................
  6978   7017       idx = ++pCur->aiIdx[pCur->iPage];
  6979   7018     }else{
  6980   7019       assert( pPage->leaf );
  6981   7020     }
  6982   7021     insertCell(pPage, idx, newCell, szNew, 0, 0, &rc);
  6983   7022     assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );
  6984   7023   
  6985         -  /* If no error has occured and pPage has an overflow cell, call balance() 
         7024  +  /* If no error has occurred and pPage has an overflow cell, call balance() 
  6986   7025     ** to redistribute the cells within the tree. Since balance() may move
  6987   7026     ** the cursor, zero the BtCursor.info.nSize and BtCursor.validNKey
  6988   7027     ** variables.
  6989   7028     **
  6990   7029     ** Previous versions of SQLite called moveToRoot() to move the cursor
  6991   7030     ** back to the root page as balance() used to invalidate the contents
  6992   7031     ** of BtCursor.apPage[] and BtCursor.aiIdx[]. Instead of doing that,
................................................................................
  7207   7246         ** allocated pgnoMove. If required (i.e. if it was not allocated
  7208   7247         ** by extending the file), the current page at position pgnoMove
  7209   7248         ** is already journaled.
  7210   7249         */
  7211   7250         u8 eType = 0;
  7212   7251         Pgno iPtrPage = 0;
  7213   7252   
         7253  +      /* Save the positions of any open cursors. This is required in
         7254  +      ** case they are holding a reference to an xFetch reference
         7255  +      ** corresponding to page pgnoRoot.  */
         7256  +      rc = saveAllCursors(pBt, 0, 0);
  7214   7257         releasePage(pPageMove);
         7258  +      if( rc!=SQLITE_OK ){
         7259  +        return rc;
         7260  +      }
  7215   7261   
  7216   7262         /* Move the page currently at pgnoRoot to pgnoMove. */
  7217         -      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
         7263  +      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0, 0);
  7218   7264         if( rc!=SQLITE_OK ){
  7219   7265           return rc;
  7220   7266         }
  7221   7267         rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage);
  7222   7268         if( eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){
  7223   7269           rc = SQLITE_CORRUPT_BKPT;
  7224   7270         }
................................................................................
  7231   7277         rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove, 0);
  7232   7278         releasePage(pRoot);
  7233   7279   
  7234   7280         /* Obtain the page at pgnoRoot */
  7235   7281         if( rc!=SQLITE_OK ){
  7236   7282           return rc;
  7237   7283         }
  7238         -      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
         7284  +      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0, 0);
  7239   7285         if( rc!=SQLITE_OK ){
  7240   7286           return rc;
  7241   7287         }
  7242   7288         rc = sqlite3PagerWrite(pRoot->pDbPage);
  7243   7289         if( rc!=SQLITE_OK ){
  7244   7290           releasePage(pRoot);
  7245   7291           return rc;
................................................................................
  7307   7353     int i;
  7308   7354   
  7309   7355     assert( sqlite3_mutex_held(pBt->mutex) );
  7310   7356     if( pgno>btreePagecount(pBt) ){
  7311   7357       return SQLITE_CORRUPT_BKPT;
  7312   7358     }
  7313   7359   
  7314         -  rc = getAndInitPage(pBt, pgno, &pPage);
         7360  +  rc = getAndInitPage(pBt, pgno, &pPage, 0);
  7315   7361     if( rc ) return rc;
  7316   7362     for(i=0; i<pPage->nCell; i++){
  7317   7363       pCell = findCell(pPage, i);
  7318   7364       if( !pPage->leaf ){
  7319   7365         rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
  7320   7366         if( rc ) goto cleardatabasepage_out;
  7321   7367       }
................................................................................
  7409   7455     ** This error is caught long before control reaches this point.
  7410   7456     */
  7411   7457     if( NEVER(pBt->pCursor) ){
  7412   7458       sqlite3ConnectionBlocked(p->db, pBt->pCursor->pBtree->db);
  7413   7459       return SQLITE_LOCKED_SHAREDCACHE;
  7414   7460     }
  7415   7461   
  7416         -  rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
         7462  +  rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0, 0);
  7417   7463     if( rc ) return rc;
  7418   7464     rc = sqlite3BtreeClearTable(p, iTable, 0);
  7419   7465     if( rc ){
  7420   7466       releasePage(pPage);
  7421   7467       return rc;
  7422   7468     }
  7423   7469   
................................................................................
  7444   7490         }else{
  7445   7491           /* The table being dropped does not have the largest root-page
  7446   7492           ** number in the database. So move the page that does into the 
  7447   7493           ** gap left by the deleted root-page.
  7448   7494           */
  7449   7495           MemPage *pMove;
  7450   7496           releasePage(pPage);
  7451         -        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
         7497  +        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0, 0);
  7452   7498           if( rc!=SQLITE_OK ){
  7453   7499             return rc;
  7454   7500           }
  7455   7501           rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable, 0);
  7456   7502           releasePage(pMove);
  7457   7503           if( rc!=SQLITE_OK ){
  7458   7504             return rc;
  7459   7505           }
  7460   7506           pMove = 0;
  7461         -        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
         7507  +        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0, 0);
  7462   7508           freePage(pMove, &rc);
  7463   7509           releasePage(pMove);
  7464   7510           if( rc!=SQLITE_OK ){
  7465   7511             return rc;
  7466   7512           }
  7467   7513           *piMoved = maxRootPgno;
  7468   7514         }
................................................................................
  7866   7912   
  7867   7913     /* Check that the page exists
  7868   7914     */
  7869   7915     pBt = pCheck->pBt;
  7870   7916     usableSize = pBt->usableSize;
  7871   7917     if( iPage==0 ) return 0;
  7872   7918     if( checkRef(pCheck, iPage, zParentContext) ) return 0;
  7873         -  if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
         7919  +  if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0, 0))!=0 ){
  7874   7920       checkAppendMsg(pCheck, zContext,
  7875   7921          "unable to get the page. error code=%d", rc);
  7876   7922       return 0;
  7877   7923     }
  7878   7924   
  7879   7925     /* Clear MemPage.isInit to make sure the corruption detection code in
  7880   7926     ** btreeInitPage() is executed.  */
................................................................................
  8337   8383     if( rc!=SQLITE_OK ){
  8338   8384       return rc;
  8339   8385     }
  8340   8386     assert( pCsr->eState!=CURSOR_REQUIRESEEK );
  8341   8387     if( pCsr->eState!=CURSOR_VALID ){
  8342   8388       return SQLITE_ABORT;
  8343   8389     }
         8390  +
         8391  +  /* Save the positions of all other cursors open on this table. This is
         8392  +  ** required in case any of them are holding references to an xFetch
         8393  +  ** version of the b-tree page modified by the accessPayload call below.
         8394  +  **
         8395  +  ** Note that pCsr must be open on a BTREE_INTKEY table and saveCursorPosition()
         8396  +  ** and hence saveAllCursors() cannot fail on a BTREE_INTKEY table, hence
         8397  +  ** saveAllCursors can only return SQLITE_OK.
         8398  +  */
         8399  +  VVA_ONLY(rc =) saveAllCursors(pCsr->pBt, pCsr->pgnoRoot, pCsr);
         8400  +  assert( rc==SQLITE_OK );
  8344   8401   
  8345   8402     /* Check some assumptions: 
  8346   8403     **   (a) the cursor is open for writing,
  8347   8404     **   (b) there is a read/write transaction open,
  8348   8405     **   (c) the connection holds a write-lock on the table (if required),
  8349   8406     **   (d) there are no conflicting read-locks, and
  8350   8407     **   (e) the cursor points at a valid row of an intKey table.

Changes to src/btree.h.

    59     59   #define BTREE_OMIT_JOURNAL  1  /* Do not create or use a rollback journal */
    60     60   #define BTREE_MEMORY        2  /* This is an in-memory DB */
    61     61   #define BTREE_SINGLE        4  /* The file contains at most 1 b-tree */
    62     62   #define BTREE_UNORDERED     8  /* Use of a hash implementation is OK */
    63     63   
    64     64   int sqlite3BtreeClose(Btree*);
    65     65   int sqlite3BtreeSetCacheSize(Btree*,int);
           66  +int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
    66     67   int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
    67     68   int sqlite3BtreeSyncDisabled(Btree*);
    68     69   int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
    69     70   int sqlite3BtreeGetPageSize(Btree*);
    70     71   int sqlite3BtreeMaxPageCount(Btree*,int);
    71     72   u32 sqlite3BtreeLastPage(Btree*);
    72     73   int sqlite3BtreeSecureDelete(Btree*,int);
................................................................................
   135    136   #define BTREE_SCHEMA_VERSION      1
   136    137   #define BTREE_FILE_FORMAT         2
   137    138   #define BTREE_DEFAULT_CACHE_SIZE  3
   138    139   #define BTREE_LARGEST_ROOT_PAGE   4
   139    140   #define BTREE_TEXT_ENCODING       5
   140    141   #define BTREE_USER_VERSION        6
   141    142   #define BTREE_INCR_VACUUM         7
          143  +#define BTREE_APPLICATION_ID      8
   142    144   
   143    145   /*
   144    146   ** Values that may be OR'd together to form the second argument of an
   145    147   ** sqlite3BtreeCursorHints() call.
   146    148   */
   147    149   #define BTREE_BULKLOAD 0x00000001
   148    150   

Changes to src/build.c.

  2096   2096       );
  2097   2097     }
  2098   2098   #endif
  2099   2099   
  2100   2100     /* Drop all SQLITE_MASTER table and index entries that refer to the
  2101   2101     ** table. The program name loops through the master table and deletes
  2102   2102     ** every row that refers to a table of the same name as the one being
  2103         -  ** dropped. Triggers are handled seperately because a trigger can be
         2103  +  ** dropped. Triggers are handled separately because a trigger can be
  2104   2104     ** created in the temp database that refers to a table in another
  2105   2105     ** database.
  2106   2106     */
  2107   2107     sqlite3NestedParse(pParse, 
  2108   2108         "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
  2109   2109         pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);
  2110   2110     if( !isView && !IsVirtual(pTab) ){
................................................................................
  2388   2388     int iIdx = pParse->nTab++;     /* Btree cursor used for pIndex */
  2389   2389     int iSorter;                   /* Cursor opened by OpenSorter (if in use) */
  2390   2390     int addr1;                     /* Address of top of loop */
  2391   2391     int addr2;                     /* Address to jump to for next iteration */
  2392   2392     int tnum;                      /* Root page of index */
  2393   2393     Vdbe *v;                       /* Generate code into this virtual machine */
  2394   2394     KeyInfo *pKey;                 /* KeyInfo for index */
  2395         -#ifdef SQLITE_OMIT_MERGE_SORT
  2396         -  int regIdxKey;                 /* Registers containing the index key */
  2397         -#endif
  2398   2395     int regRecord;                 /* Register holding assemblied index record */
  2399   2396     sqlite3 *db = pParse->db;      /* The database connection */
  2400   2397     int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
  2401   2398   
  2402   2399   #ifndef SQLITE_OMIT_AUTHORIZATION
  2403   2400     if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,
  2404   2401         db->aDb[iDb].zName ) ){
................................................................................
  2418   2415       sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
  2419   2416     }
  2420   2417     pKey = sqlite3IndexKeyinfo(pParse, pIndex);
  2421   2418     sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, 
  2422   2419                       (char *)pKey, P4_KEYINFO_HANDOFF);
  2423   2420     sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
  2424   2421   
  2425         -#ifndef SQLITE_OMIT_MERGE_SORT
  2426   2422     /* Open the sorter cursor if we are to use one. */
  2427   2423     iSorter = pParse->nTab++;
  2428   2424     sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
  2429         -#else
  2430         -  iSorter = iTab;
  2431         -#endif
  2432   2425   
  2433   2426     /* Open the table. Loop through all rows of the table, inserting index
  2434   2427     ** records into the sorter. */
  2435   2428     sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
  2436   2429     addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
  2437   2430     regRecord = sqlite3GetTempReg(pParse);
  2438   2431   
  2439         -#ifndef SQLITE_OMIT_MERGE_SORT
  2440   2432     sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
  2441   2433     sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
  2442   2434     sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
  2443   2435     sqlite3VdbeJumpHere(v, addr1);
  2444   2436     addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0);
  2445   2437     if( pIndex->onError!=OE_None ){
  2446   2438       int j2 = sqlite3VdbeCurrentAddr(v) + 3;
................................................................................
  2452   2444       );
  2453   2445     }else{
  2454   2446       addr2 = sqlite3VdbeCurrentAddr(v);
  2455   2447     }
  2456   2448     sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord);
  2457   2449     sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
  2458   2450     sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
  2459         -#else
  2460         -  regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
  2461         -  addr2 = addr1 + 1;
  2462         -  if( pIndex->onError!=OE_None ){
  2463         -    const int regRowid = regIdxKey + pIndex->nColumn;
  2464         -    const int j2 = sqlite3VdbeCurrentAddr(v) + 2;
  2465         -    void * const pRegKey = SQLITE_INT_TO_PTR(regIdxKey);
  2466         -
  2467         -    /* The registers accessed by the OP_IsUnique opcode were allocated
  2468         -    ** using sqlite3GetTempRange() inside of the sqlite3GenerateIndexKey()
  2469         -    ** call above. Just before that function was freed they were released
  2470         -    ** (made available to the compiler for reuse) using 
  2471         -    ** sqlite3ReleaseTempRange(). So in some ways having the OP_IsUnique
  2472         -    ** opcode use the values stored within seems dangerous. However, since
  2473         -    ** we can be sure that no other temp registers have been allocated
  2474         -    ** since sqlite3ReleaseTempRange() was called, it is safe to do so.
  2475         -    */
  2476         -    sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, j2, regRowid, pRegKey, P4_INT32);
  2477         -    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
  2478         -        "indexed columns are not unique", P4_STATIC);
  2479         -  }
  2480         -  sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0);
  2481         -  sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
  2482         -#endif
  2483   2451     sqlite3ReleaseTempReg(pParse, regRecord);
  2484   2452     sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2);
  2485   2453     sqlite3VdbeJumpHere(v, addr1);
  2486   2454   
  2487   2455     sqlite3VdbeAddOp1(v, OP_Close, iTab);
  2488   2456     sqlite3VdbeAddOp1(v, OP_Close, iIdx);
  2489   2457     sqlite3VdbeAddOp1(v, OP_Close, iSorter);
................................................................................
  2835   2803         if( k==pIdx->nColumn ){
  2836   2804           if( pIdx->onError!=pIndex->onError ){
  2837   2805             /* This constraint creates the same index as a previous
  2838   2806             ** constraint specified somewhere in the CREATE TABLE statement.
  2839   2807             ** However the ON CONFLICT clauses are different. If both this 
  2840   2808             ** constraint and the previous equivalent constraint have explicit
  2841   2809             ** ON CONFLICT clauses this is an error. Otherwise, use the
  2842         -          ** explicitly specified behaviour for the index.
         2810  +          ** explicitly specified behavior for the index.
  2843   2811             */
  2844   2812             if( !(pIdx->onError==OE_Default || pIndex->onError==OE_Default) ){
  2845   2813               sqlite3ErrorMsg(pParse, 
  2846   2814                   "conflicting ON CONFLICT clauses specified", 0);
  2847   2815             }
  2848   2816             if( pIdx->onError==OE_Default ){
  2849   2817               pIdx->onError = pIndex->onError;

Changes to src/ctime.c.

    44     44   #endif
    45     45   #ifdef SQLITE_CHECK_PAGES
    46     46     "CHECK_PAGES",
    47     47   #endif
    48     48   #ifdef SQLITE_COVERAGE_TEST
    49     49     "COVERAGE_TEST",
    50     50   #endif
    51         -#ifdef SQLITE_CURDIR
    52         -  "CURDIR",
    53         -#endif
    54     51   #ifdef SQLITE_DEBUG
    55     52     "DEBUG",
    56     53   #endif
    57     54   #ifdef SQLITE_DEFAULT_LOCKING_MODE
    58     55     "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
           56  +#endif
           57  +#if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc)
           58  +  "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
    59     59   #endif
    60     60   #ifdef SQLITE_DISABLE_DIRSYNC
    61     61     "DISABLE_DIRSYNC",
    62     62   #endif
    63     63   #ifdef SQLITE_DISABLE_LFS
    64     64     "DISABLE_LFS",
    65     65   #endif
................................................................................
   143    143   #endif
   144    144   #ifdef SQLITE_INT64_TYPE
   145    145     "INT64_TYPE",
   146    146   #endif
   147    147   #ifdef SQLITE_LOCK_TRACE
   148    148     "LOCK_TRACE",
   149    149   #endif
          150  +#if defined(SQLITE_MAX_MMAP_SIZE) && !defined(SQLITE_MAX_MMAP_SIZE_xc)
          151  +  "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
          152  +#endif
   150    153   #ifdef SQLITE_MAX_SCHEMA_RETRY
   151    154     "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
   152    155   #endif
   153    156   #ifdef SQLITE_MEMDEBUG
   154    157     "MEMDEBUG",
   155    158   #endif
   156    159   #ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
................................................................................
   200    203   #endif
   201    204   #ifdef SQLITE_OMIT_CAST
   202    205     "OMIT_CAST",
   203    206   #endif
   204    207   #ifdef SQLITE_OMIT_CHECK
   205    208     "OMIT_CHECK",
   206    209   #endif
   207         -/* // redundant
   208         -** #ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS
   209         -**   "OMIT_COMPILEOPTION_DIAGS",
   210         -** #endif
   211         -*/
   212    210   #ifdef SQLITE_OMIT_COMPLETE
   213    211     "OMIT_COMPLETE",
   214    212   #endif
   215    213   #ifdef SQLITE_OMIT_COMPOUND_SELECT
   216    214     "OMIT_COMPOUND_SELECT",
   217    215   #endif
   218    216   #ifdef SQLITE_OMIT_DATETIME_FUNCS
................................................................................
   259    257   #endif
   260    258   #ifdef SQLITE_OMIT_LOOKASIDE
   261    259     "OMIT_LOOKASIDE",
   262    260   #endif
   263    261   #ifdef SQLITE_OMIT_MEMORYDB
   264    262     "OMIT_MEMORYDB",
   265    263   #endif
   266         -#ifdef SQLITE_OMIT_MERGE_SORT
   267         -  "OMIT_MERGE_SORT",
   268         -#endif
   269    264   #ifdef SQLITE_OMIT_OR_OPTIMIZATION
   270    265     "OMIT_OR_OPTIMIZATION",
   271    266   #endif
   272    267   #ifdef SQLITE_OMIT_PAGER_PRAGMAS
   273    268     "OMIT_PAGER_PRAGMAS",
   274    269   #endif
   275    270   #ifdef SQLITE_OMIT_PRAGMA
................................................................................
   349    344   #endif
   350    345   #ifdef SQLITE_SOUNDEX
   351    346     "SOUNDEX",
   352    347   #endif
   353    348   #ifdef SQLITE_TCL
   354    349     "TCL",
   355    350   #endif
   356         -#ifdef SQLITE_TEMP_STORE
          351  +#if defined(SQLITE_TEMP_STORE) && !defined(SQLITE_TEMP_STORE_xc)
   357    352     "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
   358    353   #endif
   359    354   #ifdef SQLITE_TEST
   360    355     "TEST",
   361    356   #endif
   362         -#ifdef SQLITE_THREADSAFE
          357  +#if defined(SQLITE_THREADSAFE)
   363    358     "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
   364    359   #endif
   365    360   #ifdef SQLITE_USE_ALLOCA
   366    361     "USE_ALLOCA",
   367    362   #endif
   368    363   #ifdef SQLITE_ZERO_MALLOC
   369    364     "ZERO_MALLOC"
................................................................................
   381    376     int i, n;
   382    377     if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
   383    378     n = sqlite3Strlen30(zOptName);
   384    379   
   385    380     /* Since ArraySize(azCompileOpt) is normally in single digits, a
   386    381     ** linear search is adequate.  No need for a binary search. */
   387    382     for(i=0; i<ArraySize(azCompileOpt); i++){
   388         -    if(   (sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0)
   389         -       && ( (azCompileOpt[i][n]==0) || (azCompileOpt[i][n]=='=') ) ) return 1;
          383  +    if( sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0
          384  +     && sqlite3CtypeMap[(unsigned char)azCompileOpt[i][n]]==0
          385  +    ){
          386  +      return 1;
          387  +    }
   390    388     }
   391    389     return 0;
   392    390   }
   393    391   
   394    392   /*
   395    393   ** Return the N-th compile-time option string.  If N is out of range,
   396    394   ** return a NULL pointer.

Changes to src/expr.c.

  1210   1210   static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){
  1211   1211     UNUSED_PARAMETER(NotUsed);
  1212   1212     pWalker->u.i = 0;
  1213   1213     return WRC_Abort;
  1214   1214   }
  1215   1215   static int exprIsConst(Expr *p, int initFlag){
  1216   1216     Walker w;
         1217  +  memset(&w, 0, sizeof(w));
  1217   1218     w.u.i = initFlag;
  1218   1219     w.xExprCallback = exprNodeIsConstant;
  1219   1220     w.xSelectCallback = selectNodeIsConstant;
  1220   1221     sqlite3WalkExpr(&w, p);
  1221   1222     return w.u.i;
  1222   1223   }
  1223   1224   
................................................................................
  3424   3425   ** obtained for queries regardless of whether or not constants are
  3425   3426   ** precomputed into registers or if they are inserted in-line.
  3426   3427   */
  3427   3428   void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){
  3428   3429     Walker w;
  3429   3430     if( pParse->cookieGoto ) return;
  3430   3431     if( OptimizationDisabled(pParse->db, SQLITE_FactorOutConst) ) return;
         3432  +  memset(&w, 0, sizeof(w));
  3431   3433     w.xExprCallback = evalConstExpr;
  3432         -  w.xSelectCallback = 0;
  3433   3434     w.pParse = pParse;
  3434   3435     sqlite3WalkExpr(&w, pExpr);
  3435   3436   }
  3436   3437   
  3437   3438   
  3438   3439   /*
  3439   3440   ** Generate code that pushes the value of every element of the given
................................................................................
  3538   3539     Vdbe *v = pParse->pVdbe;
  3539   3540     int op = 0;
  3540   3541     int regFree1 = 0;
  3541   3542     int regFree2 = 0;
  3542   3543     int r1, r2;
  3543   3544   
  3544   3545     assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
  3545         -  if( NEVER(v==0) )     return;  /* Existance of VDBE checked by caller */
         3546  +  if( NEVER(v==0) )     return;  /* Existence of VDBE checked by caller */
  3546   3547     if( NEVER(pExpr==0) ) return;  /* No way this can happen */
  3547   3548     op = pExpr->op;
  3548   3549     switch( op ){
  3549   3550       case TK_AND: {
  3550   3551         int d2 = sqlite3VdbeMakeLabel(v);
  3551   3552         testcase( jumpIfNull==0 );
  3552   3553         sqlite3ExprCachePush(pParse);
................................................................................
  3658   3659     Vdbe *v = pParse->pVdbe;
  3659   3660     int op = 0;
  3660   3661     int regFree1 = 0;
  3661   3662     int regFree2 = 0;
  3662   3663     int r1, r2;
  3663   3664   
  3664   3665     assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
  3665         -  if( NEVER(v==0) ) return; /* Existance of VDBE checked by caller */
         3666  +  if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */
  3666   3667     if( pExpr==0 )    return;
  3667   3668   
  3668   3669     /* The value of pExpr->op and op are related as follows:
  3669   3670     **
  3670   3671     **       pExpr->op            op
  3671   3672     **       ---------          ----------
  3672   3673     **       TK_ISNULL          OP_NotNull

Changes to src/func.c.

   691    691           return 0;
   692    692         }
   693    693         prevEscape = 0;
   694    694       }
   695    695     }
   696    696     return *zString==0;
   697    697   }
          698  +
          699  +/*
          700  +** The sqlite3_strglob() interface.
          701  +*/
          702  +int sqlite3_strglob(const char *zGlobPattern, const char *zString){
          703  +  return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, 0)==0;
          704  +}
   698    705   
   699    706   /*
   700    707   ** Count the number of times that the LIKE operator (or GLOB which is
   701    708   ** just a variation of LIKE) gets called.  This is used for testing
   702    709   ** only.
   703    710   */
   704    711   #ifdef SQLITE_TEST

Changes to src/global.c.

   152    152      500,                       /* nLookaside */
   153    153      {0,0,0,0,0,0,0,0},         /* m */
   154    154      {0,0,0,0,0,0,0,0,0},       /* mutex */
   155    155      {0,0,0,0,0,0,0,0,0,0,0,0,0},/* pcache2 */
   156    156      (void*)0,                  /* pHeap */
   157    157      0,                         /* nHeap */
   158    158      0, 0,                      /* mnHeap, mxHeap */
          159  +   SQLITE_DEFAULT_MMAP_SIZE,  /* szMmap */
          160  +   SQLITE_MAX_MMAP_SIZE,      /* mxMmap */
   159    161      (void*)0,                  /* pScratch */
   160    162      0,                         /* szScratch */
   161    163      0,                         /* nScratch */
   162    164      (void*)0,                  /* pPage */
   163    165      0,                         /* szPage */
   164    166      0,                         /* nPage */
   165    167      0,                         /* mxParserStack */

Changes to src/hash.h.

     5      5   ** a legal notice, here is a blessing:
     6      6   **
     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12         -** This is the header file for the generic hash-table implemenation
           12  +** This is the header file for the generic hash-table implementation
    13     13   ** used in SQLite.
    14     14   */
    15     15   #ifndef _SQLITE_HASH_H_
    16     16   #define _SQLITE_HASH_H_
    17     17   
    18     18   /* Forward declarations of structures. */
    19     19   typedef struct Hash Hash;

Changes to src/legacy.c.

    34     34     void *pArg,                 /* First argument to xCallback() */
    35     35     char **pzErrMsg             /* Write error messages here */
    36     36   ){
    37     37     int rc = SQLITE_OK;         /* Return code */
    38     38     const char *zLeftover;      /* Tail of unprocessed SQL */
    39     39     sqlite3_stmt *pStmt = 0;    /* The current SQL statement */
    40     40     char **azCols = 0;          /* Names of result columns */
    41         -  int nRetry = 0;             /* Number of retry attempts */
    42     41     int callbackIsInit;         /* True if callback data is initialized */
    43     42   
    44     43     if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
    45     44     if( zSql==0 ) zSql = "";
    46     45   
    47     46     sqlite3_mutex_enter(db->mutex);
    48     47     sqlite3Error(db, SQLITE_OK, 0);
    49         -  while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){
           48  +  while( rc==SQLITE_OK && zSql[0] ){
    50     49       int nCol;
    51     50       char **azVals = 0;
    52     51   
    53     52       pStmt = 0;
    54         -    rc = sqlite3_prepare(db, zSql, -1, &pStmt, &zLeftover);
           53  +    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
    55     54       assert( rc==SQLITE_OK || pStmt==0 );
    56     55       if( rc!=SQLITE_OK ){
    57     56         continue;
    58     57       }
    59     58       if( !pStmt ){
    60     59         /* this happens for a comment or white-space */
    61     60         zSql = zLeftover;
................................................................................
   104    103             goto exec_out;
   105    104           }
   106    105         }
   107    106   
   108    107         if( rc!=SQLITE_ROW ){
   109    108           rc = sqlite3VdbeFinalize((Vdbe *)pStmt);
   110    109           pStmt = 0;
   111         -        if( rc!=SQLITE_SCHEMA ){
   112         -          nRetry = 0;
   113         -          zSql = zLeftover;
   114         -          while( sqlite3Isspace(zSql[0]) ) zSql++;
   115         -        }
          110  +        zSql = zLeftover;
          111  +        while( sqlite3Isspace(zSql[0]) ) zSql++;
   116    112           break;
   117    113         }
   118    114       }
   119    115   
   120    116       sqlite3DbFree(db, azCols);
   121    117       azCols = 0;
   122    118     }

Changes to src/loadext.c.

   411    411     const char *zProc,    /* Entry point.  Use "sqlite3_extension_init" if 0 */
   412    412     char **pzErrMsg       /* Put error message here if not 0 */
   413    413   ){
   414    414     sqlite3_vfs *pVfs = db->pVfs;
   415    415     void *handle;
   416    416     int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
   417    417     char *zErrmsg = 0;
          418  +  const char *zEntry;
          419  +  char *zAltEntry = 0;
   418    420     void **aHandle;
   419    421     int nMsg = 300 + sqlite3Strlen30(zFile);
          422  +  int ii;
          423  +
          424  +  /* Shared library endings to try if zFile cannot be loaded as written */
          425  +  static const char *azEndings[] = {
          426  +#if SQLITE_OS_WIN
          427  +     "dll"   
          428  +#elif defined(__APPLE__)
          429  +     "dylib"
          430  +#else
          431  +     "so"
          432  +#endif
          433  +  };
          434  +
   420    435   
   421    436     if( pzErrMsg ) *pzErrMsg = 0;
   422    437   
   423    438     /* Ticket #1863.  To avoid a creating security problems for older
   424    439     ** applications that relink against newer versions of SQLite, the
   425    440     ** ability to run load_extension is turned off by default.  One
   426    441     ** must call sqlite3_enable_load_extension() to turn on extension
................................................................................
   429    444     if( (db->flags & SQLITE_LoadExtension)==0 ){
   430    445       if( pzErrMsg ){
   431    446         *pzErrMsg = sqlite3_mprintf("not authorized");
   432    447       }
   433    448       return SQLITE_ERROR;
   434    449     }
   435    450   
   436         -  if( zProc==0 ){
   437         -    zProc = "sqlite3_extension_init";
   438         -  }
          451  +  zEntry = zProc ? zProc : "sqlite3_extension_init";
   439    452   
   440    453     handle = sqlite3OsDlOpen(pVfs, zFile);
          454  +#if SQLITE_OS_UNIX || SQLITE_OS_WIN
          455  +  for(ii=0; ii<ArraySize(azEndings) && handle==0; ii++){
          456  +    char *zAltFile = sqlite3_mprintf("%s.%s", zFile, azEndings[ii]);
          457  +    if( zAltFile==0 ) return SQLITE_NOMEM;
          458  +    handle = sqlite3OsDlOpen(pVfs, zAltFile);
          459  +    sqlite3_free(zAltFile);
          460  +  }
          461  +#endif
   441    462     if( handle==0 ){
   442    463       if( pzErrMsg ){
   443    464         *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg);
   444    465         if( zErrmsg ){
   445    466           sqlite3_snprintf(nMsg, zErrmsg, 
   446    467               "unable to open shared library [%s]", zFile);
   447    468           sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
   448    469         }
   449    470       }
   450    471       return SQLITE_ERROR;
   451    472     }
   452    473     xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
   453         -                   sqlite3OsDlSym(pVfs, handle, zProc);
          474  +                   sqlite3OsDlSym(pVfs, handle, zEntry);
          475  +
          476  +  /* If no entry point was specified and the default legacy
          477  +  ** entry point name "sqlite3_extension_init" was not found, then
          478  +  ** construct an entry point name "sqlite3_X_init" where the X is
          479  +  ** replaced by the lowercase value of every ASCII alphabetic 
          480  +  ** character in the filename after the last "/" upto the first ".",
          481  +  ** and eliding the first three characters if they are "lib".  
          482  +  ** Examples:
          483  +  **
          484  +  **    /usr/local/lib/libExample5.4.3.so ==>  sqlite3_example_init
          485  +  **    C:/lib/mathfuncs.dll              ==>  sqlite3_mathfuncs_init
          486  +  */
          487  +  if( xInit==0 && zProc==0 ){
          488  +    int iFile, iEntry, c;
          489  +    int ncFile = sqlite3Strlen30(zFile);
          490  +    zAltEntry = sqlite3_malloc(ncFile+30);
          491  +    if( zAltEntry==0 ){
          492  +      sqlite3OsDlClose(pVfs, handle);
          493  +      return SQLITE_NOMEM;
          494  +    }
          495  +    memcpy(zAltEntry, "sqlite3_", 8);
          496  +    for(iFile=ncFile-1; iFile>=0 && zFile[iFile]!='/'; iFile--){}
          497  +    iFile++;
          498  +    if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3;
          499  +    for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){
          500  +      if( sqlite3Isalpha(c) ){
          501  +        zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c];
          502  +      }
          503  +    }
          504  +    memcpy(zAltEntry+iEntry, "_init", 6);
          505  +    zEntry = zAltEntry;
          506  +    xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
          507  +                     sqlite3OsDlSym(pVfs, handle, zEntry);
          508  +  }
   454    509     if( xInit==0 ){
   455    510       if( pzErrMsg ){
   456         -      nMsg += sqlite3Strlen30(zProc);
          511  +      nMsg += sqlite3Strlen30(zEntry);
   457    512         *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg);
   458    513         if( zErrmsg ){
   459    514           sqlite3_snprintf(nMsg, zErrmsg,
   460         -            "no entry point [%s] in shared library [%s]", zProc,zFile);
          515  +            "no entry point [%s] in shared library [%s]", zEntry, zFile);
   461    516           sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
   462    517         }
   463         -      sqlite3OsDlClose(pVfs, handle);
   464    518       }
          519  +    sqlite3OsDlClose(pVfs, handle);
          520  +    sqlite3_free(zAltEntry);
   465    521       return SQLITE_ERROR;
   466         -  }else if( xInit(db, &zErrmsg, &sqlite3Apis) ){
          522  +  }
          523  +  sqlite3_free(zAltEntry);
          524  +  if( xInit(db, &zErrmsg, &sqlite3Apis) ){
   467    525       if( pzErrMsg ){
   468    526         *pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg);
   469    527       }
   470    528       sqlite3_free(zErrmsg);
   471    529       sqlite3OsDlClose(pVfs, handle);
   472    530       return SQLITE_ERROR;
   473    531     }

Changes to src/main.c.

   491    491       case SQLITE_CONFIG_SQLLOG: {
   492    492         typedef void(*SQLLOGFUNC_t)(void*, sqlite3*, const char*, int);
   493    493         sqlite3GlobalConfig.xSqllog = va_arg(ap, SQLLOGFUNC_t);
   494    494         sqlite3GlobalConfig.pSqllogArg = va_arg(ap, void *);
   495    495         break;
   496    496       }
   497    497   #endif
          498  +
          499  +    case SQLITE_CONFIG_MMAP_SIZE: {
          500  +      sqlite3_int64 szMmap = va_arg(ap, sqlite3_int64);
          501  +      sqlite3_int64 mxMmap = va_arg(ap, sqlite3_int64);
          502  +      if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ){
          503  +        mxMmap = SQLITE_MAX_MMAP_SIZE;
          504  +      }
          505  +      sqlite3GlobalConfig.mxMmap = mxMmap;
          506  +      if( szMmap<0 ) szMmap = SQLITE_DEFAULT_MMAP_SIZE;
          507  +      if( szMmap>mxMmap) szMmap = mxMmap;
          508  +      sqlite3GlobalConfig.szMmap = szMmap;
          509  +      break;
          510  +    }
   498    511   
   499    512       default: {
   500    513         rc = SQLITE_ERROR;
   501    514         break;
   502    515       }
   503    516     }
   504    517     va_end(ap);
................................................................................
   881    894     if( db->magic!=SQLITE_MAGIC_ZOMBIE || connectionIsBusy(db) ){
   882    895       sqlite3_mutex_leave(db->mutex);
   883    896       return;
   884    897     }
   885    898   
   886    899     /* If we reach this point, it means that the database connection has
   887    900     ** closed all sqlite3_stmt and sqlite3_backup objects and has been
   888         -  ** pased to sqlite3_close (meaning that it is a zombie).  Therefore,
          901  +  ** passed to sqlite3_close (meaning that it is a zombie).  Therefore,
   889    902     ** go ahead and free all resources.
   890    903     */
   891    904   
   892    905     /* Free any outstanding Savepoint structures. */
   893    906     sqlite3CloseSavepoints(db);
   894    907   
   895    908     /* Close all database connections */
................................................................................
  1012   1025   
  1013   1026     /* If one has been configured, invoke the rollback-hook callback */
  1014   1027     if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
  1015   1028       db->xRollbackCallback(db->pRollbackArg);
  1016   1029     }
  1017   1030   }
  1018   1031   
         1032  +/*
         1033  +** Return a static string containing the name corresponding to the error code
         1034  +** specified in the argument.
         1035  +*/
         1036  +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) || \
         1037  +    defined(SQLITE_DEBUG_OS_TRACE)
         1038  +const char *sqlite3ErrName(int rc){
         1039  +  const char *zName = 0;
         1040  +  int i, origRc = rc;
         1041  +  for(i=0; i<2 && zName==0; i++, rc &= 0xff){
         1042  +    switch( rc ){
         1043  +      case SQLITE_OK:                 zName = "SQLITE_OK";                break;
         1044  +      case SQLITE_ERROR:              zName = "SQLITE_ERROR";             break;
         1045  +      case SQLITE_INTERNAL:           zName = "SQLITE_INTERNAL";          break;
         1046  +      case SQLITE_PERM:               zName = "SQLITE_PERM";              break;
         1047  +      case SQLITE_ABORT:              zName = "SQLITE_ABORT";             break;
         1048  +      case SQLITE_ABORT_ROLLBACK:     zName = "SQLITE_ABORT_ROLLBACK";    break;
         1049  +      case SQLITE_BUSY:               zName = "SQLITE_BUSY";              break;
         1050  +      case SQLITE_BUSY_RECOVERY:      zName = "SQLITE_BUSY_RECOVERY";     break;
         1051  +      case SQLITE_LOCKED:             zName = "SQLITE_LOCKED";            break;
         1052  +      case SQLITE_LOCKED_SHAREDCACHE: zName = "SQLITE_LOCKED_SHAREDCACHE";break;
         1053  +      case SQLITE_NOMEM:              zName = "SQLITE_NOMEM";             break;
         1054  +      case SQLITE_READONLY:           zName = "SQLITE_READONLY";          break;
         1055  +      case SQLITE_READONLY_RECOVERY:  zName = "SQLITE_READONLY_RECOVERY"; break;
         1056  +      case SQLITE_READONLY_CANTLOCK:  zName = "SQLITE_READONLY_CANTLOCK"; break;
         1057  +      case SQLITE_READONLY_ROLLBACK:  zName = "SQLITE_READONLY_ROLLBACK"; break;
         1058  +      case SQLITE_INTERRUPT:          zName = "SQLITE_INTERRUPT";         break;
         1059  +      case SQLITE_IOERR:              zName = "SQLITE_IOERR";             break;
         1060  +      case SQLITE_IOERR_READ:         zName = "SQLITE_IOERR_READ";        break;
         1061  +      case SQLITE_IOERR_SHORT_READ:   zName = "SQLITE_IOERR_SHORT_READ";  break;
         1062  +      case SQLITE_IOERR_WRITE:        zName = "SQLITE_IOERR_WRITE";       break;
         1063  +      case SQLITE_IOERR_FSYNC:        zName = "SQLITE_IOERR_FSYNC";       break;
         1064  +      case SQLITE_IOERR_DIR_FSYNC:    zName = "SQLITE_IOERR_DIR_FSYNC";   break;
         1065  +      case SQLITE_IOERR_TRUNCATE:     zName = "SQLITE_IOERR_TRUNCATE";    break;
         1066  +      case SQLITE_IOERR_FSTAT:        zName = "SQLITE_IOERR_FSTAT";       break;
         1067  +      case SQLITE_IOERR_UNLOCK:       zName = "SQLITE_IOERR_UNLOCK";      break;
         1068  +      case SQLITE_IOERR_RDLOCK:       zName = "SQLITE_IOERR_RDLOCK";      break;
         1069  +      case SQLITE_IOERR_DELETE:       zName = "SQLITE_IOERR_DELETE";      break;
         1070  +      case SQLITE_IOERR_BLOCKED:      zName = "SQLITE_IOERR_BLOCKED";     break;
         1071  +      case SQLITE_IOERR_NOMEM:        zName = "SQLITE_IOERR_NOMEM";       break;
         1072  +      case SQLITE_IOERR_ACCESS:       zName = "SQLITE_IOERR_ACCESS";      break;
         1073  +      case SQLITE_IOERR_CHECKRESERVEDLOCK:
         1074  +                                zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
         1075  +      case SQLITE_IOERR_LOCK:         zName = "SQLITE_IOERR_LOCK";        break;
         1076  +      case SQLITE_IOERR_CLOSE:        zName = "SQLITE_IOERR_CLOSE";       break;
         1077  +      case SQLITE_IOERR_DIR_CLOSE:    zName = "SQLITE_IOERR_DIR_CLOSE";   break;
         1078  +      case SQLITE_IOERR_SHMOPEN:      zName = "SQLITE_IOERR_SHMOPEN";     break;
         1079  +      case SQLITE_IOERR_SHMSIZE:      zName = "SQLITE_IOERR_SHMSIZE";     break;
         1080  +      case SQLITE_IOERR_SHMLOCK:      zName = "SQLITE_IOERR_SHMLOCK";     break;
         1081  +      case SQLITE_IOERR_SHMMAP:       zName = "SQLITE_IOERR_SHMMAP";      break;
         1082  +      case SQLITE_IOERR_SEEK:         zName = "SQLITE_IOERR_SEEK";        break;
         1083  +      case SQLITE_IOERR_DELETE_NOENT: zName = "SQLITE_IOERR_DELETE_NOENT";break;
         1084  +      case SQLITE_IOERR_MMAP:         zName = "SQLITE_IOERR_MMAP";        break;
         1085  +      case SQLITE_CORRUPT:            zName = "SQLITE_CORRUPT";           break;
         1086  +      case SQLITE_CORRUPT_VTAB:       zName = "SQLITE_CORRUPT_VTAB";      break;
         1087  +      case SQLITE_NOTFOUND:           zName = "SQLITE_NOTFOUND";          break;
         1088  +      case SQLITE_FULL:               zName = "SQLITE_FULL";              break;
         1089  +      case SQLITE_CANTOPEN:           zName = "SQLITE_CANTOPEN";          break;
         1090  +      case SQLITE_CANTOPEN_NOTEMPDIR: zName = "SQLITE_CANTOPEN_NOTEMPDIR";break;
         1091  +      case SQLITE_CANTOPEN_ISDIR:     zName = "SQLITE_CANTOPEN_ISDIR";    break;
         1092  +      case SQLITE_CANTOPEN_FULLPATH:  zName = "SQLITE_CANTOPEN_FULLPATH"; break;
         1093  +      case SQLITE_PROTOCOL:           zName = "SQLITE_PROTOCOL";          break;
         1094  +      case SQLITE_EMPTY:              zName = "SQLITE_EMPTY";             break;
         1095  +      case SQLITE_SCHEMA:             zName = "SQLITE_SCHEMA";            break;
         1096  +      case SQLITE_TOOBIG:             zName = "SQLITE_TOOBIG";            break;
         1097  +      case SQLITE_CONSTRAINT:         zName = "SQLITE_CONSTRAINT";        break;
         1098  +      case SQLITE_CONSTRAINT_UNIQUE:  zName = "SQLITE_CONSTRAINT_UNIQUE"; break;
         1099  +      case SQLITE_CONSTRAINT_TRIGGER: zName = "SQLITE_CONSTRAINT_TRIGGER";break;
         1100  +      case SQLITE_CONSTRAINT_FOREIGNKEY:
         1101  +                                zName = "SQLITE_CONSTRAINT_FOREIGNKEY";   break;
         1102  +      case SQLITE_CONSTRAINT_CHECK:   zName = "SQLITE_CONSTRAINT_CHECK";  break;
         1103  +      case SQLITE_CONSTRAINT_PRIMARYKEY:
         1104  +                                zName = "SQLITE_CONSTRAINT_PRIMARYKEY";   break;
         1105  +      case SQLITE_CONSTRAINT_NOTNULL: zName = "SQLITE_CONSTRAINT_NOTNULL";break;
         1106  +      case SQLITE_CONSTRAINT_COMMITHOOK:
         1107  +                                zName = "SQLITE_CONSTRAINT_COMMITHOOK";   break;
         1108  +      case SQLITE_CONSTRAINT_VTAB:    zName = "SQLITE_CONSTRAINT_VTAB";   break;
         1109  +      case SQLITE_CONSTRAINT_FUNCTION:
         1110  +                                zName = "SQLITE_CONSTRAINT_FUNCTION";     break;
         1111  +      case SQLITE_MISMATCH:           zName = "SQLITE_MISMATCH";          break;
         1112  +      case SQLITE_MISUSE:             zName = "SQLITE_MISUSE";            break;
         1113  +      case SQLITE_NOLFS:              zName = "SQLITE_NOLFS";             break;
         1114  +      case SQLITE_AUTH:               zName = "SQLITE_AUTH";              break;
         1115  +      case SQLITE_FORMAT:             zName = "SQLITE_FORMAT";            break;
         1116  +      case SQLITE_RANGE:              zName = "SQLITE_RANGE";             break;
         1117  +      case SQLITE_NOTADB:             zName = "SQLITE_NOTADB";            break;
         1118  +      case SQLITE_ROW:                zName = "SQLITE_ROW";               break;
         1119  +      case SQLITE_NOTICE:             zName = "SQLITE_NOTICE";            break;
         1120  +      case SQLITE_NOTICE_RECOVER_WAL: zName = "SQLITE_NOTICE_RECOVER_WAL";break;
         1121  +      case SQLITE_NOTICE_RECOVER_ROLLBACK:
         1122  +                                zName = "SQLITE_NOTICE_RECOVER_ROLLBACK"; break;
         1123  +      case SQLITE_WARNING:            zName = "SQLITE_WARNING";           break;
         1124  +      case SQLITE_DONE:               zName = "SQLITE_DONE";              break;
         1125  +    }
         1126  +  }
         1127  +  if( zName==0 ){
         1128  +    static char zBuf[50];
         1129  +    sqlite3_snprintf(sizeof(zBuf), zBuf, "SQLITE_UNKNOWN(%d)", origRc);
         1130  +    zName = zBuf;
         1131  +  }
         1132  +  return zName;
         1133  +}
         1134  +#endif
         1135  +
  1019   1136   /*
  1020   1137   ** Return a static string that describes the kind of error specified in the
  1021   1138   ** argument.
  1022   1139   */
  1023   1140   const char *sqlite3ErrStr(int rc){
  1024   1141     static const char* const aMsg[] = {
  1025   1142       /* SQLITE_OK          */ "not an error",
................................................................................
  2312   2429     db->magic = SQLITE_MAGIC_BUSY;
  2313   2430     db->aDb = db->aDbStatic;
  2314   2431   
  2315   2432     assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
  2316   2433     memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
  2317   2434     db->autoCommit = 1;
  2318   2435     db->nextAutovac = -1;
         2436  +  db->szMmap = sqlite3GlobalConfig.szMmap;
  2319   2437     db->nextPagesize = 0;
  2320   2438     db->flags |= SQLITE_ShortColNames | SQLITE_AutoIndex | SQLITE_EnableTrigger
  2321   2439   #if SQLITE_DEFAULT_FILE_FORMAT<4
  2322   2440                    | SQLITE_LegacyFileFmt
  2323   2441   #endif
  2324   2442   #ifdef SQLITE_ENABLE_LOAD_EXTENSION
  2325   2443                    | SQLITE_LoadExtension

Changes to src/memjournal.c.

   226    226     0,                /* xCheckReservedLock */
   227    227     0,                /* xFileControl */
   228    228     0,                /* xSectorSize */
   229    229     0,                /* xDeviceCharacteristics */
   230    230     0,                /* xShmMap */
   231    231     0,                /* xShmLock */
   232    232     0,                /* xShmBarrier */
   233         -  0                 /* xShmUnlock */
          233  +  0,                /* xShmUnmap */
          234  +  0,                /* xFetch */
          235  +  0                 /* xUnfetch */
   234    236   };
   235    237   
   236    238   /* 
   237    239   ** Open a journal file.
   238    240   */
   239    241   void sqlite3MemJournalOpen(sqlite3_file *pJfd){
   240    242     MemJournal *p = (MemJournal *)pJfd;

Changes to src/os.c.

   136    136     int pgsz,
   137    137     int bExtend,                    /* True to extend file if necessary */
   138    138     void volatile **pp              /* OUT: Pointer to mapping */
   139    139   ){
   140    140     DO_OS_MALLOC_TEST(id);
   141    141     return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
   142    142   }
          143  +
          144  +#if SQLITE_MAX_MMAP_SIZE>0
          145  +/* The real implementation of xFetch and xUnfetch */
          146  +int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
          147  +  DO_OS_MALLOC_TEST(id);
          148  +  return id->pMethods->xFetch(id, iOff, iAmt, pp);
          149  +}
          150  +int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
          151  +  return id->pMethods->xUnfetch(id, iOff, p);
          152  +}
          153  +#else
          154  +/* No-op stubs to use when memory-mapped I/O is disabled */
          155  +int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
          156  +  *pp = 0;
          157  +  return SQLITE_OK;
          158  +}
          159  +int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
          160  +  return SQLITE_OK;
          161  +}
          162  +#endif
   143    163   
   144    164   /*
   145    165   ** The next group of routines are convenience wrappers around the
   146    166   ** VFS methods.
   147    167   */
   148    168   int sqlite3OsOpen(
   149    169     sqlite3_vfs *pVfs, 

Changes to src/os.h.

    95     95   ** Determine if we are dealing with WinRT, which provides only a subset of
    96     96   ** the full Win32 API.
    97     97   */
    98     98   #if !defined(SQLITE_OS_WINRT)
    99     99   # define SQLITE_OS_WINRT 0
   100    100   #endif
   101    101   
   102         -/*
   103         -** When compiled for WinCE or WinRT, there is no concept of the current
   104         -** directory.
   105         - */
   106         -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
   107         -# define SQLITE_CURDIR 1
   108         -#endif
   109         -
   110    102   /* If the SET_FULLSYNC macro is not defined above, then make it
   111    103   ** a no-op
   112    104   */
   113    105   #ifndef SET_FULLSYNC
   114    106   # define SET_FULLSYNC(x,y)
   115    107   #endif
   116    108   
................................................................................
   255    247   #define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
   256    248   int sqlite3OsSectorSize(sqlite3_file *id);
   257    249   int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
   258    250   int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **);
   259    251   int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
   260    252   void sqlite3OsShmBarrier(sqlite3_file *id);
   261    253   int sqlite3OsShmUnmap(sqlite3_file *id, int);
          254  +int sqlite3OsFetch(sqlite3_file *id, i64, int, void **);
          255  +int sqlite3OsUnfetch(sqlite3_file *, i64, void *);
   262    256   
   263    257   
   264    258   /* 
   265    259   ** Functions for accessing sqlite3_vfs methods 
   266    260   */
   267    261   int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *);
   268    262   int sqlite3OsDelete(sqlite3_vfs *, const char *, int);

Changes to src/os_unix.c.

   122    122   #include <sys/types.h>
   123    123   #include <sys/stat.h>
   124    124   #include <fcntl.h>
   125    125   #include <unistd.h>
   126    126   #include <time.h>
   127    127   #include <sys/time.h>
   128    128   #include <errno.h>
   129         -#ifndef SQLITE_OMIT_WAL
          129  +#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
   130    130   #include <sys/mman.h>
   131    131   #endif
   132    132   
   133    133   
   134    134   #if SQLITE_ENABLE_LOCKING_STYLE
   135    135   # include <sys/ioctl.h>
   136    136   # if OS_VXWORKS
................................................................................
   221    221     unsigned short int ctrlFlags;       /* Behavioral bits.  UNIXFILE_* flags */
   222    222     int lastErrno;                      /* The unix errno from last I/O error */
   223    223     void *lockingContext;               /* Locking style specific state */
   224    224     UnixUnusedFd *pUnused;              /* Pre-allocated UnixUnusedFd */
   225    225     const char *zPath;                  /* Name of the file */
   226    226     unixShm *pShm;                      /* Shared memory segment information */
   227    227     int szChunk;                        /* Configured by FCNTL_CHUNK_SIZE */
          228  +  int nFetchOut;                      /* Number of outstanding xFetch refs */
          229  +  sqlite3_int64 mmapSize;             /* Usable size of mapping at pMapRegion */
          230  +  sqlite3_int64 mmapSizeActual;       /* Actual size of mapping at pMapRegion */
          231  +  sqlite3_int64 mmapSizeMax;          /* Configured FCNTL_MMAP_SIZE value */
          232  +  void *pMapRegion;                   /* Memory mapped region */
   228    233   #ifdef __QNXNTO__
   229    234     int sectorSize;                     /* Device sector size */
   230    235     int deviceCharacteristics;          /* Precomputed device characteristics */
   231    236   #endif
   232    237   #if SQLITE_ENABLE_LOCKING_STYLE
   233    238     int openFlags;                      /* The flags specified at open() */
   234    239   #endif
................................................................................
   245    250     ** occur if a file is updated without also updating the transaction
   246    251     ** counter.  This test is made to avoid new problems similar to the
   247    252     ** one described by ticket #3584. 
   248    253     */
   249    254     unsigned char transCntrChng;   /* True if the transaction counter changed */
   250    255     unsigned char dbUpdate;        /* True if any part of database file changed */
   251    256     unsigned char inNormalWrite;   /* True if in a normal write operation */
          257  +
   252    258   #endif
          259  +
   253    260   #ifdef SQLITE_TEST
   254    261     /* In test mode, increase the size of this structure a bit so that 
   255    262     ** it is larger than the struct CrashFile defined in test6.c.
   256    263     */
   257    264     char aPadding[32];
   258    265   #endif
   259    266   };
................................................................................
   269    276   #else
   270    277   # define UNIXFILE_DIRSYNC    0x00
   271    278   #endif
   272    279   #define UNIXFILE_PSOW        0x10     /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
   273    280   #define UNIXFILE_DELETE      0x20     /* Delete on close */
   274    281   #define UNIXFILE_URI         0x40     /* Filename might have query parameters */
   275    282   #define UNIXFILE_NOLOCK      0x80     /* Do no file locking */
          283  +#define UNIXFILE_WARNED    0x0100     /* verifyDbFile() warnings have been issued */
   276    284   
   277    285   /*
   278    286   ** Include code that is common to all os_*.c files
   279    287   */
   280    288   #include "os_common.h"
   281    289   
   282    290   /*
................................................................................
   302    310   */
   303    311   #if SQLITE_THREADSAFE
   304    312   #define threadid pthread_self()
   305    313   #else
   306    314   #define threadid 0
   307    315   #endif
   308    316   
          317  +/*
          318  +** HAVE_MREMAP defaults to true on Linux and false everywhere else.
          319  +*/
          320  +#if !defined(HAVE_MREMAP)
          321  +# if defined(__linux__) && defined(_GNU_SOURCE)
          322  +#  define HAVE_MREMAP 1
          323  +# else
          324  +#  define HAVE_MREMAP 0
          325  +# endif
          326  +#endif
          327  +
   309    328   /*
   310    329   ** Different Unix systems declare open() in different ways.  Same use
   311    330   ** open(const char*,int,mode_t).  Others use open(const char*,int,...).
   312    331   ** The difference is important when using a pointer to the function.
   313    332   **
   314    333   ** The safest way to deal with the problem is to always use this wrapper
   315    334   ** which always has the same well-defined interface.
................................................................................
   333    352   /*
   334    353   ** Many system calls are accessed through pointer-to-functions so that
   335    354   ** they may be overridden at runtime to facilitate fault injection during
   336    355   ** testing and sandboxing.  The following array holds the names and pointers
   337    356   ** to all overrideable system calls.
   338    357   */
   339    358   static struct unix_syscall {
   340         -  const char *zName;            /* Name of the sytem call */
          359  +  const char *zName;            /* Name of the system call */
   341    360     sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
   342    361     sqlite3_syscall_ptr pDefault; /* Default value */
   343    362   } aSyscall[] = {
   344    363     { "open",         (sqlite3_syscall_ptr)posixOpen,  0  },
   345    364   #define osOpen      ((int(*)(const char*,int,int))aSyscall[0].pCurrent)
   346    365   
   347    366     { "close",        (sqlite3_syscall_ptr)close,      0  },
................................................................................
   433    452   
   434    453     { "rmdir",        (sqlite3_syscall_ptr)rmdir,           0 },
   435    454   #define osRmdir     ((int(*)(const char*))aSyscall[19].pCurrent)
   436    455   
   437    456     { "fchown",       (sqlite3_syscall_ptr)posixFchown,     0 },
   438    457   #define osFchown    ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
   439    458   
          459  +  { "mmap",       (sqlite3_syscall_ptr)mmap,     0 },
          460  +#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[21].pCurrent)
          461  +
          462  +  { "munmap",       (sqlite3_syscall_ptr)munmap,          0 },
          463  +#define osMunmap ((void*(*)(void*,size_t))aSyscall[22].pCurrent)
          464  +
          465  +#if HAVE_MREMAP
          466  +  { "mremap",       (sqlite3_syscall_ptr)mremap,          0 },
          467  +#else
          468  +  { "mremap",       (sqlite3_syscall_ptr)0,               0 },
          469  +#endif
          470  +#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent)
          471  +
   440    472   }; /* End of the overrideable system calls */
   441    473   
   442    474   /*
   443    475   ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
   444    476   ** "unix" VFSes.  Return SQLITE_OK opon successfully updating the
   445    477   ** system call pointer, or SQLITE_NOTFOUND if there is no configurable
   446    478   ** system call named zName.
................................................................................
   762    794     case ENOSYS:
   763    795       /* these should force the client to close the file and reconnect */
   764    796       
   765    797     default: 
   766    798       return sqliteIOErr;
   767    799     }
   768    800   }
   769         -
   770    801   
   771    802   
   772    803   /******************************************************************************
   773    804   ****************** Begin Unique File ID Utility Used By VxWorks ***************
   774    805   **
   775    806   ** On most versions of unix, we can get a unique ID for a file by concatenating
   776    807   ** the device number and the inode number.  But this does not work on VxWorks.
................................................................................
  1100   1131     /* This is a threadsafe build, but strerror_r() is not available. */
  1101   1132     zErr = "";
  1102   1133   #else
  1103   1134     /* Non-threadsafe build, use strerror(). */
  1104   1135     zErr = strerror(iErrno);
  1105   1136   #endif
  1106   1137   
  1107         -  assert( errcode!=SQLITE_OK );
  1108   1138     if( zPath==0 ) zPath = "";
  1109   1139     sqlite3_log(errcode,
  1110   1140         "os_unix.c:%d: (%d) %s(%s) - %s",
  1111   1141         iLine, iErrno, zFunc, zPath, zErr
  1112   1142     );
  1113   1143   
  1114   1144     return errcode;
................................................................................
  1265   1295     }else{
  1266   1296       pInode->nRef++;
  1267   1297     }
  1268   1298     *ppInode = pInode;
  1269   1299     return SQLITE_OK;
  1270   1300   }
  1271   1301   
         1302  +
         1303  +/*
         1304  +** Check a unixFile that is a database.  Verify the following:
         1305  +**
         1306  +** (1) There is exactly one hard link on the file
         1307  +** (2) The file is not a symbolic link
         1308  +** (3) The file has not been renamed or unlinked
         1309  +**
         1310  +** Issue sqlite3_log(SQLITE_WARNING,...) messages if anything is not right.
         1311  +*/
         1312  +static void verifyDbFile(unixFile *pFile){
         1313  +  struct stat buf;
         1314  +  int rc;
         1315  +  if( pFile->ctrlFlags & UNIXFILE_WARNED ){
         1316  +    /* One or more of the following warnings have already been issued.  Do not
         1317  +    ** repeat them so as not to clutter the error log */
         1318  +    return;
         1319  +  }
         1320  +  rc = osFstat(pFile->h, &buf);
         1321  +  if( rc!=0 ){
         1322  +    sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s", pFile->zPath);
         1323  +    pFile->ctrlFlags |= UNIXFILE_WARNED;
         1324  +    return;
         1325  +  }
         1326  +  if( buf.st_nlink==0 && (pFile->ctrlFlags & UNIXFILE_DELETE)==0 ){
         1327  +    sqlite3_log(SQLITE_WARNING, "file unlinked while open: %s", pFile->zPath);
         1328  +    pFile->ctrlFlags |= UNIXFILE_WARNED;
         1329  +    return;
         1330  +  }
         1331  +  if( buf.st_nlink>1 ){
         1332  +    sqlite3_log(SQLITE_WARNING, "multiple links to file: %s", pFile->zPath);
         1333  +    pFile->ctrlFlags |= UNIXFILE_WARNED;
         1334  +    return;
         1335  +  }
         1336  +  if( pFile->pInode!=0
         1337  +   && ((rc = osStat(pFile->zPath, &buf))!=0
         1338  +       || buf.st_ino!=pFile->pInode->fileId.ino)
         1339  +  ){
         1340  +    sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath);
         1341  +    pFile->ctrlFlags |= UNIXFILE_WARNED;
         1342  +    return;
         1343  +  }
         1344  +}
         1345  +
  1272   1346   
  1273   1347   /*
  1274   1348   ** This routine checks if there is a RESERVED lock held on the specified
  1275   1349   ** file by this or any other process. If such a lock is held, set *pResOut
  1276   1350   ** to a non-zero value otherwise *pResOut is set to zero.  The return value
  1277   1351   ** is set to SQLITE_OK unless an I/O error occurs during lock checking.
  1278   1352   */
................................................................................
  1796   1870   ** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
  1797   1871   ** must be either NO_LOCK or SHARED_LOCK.
  1798   1872   **
  1799   1873   ** If the locking level of the file descriptor is already at or below
  1800   1874   ** the requested locking level, this routine is a no-op.
  1801   1875   */
  1802   1876   static int unixUnlock(sqlite3_file *id, int eFileLock){
         1877  +  assert( eFileLock==SHARED_LOCK || ((unixFile *)id)->nFetchOut==0 );
  1803   1878     return posixUnlock(id, eFileLock, 0);
  1804   1879   }
         1880  +
         1881  +static int unixMapfile(unixFile *pFd, i64 nByte);
         1882  +static void unixUnmapfile(unixFile *pFd);
  1805   1883   
  1806   1884   /*
  1807   1885   ** This function performs the parts of the "close file" operation 
  1808   1886   ** common to all locking schemes. It closes the directory and file
  1809   1887   ** handles, if they are valid, and sets all fields of the unixFile
  1810   1888   ** structure to 0.
  1811   1889   **
  1812   1890   ** It is *not* necessary to hold the mutex when this routine is called,
  1813   1891   ** even on VxWorks.  A mutex will be acquired on VxWorks by the
  1814   1892   ** vxworksReleaseFileId() routine.
  1815   1893   */
  1816   1894   static int closeUnixFile(sqlite3_file *id){
  1817   1895     unixFile *pFile = (unixFile*)id;
         1896  +  unixUnmapfile(pFile);
  1818   1897     if( pFile->h>=0 ){
  1819   1898       robust_close(pFile, pFile->h, __LINE__);
  1820   1899       pFile->h = -1;
  1821   1900     }
  1822   1901   #if OS_VXWORKS
  1823   1902     if( pFile->pId ){
  1824   1903       if( pFile->ctrlFlags & UNIXFILE_DELETE ){
................................................................................
  1837   1916   
  1838   1917   /*
  1839   1918   ** Close a file.
  1840   1919   */
  1841   1920   static int unixClose(sqlite3_file *id){
  1842   1921     int rc = SQLITE_OK;
  1843   1922     unixFile *pFile = (unixFile *)id;
         1923  +  verifyDbFile(pFile);
  1844   1924     unixUnlock(id, NO_LOCK);
  1845   1925     unixEnterMutex();
  1846   1926   
  1847   1927     /* unixFile.pInode is always valid here. Otherwise, a different close
  1848   1928     ** routine (e.g. nolockClose()) would be called instead.
  1849   1929     */
  1850   1930     assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 );
................................................................................
  1905   1985   
  1906   1986   /******************* End of the no-op lock implementation *********************
  1907   1987   ******************************************************************************/
  1908   1988   
  1909   1989   /******************************************************************************
  1910   1990   ************************* Begin dot-file Locking ******************************
  1911   1991   **
  1912         -** The dotfile locking implementation uses the existance of separate lock
         1992  +** The dotfile locking implementation uses the existence of separate lock
  1913   1993   ** files (really a directory) to control access to the database.  This works
  1914   1994   ** on just about every filesystem imaginable.  But there are serious downsides:
  1915   1995   **
  1916   1996   **    (1)  There is zero concurrency.  A single reader blocks all other
  1917   1997   **         connections from reading or writing the database.
  1918   1998   **
  1919   1999   **    (2)  An application crash or power loss can leave stale lock files
................................................................................
  1920   2000   **         sitting around that need to be cleared manually.
  1921   2001   **
  1922   2002   ** Nevertheless, a dotlock is an appropriate locking mode for use if no
  1923   2003   ** other locking strategy is available.
  1924   2004   **
  1925   2005   ** Dotfile locking works by creating a subdirectory in the same directory as
  1926   2006   ** the database and with the same name but with a ".lock" extension added.
  1927         -** The existance of a lock directory implies an EXCLUSIVE lock.  All other
         2007  +** The existence of a lock directory implies an EXCLUSIVE lock.  All other
  1928   2008   ** lock types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
  1929   2009   */
  1930   2010   
  1931   2011   /*
  1932   2012   ** The file suffix added to the data base filename in order to create the
  1933   2013   ** lock directory.
  1934   2014   */
................................................................................
  3068   3148     void *pBuf, 
  3069   3149     int amt,
  3070   3150     sqlite3_int64 offset
  3071   3151   ){
  3072   3152     unixFile *pFile = (unixFile *)id;
  3073   3153     int got;
  3074   3154     assert( id );
         3155  +  assert( offset>=0 );
         3156  +  assert( amt>0 );
  3075   3157   
  3076   3158     /* If this is a database file (not a journal, master-journal or temp
  3077   3159     ** file), the bytes in the locking range should never be read or written. */
  3078   3160   #if 0
  3079   3161     assert( pFile->pUnused==0
  3080   3162          || offset>=PENDING_BYTE+512
  3081   3163          || offset+amt<=PENDING_BYTE 
  3082   3164     );
  3083   3165   #endif
         3166  +
         3167  +#if SQLITE_MAX_MMAP_SIZE>0
         3168  +  /* Deal with as much of this read request as possible by transfering
         3169  +  ** data from the memory mapping using memcpy().  */
         3170  +  if( offset<pFile->mmapSize ){
         3171  +    if( offset+amt <= pFile->mmapSize ){
         3172  +      memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
         3173  +      return SQLITE_OK;
         3174  +    }else{
         3175  +      int nCopy = pFile->mmapSize - offset;
         3176  +      memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy);
         3177  +      pBuf = &((u8 *)pBuf)[nCopy];
         3178  +      amt -= nCopy;
         3179  +      offset += nCopy;
         3180  +    }
         3181  +  }
         3182  +#endif
  3084   3183   
  3085   3184     got = seekAndRead(pFile, offset, pBuf, amt);
  3086   3185     if( got==amt ){
  3087   3186       return SQLITE_OK;
  3088   3187     }else if( got<0 ){
  3089   3188       /* lastErrno set by seekAndRead */
  3090   3189       return SQLITE_IOERR_READ;
................................................................................
  3091   3190     }else{
  3092   3191       pFile->lastErrno = 0; /* not a system error */
  3093   3192       /* Unread parts of the buffer must be zero-filled */
  3094   3193       memset(&((char*)pBuf)[got], 0, amt-got);
  3095   3194       return SQLITE_IOERR_SHORT_READ;
  3096   3195     }
  3097   3196   }
         3197  +
         3198  +/*
         3199  +** Attempt to seek the file-descriptor passed as the first argument to
         3200  +** absolute offset iOff, then attempt to write nBuf bytes of data from
         3201  +** pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise, 
         3202  +** return the actual number of bytes written (which may be less than
         3203  +** nBuf).
         3204  +*/
         3205  +static int seekAndWriteFd(
         3206  +  int fd,                         /* File descriptor to write to */
         3207  +  i64 iOff,                       /* File offset to begin writing at */
         3208  +  const void *pBuf,               /* Copy data from this buffer to the file */
         3209  +  int nBuf,                       /* Size of buffer pBuf in bytes */
         3210  +  int *piErrno                    /* OUT: Error number if error occurs */
         3211  +){
         3212  +  int rc = 0;                     /* Value returned by system call */
         3213  +
         3214  +  assert( nBuf==(nBuf&0x1ffff) );
         3215  +  nBuf &= 0x1ffff;
         3216  +  TIMER_START;
         3217  +
         3218  +#if defined(USE_PREAD)
         3219  +  do{ rc = osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR );
         3220  +#elif defined(USE_PREAD64)
         3221  +  do{ rc = osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR);
         3222  +#else
         3223  +  do{
         3224  +    i64 iSeek = lseek(fd, iOff, SEEK_SET);
         3225  +    SimulateIOError( iSeek-- );
         3226  +
         3227  +    if( iSeek!=iOff ){
         3228  +      if( piErrno ) *piErrno = (iSeek==-1 ? errno : 0);
         3229  +      return -1;
         3230  +    }
         3231  +    rc = osWrite(fd, pBuf, nBuf);
         3232  +  }while( rc<0 && errno==EINTR );
         3233  +#endif
         3234  +
         3235  +  TIMER_END;
         3236  +  OSTRACE(("WRITE   %-3d %5d %7lld %llu\n", fd, rc, iOff, TIMER_ELAPSED));
         3237  +
         3238  +  if( rc<0 && piErrno ) *piErrno = errno;
         3239  +  return rc;
         3240  +}
         3241  +
  3098   3242   
  3099   3243   /*
  3100   3244   ** Seek to the offset in id->offset then read cnt bytes into pBuf.
  3101   3245   ** Return the number of bytes actually read.  Update the offset.
  3102   3246   **
  3103   3247   ** To avoid stomping the errno value on a failed write the lastErrno value
  3104   3248   ** is set before returning.
  3105   3249   */
  3106   3250   static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
  3107         -  int got;
  3108         -#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
  3109         -  i64 newOffset;
  3110         -#endif
  3111         -  assert( cnt==(cnt&0x1ffff) );
  3112         -  cnt &= 0x1ffff;
  3113         -  TIMER_START;
  3114         -#if defined(USE_PREAD)
  3115         -  do{ got = osPwrite(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR );
  3116         -#elif defined(USE_PREAD64)
  3117         -  do{ got = osPwrite64(id->h, pBuf, cnt, offset);}while( got<0 && errno==EINTR);
  3118         -#else
  3119         -  do{
  3120         -    newOffset = lseek(id->h, offset, SEEK_SET);
  3121         -    SimulateIOError( newOffset-- );
  3122         -    if( newOffset!=offset ){
  3123         -      if( newOffset == -1 ){
  3124         -        ((unixFile*)id)->lastErrno = errno;
  3125         -      }else{
  3126         -        ((unixFile*)id)->lastErrno = 0;
  3127         -      }
  3128         -      return -1;
  3129         -    }
  3130         -    got = osWrite(id->h, pBuf, cnt);
  3131         -  }while( got<0 && errno==EINTR );
  3132         -#endif
  3133         -  TIMER_END;
  3134         -  if( got<0 ){
  3135         -    ((unixFile*)id)->lastErrno = errno;
  3136         -  }
  3137         -
  3138         -  OSTRACE(("WRITE   %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED));
  3139         -  return got;
         3251  +  return seekAndWriteFd(id->h, offset, pBuf, cnt, &id->lastErrno);
  3140   3252   }
  3141   3253   
  3142   3254   
  3143   3255   /*
  3144   3256   ** Write data from a buffer into a file.  Return SQLITE_OK on success
  3145   3257   ** or some other error code on failure.
  3146   3258   */
................................................................................
  3179   3291         SimulateIOErrorBenign(1);
  3180   3292         rc = seekAndRead(pFile, 24, oldCntr, 4);
  3181   3293         SimulateIOErrorBenign(0);
  3182   3294         if( rc!=4 || memcmp(oldCntr, &((char*)pBuf)[24-offset], 4)!=0 ){
  3183   3295           pFile->transCntrChng = 1;  /* The transaction counter has changed */
  3184   3296         }
  3185   3297       }
         3298  +  }
         3299  +#endif
         3300  +
         3301  +#if SQLITE_MAX_MMAP_SIZE>0
         3302  +  /* Deal with as much of this write request as possible by transfering
         3303  +  ** data from the memory mapping using memcpy().  */
         3304  +  if( offset<pFile->mmapSize ){
         3305  +    if( offset+amt <= pFile->mmapSize ){
         3306  +      memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
         3307  +      return SQLITE_OK;
         3308  +    }else{
         3309  +      int nCopy = pFile->mmapSize - offset;
         3310  +      memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy);
         3311  +      pBuf = &((u8 *)pBuf)[nCopy];
         3312  +      amt -= nCopy;
         3313  +      offset += nCopy;
         3314  +    }
  3186   3315     }
  3187   3316   #endif
  3188   3317   
  3189   3318     while( amt>0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt))>0 ){
  3190   3319       amt -= wrote;
  3191   3320       offset += wrote;
  3192   3321       pBuf = &((char*)pBuf)[wrote];
................................................................................
  3409   3538     SimulateIOError( rc=1 );
  3410   3539     if( rc ){
  3411   3540       pFile->lastErrno = errno;
  3412   3541       return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath);
  3413   3542     }
  3414   3543   
  3415   3544     /* Also fsync the directory containing the file if the DIRSYNC flag
  3416         -  ** is set.  This is a one-time occurrance.  Many systems (examples: AIX)
         3545  +  ** is set.  This is a one-time occurrence.  Many systems (examples: AIX)
  3417   3546     ** are unable to fsync a directory, so ignore errors on the fsync.
  3418   3547     */
  3419   3548     if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
  3420   3549       int dirfd;
  3421   3550       OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath,
  3422   3551               HAVE_FULLFSYNC, isFullsync));
  3423   3552       rc = osOpenDirectory(pFile->zPath, &dirfd);
................................................................................
  3463   3592       ** when restoring a database using the backup API from a zero-length
  3464   3593       ** source.
  3465   3594       */
  3466   3595       if( pFile->inNormalWrite && nByte==0 ){
  3467   3596         pFile->transCntrChng = 1;
  3468   3597       }
  3469   3598   #endif
         3599  +
         3600  +    /* If the file was just truncated to a size smaller than the currently
         3601  +    ** mapped region, reduce the effective mapping size as well. SQLite will
         3602  +    ** use read() and write() to access data beyond this point from now on.  
         3603  +    */
         3604  +    if( nByte<pFile->mmapSize ){
         3605  +      pFile->mmapSize = nByte;
         3606  +    }
  3470   3607   
  3471   3608       return SQLITE_OK;
  3472   3609     }
  3473   3610   }
  3474   3611   
  3475   3612   /*
  3476   3613   ** Determine the current size of a file in bytes
................................................................................
  3551   3688           int nWrite = seekAndWrite(pFile, iWrite, "", 1);
  3552   3689           if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
  3553   3690           iWrite += nBlk;
  3554   3691         }
  3555   3692   #endif
  3556   3693       }
  3557   3694     }
         3695  +
         3696  +  if( pFile->mmapSizeMax>0 && nByte>pFile->mmapSize ){
         3697  +    int rc;
         3698  +    if( pFile->szChunk<=0 ){
         3699  +      if( robust_ftruncate(pFile->h, nByte) ){
         3700  +        pFile->lastErrno = errno;
         3701  +        return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
         3702  +      }
         3703  +    }
         3704  +
         3705  +    rc = unixMapfile(pFile, nByte);
         3706  +    return rc;
         3707  +  }
  3558   3708   
  3559   3709     return SQLITE_OK;
  3560   3710   }
  3561   3711   
  3562   3712   /*
  3563   3713   ** If *pArg is inititially negative then this is a query.  Set *pArg to
  3564   3714   ** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
................................................................................
  3618   3768       case SQLITE_FCNTL_TEMPFILENAME: {
  3619   3769         char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
  3620   3770         if( zTFile ){
  3621   3771           unixGetTempname(pFile->pVfs->mxPathname, zTFile);
  3622   3772           *(char**)pArg = zTFile;
  3623   3773         }
  3624   3774         return SQLITE_OK;
         3775  +    }
         3776  +    case SQLITE_FCNTL_MMAP_SIZE: {
         3777  +      i64 newLimit = *(i64*)pArg;
         3778  +      if( newLimit>sqlite3GlobalConfig.mxMmap ){
         3779  +        newLimit = sqlite3GlobalConfig.mxMmap;
         3780  +      }
         3781  +      *(i64*)pArg = pFile->mmapSizeMax;
         3782  +      if( newLimit>=0 ){
         3783  +        pFile->mmapSizeMax = newLimit;
         3784  +        if( newLimit<pFile->mmapSize ) pFile->mmapSize = newLimit;
         3785  +      }
         3786  +      return SQLITE_OK;
  3625   3787       }
  3626   3788   #ifdef SQLITE_DEBUG
  3627   3789       /* The pager calls this method to signal that it has done
  3628   3790       ** a rollback and that the database is therefore unchanged and
  3629   3791       ** it hence it is OK for the transaction change counter to be
  3630   3792       ** unchanged.
  3631   3793       */
................................................................................
  3931   4093     assert( unixMutexHeld() );
  3932   4094     if( p && p->nRef==0 ){
  3933   4095       int i;
  3934   4096       assert( p->pInode==pFd->pInode );
  3935   4097       sqlite3_mutex_free(p->mutex);
  3936   4098       for(i=0; i<p->nRegion; i++){
  3937   4099         if( p->h>=0 ){
  3938         -        munmap(p->apRegion[i], p->szRegion);
         4100  +        osMunmap(p->apRegion[i], p->szRegion);
  3939   4101         }else{
  3940   4102           sqlite3_free(p->apRegion[i]);
  3941   4103         }
  3942   4104       }
  3943   4105       sqlite3_free(p->apRegion);
  3944   4106       if( p->h>=0 ){
  3945   4107         robust_close(pFd, p->h, __LINE__);
................................................................................
  4171   4333           rc = SQLITE_IOERR_SHMSIZE;
  4172   4334           goto shmpage_out;
  4173   4335         }
  4174   4336     
  4175   4337         if( sStat.st_size<nByte ){
  4176   4338           /* The requested memory region does not exist. If bExtend is set to
  4177   4339           ** false, exit early. *pp will be set to NULL and SQLITE_OK returned.
  4178         -        **
  4179         -        ** Alternatively, if bExtend is true, use ftruncate() to allocate
  4180         -        ** the requested memory region.
  4181   4340           */
  4182         -        if( !bExtend ) goto shmpage_out;
  4183         -#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
  4184         -        if( osFallocate(pShmNode->h, sStat.st_size, nByte)!=0 ){
  4185         -          rc = unixLogError(SQLITE_IOERR_SHMSIZE, "fallocate",
  4186         -                            pShmNode->zFilename);
         4341  +        if( !bExtend ){
  4187   4342             goto shmpage_out;
  4188   4343           }
  4189         -#else
  4190         -        if( robust_ftruncate(pShmNode->h, nByte) ){
  4191         -          rc = unixLogError(SQLITE_IOERR_SHMSIZE, "ftruncate",
  4192         -                            pShmNode->zFilename);
  4193         -          goto shmpage_out;
         4344  +
         4345  +        /* Alternatively, if bExtend is true, extend the file. Do this by
         4346  +        ** writing a single byte to the end of each (OS) page being
         4347  +        ** allocated or extended. Technically, we need only write to the
         4348  +        ** last page in order to extend the file. But writing to all new
         4349  +        ** pages forces the OS to allocate them immediately, which reduces
         4350  +        ** the chances of SIGBUS while accessing the mapped region later on.
         4351  +        */
         4352  +        else{
         4353  +          static const int pgsz = 4096;
         4354  +          int iPg;
         4355  +
         4356  +          /* Write to the last byte of each newly allocated or extended page */
         4357  +          assert( (nByte % pgsz)==0 );
         4358  +          for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){
         4359  +            if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, 0)!=1 ){
         4360  +              const char *zFile = pShmNode->zFilename;
         4361  +              rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile);
         4362  +              goto shmpage_out;
         4363  +            }
         4364  +          }
  4194   4365           }
  4195         -#endif
  4196   4366         }
  4197   4367       }
  4198   4368   
  4199   4369       /* Map the requested memory region into this processes address space. */
  4200   4370       apNew = (char **)sqlite3_realloc(
  4201   4371           pShmNode->apRegion, (iRegion+1)*sizeof(char *)
  4202   4372       );
................................................................................
  4204   4374         rc = SQLITE_IOERR_NOMEM;
  4205   4375         goto shmpage_out;
  4206   4376       }
  4207   4377       pShmNode->apRegion = apNew;
  4208   4378       while(pShmNode->nRegion<=iRegion){
  4209   4379         void *pMem;
  4210   4380         if( pShmNode->h>=0 ){
  4211         -        pMem = mmap(0, szRegion,
         4381  +        pMem = osMmap(0, szRegion,
  4212   4382               pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, 
  4213   4383               MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
  4214   4384           );
  4215   4385           if( pMem==MAP_FAILED ){
  4216   4386             rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
  4217   4387             goto shmpage_out;
  4218   4388           }
................................................................................
  4420   4590   
  4421   4591   #else
  4422   4592   # define unixShmMap     0
  4423   4593   # define unixShmLock    0
  4424   4594   # define unixShmBarrier 0
  4425   4595   # define unixShmUnmap   0
  4426   4596   #endif /* #ifndef SQLITE_OMIT_WAL */
         4597  +
         4598  +/*
         4599  +** If it is currently memory mapped, unmap file pFd.
         4600  +*/
         4601  +static void unixUnmapfile(unixFile *pFd){
         4602  +  assert( pFd->nFetchOut==0 );
         4603  +#if SQLITE_MAX_MMAP_SIZE>0
         4604  +  if( pFd->pMapRegion ){
         4605  +    osMunmap(pFd->pMapRegion, pFd->mmapSizeActual);
         4606  +    pFd->pMapRegion = 0;
         4607  +    pFd->mmapSize = 0;
         4608  +    pFd->mmapSizeActual = 0;
         4609  +  }
         4610  +#endif
         4611  +}
         4612  +
         4613  +#if SQLITE_MAX_MMAP_SIZE>0
         4614  +/*
         4615  +** Return the system page size.
         4616  +*/
         4617  +static int unixGetPagesize(void){
         4618  +#if HAVE_MREMAP
         4619  +  return 512;
         4620  +#elif defined(_BSD_SOURCE)
         4621  +  return getpagesize();
         4622  +#else
         4623  +  return (int)sysconf(_SC_PAGESIZE);
         4624  +#endif
         4625  +}
         4626  +#endif /* SQLITE_MAX_MMAP_SIZE>0 */
         4627  +
         4628  +#if SQLITE_MAX_MMAP_SIZE>0
         4629  +/*
         4630  +** Attempt to set the size of the memory mapping maintained by file 
         4631  +** descriptor pFd to nNew bytes. Any existing mapping is discarded.
         4632  +**
         4633  +** If successful, this function sets the following variables:
         4634  +**
         4635  +**       unixFile.pMapRegion
         4636  +**       unixFile.mmapSize
         4637  +**       unixFile.mmapSizeActual
         4638  +**
         4639  +** If unsuccessful, an error message is logged via sqlite3_log() and
         4640  +** the three variables above are zeroed. In this case SQLite should
         4641  +** continue accessing the database using the xRead() and xWrite()
         4642  +** methods.
         4643  +*/
         4644  +static void unixRemapfile(
         4645  +  unixFile *pFd,                  /* File descriptor object */
         4646  +  i64 nNew                        /* Required mapping size */
         4647  +){
         4648  +  const char *zErr = "mmap";
         4649  +  int h = pFd->h;                      /* File descriptor open on db file */
         4650  +  u8 *pOrig = (u8 *)pFd->pMapRegion;   /* Pointer to current file mapping */
         4651  +  i64 nOrig = pFd->mmapSizeActual;     /* Size of pOrig region in bytes */
         4652  +  u8 *pNew = 0;                        /* Location of new mapping */
         4653  +  int flags = PROT_READ;               /* Flags to pass to mmap() */
         4654  +
         4655  +  assert( pFd->nFetchOut==0 );
         4656  +  assert( nNew>pFd->mmapSize );
         4657  +  assert( nNew<=pFd->mmapSizeMax );
         4658  +  assert( nNew>0 );
         4659  +  assert( pFd->mmapSizeActual>=pFd->mmapSize );
         4660  +  assert( MAP_FAILED!=0 );
         4661  +
         4662  +  if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;
         4663  +
         4664  +  if( pOrig ){
         4665  +    const int szSyspage = unixGetPagesize();
         4666  +    i64 nReuse = (pFd->mmapSize & ~(szSyspage-1));
         4667  +    u8 *pReq = &pOrig[nReuse];
         4668  +
         4669  +    /* Unmap any pages of the existing mapping that cannot be reused. */
         4670  +    if( nReuse!=nOrig ){
         4671  +      osMunmap(pReq, nOrig-nReuse);
         4672  +    }
         4673  +
         4674  +#if HAVE_MREMAP
         4675  +    pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE);
         4676  +    zErr = "mremap";
         4677  +#else
         4678  +    pNew = osMmap(pReq, nNew-nReuse, flags, MAP_SHARED, h, nReuse);
         4679  +    if( pNew!=MAP_FAILED ){
         4680  +      if( pNew!=pReq ){
         4681  +        osMunmap(pNew, nNew - nReuse);
         4682  +        pNew = 0;
         4683  +      }else{
         4684  +        pNew = pOrig;
         4685  +      }
         4686  +    }
         4687  +#endif
         4688  +
         4689  +    /* The attempt to extend the existing mapping failed. Free it. */
         4690  +    if( pNew==MAP_FAILED || pNew==0 ){
         4691  +      osMunmap(pOrig, nReuse);
         4692  +    }
         4693  +  }
         4694  +
         4695  +  /* If pNew is still NULL, try to create an entirely new mapping. */
         4696  +  if( pNew==0 ){
         4697  +    pNew = osMmap(0, nNew, flags, MAP_SHARED, h, 0);
         4698  +  }
         4699  +
         4700  +  if( pNew==MAP_FAILED ){
         4701  +    pNew = 0;
         4702  +    nNew = 0;
         4703  +    unixLogError(SQLITE_OK, zErr, pFd->zPath);
         4704  +
         4705  +    /* If the mmap() above failed, assume that all subsequent mmap() calls
         4706  +    ** will probably fail too. Fall back to using xRead/xWrite exclusively
         4707  +    ** in this case.  */
         4708  +    pFd->mmapSizeMax = 0;
         4709  +  }
         4710  +  pFd->pMapRegion = (void *)pNew;
         4711  +  pFd->mmapSize = pFd->mmapSizeActual = nNew;
         4712  +}
         4713  +#endif
         4714  +
         4715  +/*
         4716  +** Memory map or remap the file opened by file-descriptor pFd (if the file
         4717  +** is already mapped, the existing mapping is replaced by the new). Or, if 
         4718  +** there already exists a mapping for this file, and there are still 
         4719  +** outstanding xFetch() references to it, this function is a no-op.
         4720  +**
         4721  +** If parameter nByte is non-negative, then it is the requested size of 
         4722  +** the mapping to create. Otherwise, if nByte is less than zero, then the 
         4723  +** requested size is the size of the file on disk. The actual size of the
         4724  +** created mapping is either the requested size or the value configured 
         4725  +** using SQLITE_FCNTL_MMAP_LIMIT, whichever is smaller.
         4726  +**
         4727  +** SQLITE_OK is returned if no error occurs (even if the mapping is not
         4728  +** recreated as a result of outstanding references) or an SQLite error
         4729  +** code otherwise.
         4730  +*/
         4731  +static int unixMapfile(unixFile *pFd, i64 nByte){
         4732  +#if SQLITE_MAX_MMAP_SIZE>0
         4733  +  i64 nMap = nByte;
         4734  +  int rc;
         4735  +
         4736  +  assert( nMap>=0 || pFd->nFetchOut==0 );
         4737  +  if( pFd->nFetchOut>0 ) return SQLITE_OK;
         4738  +
         4739  +  if( nMap<0 ){
         4740  +    struct stat statbuf;          /* Low-level file information */
         4741  +    rc = osFstat(pFd->h, &statbuf);
         4742  +    if( rc!=SQLITE_OK ){
         4743  +      return SQLITE_IOERR_FSTAT;
         4744  +    }
         4745  +    nMap = statbuf.st_size;
         4746  +  }
         4747  +  if( nMap>pFd->mmapSizeMax ){
         4748  +    nMap = pFd->mmapSizeMax;
         4749  +  }
         4750  +
         4751  +  if( nMap!=pFd->mmapSize ){
         4752  +    if( nMap>0 ){
         4753  +      unixRemapfile(pFd, nMap);
         4754  +    }else{
         4755  +      unixUnmapfile(pFd);
         4756  +    }
         4757  +  }
         4758  +#endif
         4759  +
         4760  +  return SQLITE_OK;
         4761  +}
         4762  +
         4763  +/*
         4764  +** If possible, return a pointer to a mapping of file fd starting at offset
         4765  +** iOff. The mapping must be valid for at least nAmt bytes.
         4766  +**
         4767  +** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
         4768  +** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
         4769  +** Finally, if an error does occur, return an SQLite error code. The final
         4770  +** value of *pp is undefined in this case.
         4771  +**
         4772  +** If this function does return a pointer, the caller must eventually 
         4773  +** release the reference by calling unixUnfetch().
         4774  +*/
         4775  +static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
         4776  +#if SQLITE_MAX_MMAP_SIZE>0
         4777  +  unixFile *pFd = (unixFile *)fd;   /* The underlying database file */
         4778  +#endif
         4779  +  *pp = 0;
         4780  +
         4781  +#if SQLITE_MAX_MMAP_SIZE>0
         4782  +  if( pFd->mmapSizeMax>0 ){
         4783  +    if( pFd->pMapRegion==0 ){
         4784  +      int rc = unixMapfile(pFd, -1);
         4785  +      if( rc!=SQLITE_OK ) return rc;
         4786  +    }
         4787  +    if( pFd->mmapSize >= iOff+nAmt ){
         4788  +      *pp = &((u8 *)pFd->pMapRegion)[iOff];
         4789  +      pFd->nFetchOut++;
         4790  +    }
         4791  +  }
         4792  +#endif
         4793  +  return SQLITE_OK;
         4794  +}
         4795  +
         4796  +/*
         4797  +** If the third argument is non-NULL, then this function releases a 
         4798  +** reference obtained by an earlier call to unixFetch(). The second
         4799  +** argument passed to this function must be the same as the corresponding
         4800  +** argument that was passed to the unixFetch() invocation. 
         4801  +**
         4802  +** Or, if the third argument is NULL, then this function is being called 
         4803  +** to inform the VFS layer that, according to POSIX, any existing mapping 
         4804  +** may now be invalid and should be unmapped.
         4805  +*/
         4806  +static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
         4807  +  unixFile *pFd = (unixFile *)fd;   /* The underlying database file */
         4808  +  UNUSED_PARAMETER(iOff);
         4809  +
         4810  +  /* If p==0 (unmap the entire file) then there must be no outstanding 
         4811  +  ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
         4812  +  ** then there must be at least one outstanding.  */
         4813  +  assert( (p==0)==(pFd->nFetchOut==0) );
         4814  +
         4815  +  /* If p!=0, it must match the iOff value. */
         4816  +  assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] );
         4817  +
         4818  +  if( p ){
         4819  +    pFd->nFetchOut--;
         4820  +  }else{
         4821  +    unixUnmapfile(pFd);
         4822  +  }
         4823  +
         4824  +  assert( pFd->nFetchOut>=0 );
         4825  +  return SQLITE_OK;
         4826  +}
  4427   4827   
  4428   4828   /*
  4429   4829   ** Here ends the implementation of all sqlite3_file methods.
  4430   4830   **
  4431   4831   ********************** End sqlite3_file Methods *******************************
  4432   4832   ******************************************************************************/
  4433   4833   
................................................................................
  4479   4879      CKLOCK,                     /* xCheckReservedLock */                      \
  4480   4880      unixFileControl,            /* xFileControl */                            \
  4481   4881      unixSectorSize,             /* xSectorSize */                             \
  4482   4882      unixDeviceCharacteristics,  /* xDeviceCapabilities */                     \
  4483   4883      unixShmMap,                 /* xShmMap */                                 \
  4484   4884      unixShmLock,                /* xShmLock */                                \
  4485   4885      unixShmBarrier,             /* xShmBarrier */                             \
  4486         -   unixShmUnmap                /* xShmUnmap */                               \
         4886  +   unixShmUnmap,               /* xShmUnmap */                               \
         4887  +   unixFetch,                  /* xFetch */                                  \
         4888  +   unixUnfetch,                /* xUnfetch */                                \
  4487   4889   };                                                                           \
  4488   4890   static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){   \
  4489   4891     UNUSED_PARAMETER(z); UNUSED_PARAMETER(p);                                  \
  4490   4892     return &METHOD;                                                            \
  4491   4893   }                                                                            \
  4492   4894   static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p)    \
  4493   4895       = FINDER##Impl;
................................................................................
  4496   4898   ** Here are all of the sqlite3_io_methods objects for each of the
  4497   4899   ** locking strategies.  Functions that return pointers to these methods
  4498   4900   ** are also created.
  4499   4901   */
  4500   4902   IOMETHODS(
  4501   4903     posixIoFinder,            /* Finder function name */
  4502   4904     posixIoMethods,           /* sqlite3_io_methods object name */
  4503         -  2,                        /* shared memory is enabled */
         4905  +  3,                        /* shared memory and mmap are enabled */
  4504   4906     unixClose,                /* xClose method */
  4505   4907     unixLock,                 /* xLock method */
  4506   4908     unixUnlock,               /* xUnlock method */
  4507   4909     unixCheckReservedLock     /* xCheckReservedLock method */
  4508   4910   )
  4509   4911   IOMETHODS(
  4510   4912     nolockIoFinder,           /* Finder function name */
................................................................................
  4747   5149     assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );
  4748   5150   
  4749   5151     OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
  4750   5152     pNew->h = h;
  4751   5153     pNew->pVfs = pVfs;
  4752   5154     pNew->zPath = zFilename;
  4753   5155     pNew->ctrlFlags = (u8)ctrlFlags;
         5156  +  pNew->mmapSizeMax = sqlite3GlobalConfig.mxMmap;
  4754   5157     if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
  4755   5158                              "psow", SQLITE_POWERSAFE_OVERWRITE) ){
  4756   5159       pNew->ctrlFlags |= UNIXFILE_PSOW;
  4757   5160     }
  4758   5161     if( strcmp(pVfs->zName,"unix-excl")==0 ){
  4759   5162       pNew->ctrlFlags |= UNIXFILE_EXCL;
  4760   5163     }
................................................................................
  4783   5186   #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
  4784   5187       || pLockingStyle == &nfsIoMethods
  4785   5188   #endif
  4786   5189     ){
  4787   5190       unixEnterMutex();
  4788   5191       rc = findInodeInfo(pNew, &pNew->pInode);
  4789   5192       if( rc!=SQLITE_OK ){
  4790         -      /* If an error occured in findInodeInfo(), close the file descriptor
         5193  +      /* If an error occurred in findInodeInfo(), close the file descriptor
  4791   5194         ** immediately, before releasing the mutex. findInodeInfo() may fail
  4792   5195         ** in two scenarios:
  4793   5196         **
  4794   5197         **   (a) A call to fstat() failed.
  4795   5198         **   (b) A malloc failed.
  4796   5199         **
  4797   5200         ** Scenario (b) may only occur if the process is holding no other
................................................................................
  4882   5285     
  4883   5286     pNew->lastErrno = 0;
  4884   5287   #if OS_VXWORKS
  4885   5288     if( rc!=SQLITE_OK ){
  4886   5289       if( h>=0 ) robust_close(pNew, h, __LINE__);
  4887   5290       h = -1;
  4888   5291       osUnlink(zFilename);
  4889         -    isDelete = 0;
         5292  +    pNew->ctrlFlags |= UNIXFILE_DELETE;
  4890   5293     }
  4891         -  if( isDelete ) pNew->ctrlFlags |= UNIXFILE_DELETE;
  4892   5294   #endif
  4893   5295     if( rc!=SQLITE_OK ){
  4894   5296       if( h>=0 ) robust_close(pNew, h, __LINE__);
  4895   5297     }else{
  4896   5298       pNew->pMethod = pLockingStyle;
  4897   5299       OpenCounter(+1);
         5300  +    verifyDbFile(pNew);
  4898   5301     }
  4899   5302     return rc;
  4900   5303   }
  4901   5304   
  4902   5305   /*
  4903   5306   ** Return the name of a directory in which to put temporary files.
  4904   5307   ** If no suitable temporary file directory can be found, return NULL.
................................................................................
  5421   5824       }
  5422   5825     }
  5423   5826   #endif
  5424   5827     return rc;
  5425   5828   }
  5426   5829   
  5427   5830   /*
  5428         -** Test the existance of or access permissions of file zPath. The
         5831  +** Test the existence of or access permissions of file zPath. The
  5429   5832   ** test performed depends on the value of flags:
  5430   5833   **
  5431   5834   **     SQLITE_ACCESS_EXISTS: Return 1 if the file exists
  5432   5835   **     SQLITE_ACCESS_READWRITE: Return 1 if the file is read and writable.
  5433   5836   **     SQLITE_ACCESS_READONLY: Return 1 if the file is readable.
  5434   5837   **
  5435   5838   ** Otherwise return 0.
................................................................................
  6984   7387       UNIXVFS("unix-proxy",    proxyIoFinder ),
  6985   7388   #endif
  6986   7389     };
  6987   7390     unsigned int i;          /* Loop counter */
  6988   7391   
  6989   7392     /* Double-check that the aSyscall[] array has been constructed
  6990   7393     ** correctly.  See ticket [bb3a86e890c8e96ab] */
  6991         -  assert( ArraySize(aSyscall)==21 );
         7394  +  assert( ArraySize(aSyscall)==24 );
  6992   7395   
  6993   7396     /* Register all VFSes defined in the aVfs[] array */
  6994   7397     for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
  6995   7398       sqlite3_vfs_register(&aVfs[i], i==0);
  6996   7399     }
  6997   7400     return SQLITE_OK; 
  6998   7401   }

Changes to src/os_win.c.

   146    146   #if SQLITE_OS_WINCE
   147    147     LPWSTR zDeleteOnClose;  /* Name of file to delete when closing */
   148    148     HANDLE hMutex;          /* Mutex used to control access to shared lock */  
   149    149     HANDLE hShared;         /* Shared memory segment used for locking */
   150    150     winceLock local;        /* Locks obtained by this instance of winFile */
   151    151     winceLock *shared;      /* Global shared lock memory for the file  */
   152    152   #endif
          153  +#if SQLITE_MAX_MMAP_SIZE>0
          154  +  int nFetchOut;                /* Number of outstanding xFetch references */
          155  +  HANDLE hMap;                  /* Handle for accessing memory mapping */
          156  +  void *pMapRegion;             /* Area memory mapped */
          157  +  sqlite3_int64 mmapSize;       /* Usable size of mapped region */
          158  +  sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */
          159  +  sqlite3_int64 mmapSizeMax;    /* Configured FCNTL_MMAP_SIZE value */
          160  +#endif
   153    161   };
   154    162   
   155    163   /*
   156    164   ** Allowed values for winFile.ctrlFlags
   157    165   */
          166  +#define WINFILE_RDONLY          0x02   /* Connection is read only */
   158    167   #define WINFILE_PERSIST_WAL     0x04   /* Persistent WAL mode */
   159    168   #define WINFILE_PSOW            0x10   /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
   160    169   
   161    170   /*
   162    171    * The size of the buffer used by sqlite3_win32_write_debug().
   163    172    */
   164    173   #ifndef SQLITE_WIN32_DBG_BUF_SIZE
................................................................................
   304    313   /*
   305    314   ** Many system calls are accessed through pointer-to-functions so that
   306    315   ** they may be overridden at runtime to facilitate fault injection during
   307    316   ** testing and sandboxing.  The following array holds the names and pointers
   308    317   ** to all overrideable system calls.
   309    318   */
   310    319   static struct win_syscall {
   311         -  const char *zName;            /* Name of the sytem call */
          320  +  const char *zName;            /* Name of the system call */
   312    321     sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
   313    322     sqlite3_syscall_ptr pDefault; /* Default value */
   314    323   } aSyscall[] = {
   315    324   #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
   316    325     { "AreFileApisANSI",         (SYSCALL)AreFileApisANSI,         0 },
   317    326   #else
   318    327     { "AreFileApisANSI",         (SYSCALL)0,                       0 },
................................................................................
  1510   1519         sqlite3EndBenignMalloc();
  1511   1520         /* free the system buffer allocated by FormatMessage */
  1512   1521         osLocalFree(zTemp);
  1513   1522       }
  1514   1523     }
  1515   1524   #endif
  1516   1525     if( 0 == dwLen ){
  1517         -    sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", lastErrno, lastErrno);
         1526  +    sqlite3_snprintf(nBuf, zBuf, "OsError 0x%lx (%lu)", lastErrno, lastErrno);
  1518   1527     }else{
  1519   1528       /* copy a maximum of nBuf chars to output buffer */
  1520   1529       sqlite3_snprintf(nBuf, zBuf, "%s", zOut);
  1521   1530       /* free the UTF8 buffer */
  1522   1531       sqlite3_free(zOut);
  1523   1532     }
  1524   1533     return 0;
................................................................................
  1553   1562     zMsg[0] = 0;
  1554   1563     getLastErrorMsg(lastErrno, sizeof(zMsg), zMsg);
  1555   1564     assert( errcode!=SQLITE_OK );
  1556   1565     if( zPath==0 ) zPath = "";
  1557   1566     for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){}
  1558   1567     zMsg[i] = 0;
  1559   1568     sqlite3_log(errcode,
  1560         -      "os_win.c:%d: (%d) %s(%s) - %s",
         1569  +      "os_win.c:%d: (%lu) %s(%s) - %s",
  1561   1570         iLine, lastErrno, zFunc, zPath, zMsg
  1562   1571     );
  1563   1572   
  1564   1573     return errcode;
  1565   1574   }
  1566   1575   
  1567   1576   /*
................................................................................
  2014   2023   static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
  2015   2024   #if !SQLITE_OS_WINRT
  2016   2025     LONG upperBits;                 /* Most sig. 32 bits of new offset */
  2017   2026     LONG lowerBits;                 /* Least sig. 32 bits of new offset */
  2018   2027     DWORD dwRet;                    /* Value returned by SetFilePointer() */
  2019   2028     DWORD lastErrno;                /* Value returned by GetLastError() */
  2020   2029   
         2030  +  OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset));
         2031  +
  2021   2032     upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
  2022   2033     lowerBits = (LONG)(iOffset & 0xffffffff);
  2023   2034   
  2024   2035     /* API oddity: If successful, SetFilePointer() returns a dword 
  2025   2036     ** containing the lower 32-bits of the new file-offset. Or, if it fails,
  2026   2037     ** it returns INVALID_SET_FILE_POINTER. However according to MSDN, 
  2027   2038     ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine 
  2028         -  ** whether an error has actually occured, it is also necessary to call 
         2039  +  ** whether an error has actually occurred, it is also necessary to call 
  2029   2040     ** GetLastError().
  2030   2041     */
  2031   2042     dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
  2032   2043   
  2033   2044     if( (dwRet==INVALID_SET_FILE_POINTER
  2034   2045         && ((lastErrno = osGetLastError())!=NO_ERROR)) ){
  2035   2046       pFile->lastErrno = lastErrno;
  2036   2047       winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
  2037   2048                "seekWinFile", pFile->zPath);
         2049  +    OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
  2038   2050       return 1;
  2039   2051     }
  2040   2052   
         2053  +  OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
  2041   2054     return 0;
  2042   2055   #else
  2043   2056     /*
  2044   2057     ** Same as above, except that this implementation works for WinRT.
  2045   2058     */
  2046   2059   
  2047   2060     LARGE_INTEGER x;                /* The new offset */
................................................................................
  2050   2063     x.QuadPart = iOffset;
  2051   2064     bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN);
  2052   2065   
  2053   2066     if(!bRet){
  2054   2067       pFile->lastErrno = osGetLastError();
  2055   2068       winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
  2056   2069                "seekWinFile", pFile->zPath);
         2070  +    OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
  2057   2071       return 1;
  2058   2072     }
  2059   2073   
         2074  +  OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
  2060   2075     return 0;
  2061   2076   #endif
  2062   2077   }
         2078  +
         2079  +#if SQLITE_MAX_MMAP_SIZE>0
         2080  +/* Forward references to VFS methods */
         2081  +static int winUnmapfile(winFile*);
         2082  +#endif
  2063   2083   
  2064   2084   /*
  2065   2085   ** Close a file.
  2066   2086   **
  2067   2087   ** It is reported that an attempt to close a handle might sometimes
  2068   2088   ** fail.  This is a very unreasonable result, but Windows is notorious
  2069   2089   ** for being unreasonable so I do not doubt that it might happen.  If
................................................................................
  2076   2096     int rc, cnt = 0;
  2077   2097     winFile *pFile = (winFile*)id;
  2078   2098   
  2079   2099     assert( id!=0 );
  2080   2100   #ifndef SQLITE_OMIT_WAL
  2081   2101     assert( pFile->pShm==0 );
  2082   2102   #endif
  2083         -  OSTRACE(("CLOSE %d\n", pFile->h));
  2084   2103     assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
         2104  +  OSTRACE(("CLOSE file=%p\n", pFile->h));
         2105  +
         2106  +#if SQLITE_MAX_MMAP_SIZE>0
         2107  +  rc = winUnmapfile(pFile);
         2108  +  if( rc!=SQLITE_OK ) return rc;
         2109  +#endif
         2110  +
  2085   2111     do{
  2086   2112       rc = osCloseHandle(pFile->h);
  2087   2113       /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
  2088   2114     }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) );
  2089   2115   #if SQLITE_OS_WINCE
  2090   2116   #define WINCE_DELETION_ATTEMPTS 3
  2091   2117     winceDestroyLock(pFile);
................................................................................
  2097   2123           && cnt++ < WINCE_DELETION_ATTEMPTS
  2098   2124       ){
  2099   2125          sqlite3_win32_sleep(100);  /* Wait a little before trying again */
  2100   2126       }
  2101   2127       sqlite3_free(pFile->zDeleteOnClose);
  2102   2128     }
  2103   2129   #endif
  2104         -  OSTRACE(("CLOSE %d %s\n", pFile->h, rc ? "ok" : "failed"));
  2105   2130     if( rc ){
  2106   2131       pFile->h = NULL;
  2107   2132     }
  2108   2133     OpenCounter(-1);
         2134  +  OSTRACE(("CLOSE file=%p, rc=%s\n", pFile->h, rc ? "ok" : "failed"));
  2109   2135     return rc ? SQLITE_OK
  2110   2136               : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(),
  2111   2137                             "winClose", pFile->zPath);
  2112   2138   }
  2113   2139   
  2114   2140   /*
  2115   2141   ** Read data from a file into a buffer.  Return SQLITE_OK if all
................................................................................
  2126   2152     OVERLAPPED overlapped;          /* The offset for ReadFile. */
  2127   2153   #endif
  2128   2154     winFile *pFile = (winFile*)id;  /* file handle */
  2129   2155     DWORD nRead;                    /* Number of bytes actually read from file */
  2130   2156     int nRetry = 0;                 /* Number of retrys */
  2131   2157   
  2132   2158     assert( id!=0 );
         2159  +  assert( amt>0 );
         2160  +  assert( offset>=0 );
  2133   2161     SimulateIOError(return SQLITE_IOERR_READ);
  2134         -  OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));
         2162  +  OSTRACE(("READ file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n",
         2163  +           pFile->h, pBuf, amt, offset, pFile->locktype));
         2164  +
         2165  +#if SQLITE_MAX_MMAP_SIZE>0
         2166  +  /* Deal with as much of this read request as possible by transfering
         2167  +  ** data from the memory mapping using memcpy().  */
         2168  +  if( offset<pFile->mmapSize ){
         2169  +    if( offset+amt <= pFile->mmapSize ){
         2170  +      memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
         2171  +      OSTRACE(("READ-MMAP file=%p, rc=SQLITE_OK\n", pFile->h));
         2172  +      return SQLITE_OK;
         2173  +    }else{
         2174  +      int nCopy = (int)(pFile->mmapSize - offset);
         2175  +      memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy);
         2176  +      pBuf = &((u8 *)pBuf)[nCopy];
         2177  +      amt -= nCopy;
         2178  +      offset += nCopy;
         2179  +    }
         2180  +  }
         2181  +#endif
  2135   2182   
  2136   2183   #if SQLITE_OS_WINCE
  2137   2184     if( seekWinFile(pFile, offset) ){
         2185  +    OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h));
  2138   2186       return SQLITE_FULL;
  2139   2187     }
  2140   2188     while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
  2141   2189   #else
  2142   2190     memset(&overlapped, 0, sizeof(OVERLAPPED));
  2143   2191     overlapped.Offset = (LONG)(offset & 0xffffffff);
  2144   2192     overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
  2145   2193     while( !osReadFile(pFile->h, pBuf, amt, &nRead, &overlapped) &&
  2146   2194            osGetLastError()!=ERROR_HANDLE_EOF ){
  2147   2195   #endif
  2148   2196       DWORD lastErrno;
  2149   2197       if( retryIoerr(&nRetry, &lastErrno) ) continue;
  2150   2198       pFile->lastErrno = lastErrno;
         2199  +    OSTRACE(("READ file=%p, rc=SQLITE_IOERR_READ\n", pFile->h));
  2151   2200       return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
  2152   2201                "winRead", pFile->zPath);
  2153   2202     }
  2154   2203     logIoerr(nRetry);
  2155   2204     if( nRead<(DWORD)amt ){
  2156   2205       /* Unread parts of the buffer must be zero-filled */
  2157   2206       memset(&((char*)pBuf)[nRead], 0, amt-nRead);
         2207  +    OSTRACE(("READ file=%p, rc=SQLITE_IOERR_SHORT_READ\n", pFile->h));
  2158   2208       return SQLITE_IOERR_SHORT_READ;
  2159   2209     }
  2160   2210   
         2211  +  OSTRACE(("READ file=%p, rc=SQLITE_OK\n", pFile->h));
  2161   2212     return SQLITE_OK;
  2162   2213   }
  2163   2214   
  2164   2215   /*
  2165   2216   ** Write data from a buffer into a file.  Return SQLITE_OK on success
  2166   2217   ** or some other error code on failure.
  2167   2218   */
  2168   2219   static int winWrite(
  2169   2220     sqlite3_file *id,               /* File to write into */
  2170   2221     const void *pBuf,               /* The bytes to be written */
  2171   2222     int amt,                        /* Number of bytes to write */
  2172   2223     sqlite3_int64 offset            /* Offset into the file to begin writing at */
  2173   2224   ){
  2174         -  int rc = 0;                     /* True if error has occured, else false */
         2225  +  int rc = 0;                     /* True if error has occurred, else false */
  2175   2226     winFile *pFile = (winFile*)id;  /* File handle */
  2176   2227     int nRetry = 0;                 /* Number of retries */
  2177   2228   
  2178   2229     assert( amt>0 );
  2179   2230     assert( pFile );
  2180   2231     SimulateIOError(return SQLITE_IOERR_WRITE);
  2181   2232     SimulateDiskfullError(return SQLITE_FULL);
  2182   2233   
  2183         -  OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype));
         2234  +  OSTRACE(("WRITE file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n",
         2235  <